1. 程式人生 > >fluent python筆記——資料模型

fluent python筆記——資料模型

資料模型

python最好的品質之一就是一致性,當使用python工作一會兒之後,就可以正確的猜出語句的意思。而這都歸功於python的資料模型。

資料模型其實是對python框架的描述,它規範了這門語言自身 構建模組 的介面,這些模組包括序列、迭代器、函式、類和上下文管理器。

python直譯器遇到特殊句法時,會使用特殊方法啟用物件的基本操作,這些特殊方法的格式為:__xxx__。比如obj[key]背後的方法其實是呼叫了obj.__getitem__(key)

這種特殊方法,可以使我們自己的物件,實現和支援以下的語言框架,並與之互動:迭代、集合類、屬性訪問、運算子過載、函式和方法呼叫、物件建立和銷燬、字串表示形式和格式化、管理上下文。

一、一副紙牌

接下來以實現一摞紙牌的例子,來展示如何實現__getitem____len__這兩個特殊方法,見識到特殊方法的強大。

import collections
from random import choice

Card = namedTuple('Card',['rank', 'suit'])    # 定義型別Card

class CardGenerator(object):
    ranks = [str(n) for n in range(2,11) + list('JQKA')]
    suits = 'spades diamonds clubs hearts'
.split() def __init__(self): self._card = [Card(rank, suit) for suit in self.suits for rank in self.ranks] def __len__(self): return self.len(_card) def __getitem__(self,pos): return self._card[pos] obj = CardGenerator() print(len(obj)) # 獲取長度
print(obj[0]) # 獲取第一張牌 print(obj[-5:-3]) # 切片 print(choice(obj)) # 隨機獲取一張牌 print(obj[12::13]) # 先抽索引為12的那張牌,之後每13張抽一張牌 for card in reversed(obj): # 反向遍歷 print(card)

首先,我們定義了一個有些像C結構體的型別Card,用來描述一張牌。然後,定義了CardGenerator類,用來描述一副紙牌。

我們都知道,自定義型別在沒有過載運算子的情況下,不能夠輸入輸出,不能夠用標準庫中的方法,更不可以迭代。而CardGenerator類,巧妙的運用了列表和定義特殊方法,只用了幾行程式碼就使CardGenerator物件變成了一個,可獲取長度的、可訪問的、可迭代的、可以使用標準庫方法的物件。

suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
def card_weight(card):
    rank_values = CardGenerator.ranks.index(card.rank)
    return rank_values * len(suit_values) + suit_values[card.suit]

for card in sorted(obj,key=card_weight):
    print card

在定義了每張牌的權值之後,也可以通過呼叫sorted函式對其進行排序。

二、如何使用特殊方法

首先我們需要明確,特殊方法的存在是為了python直譯器呼叫的,而不是我們自己呼叫。就比如上述程式碼中的len(obj),實際上是直譯器呼叫了由我們自己實現的 CardGenerator類中的__len__()特殊方法。

而對於python的內建型別如:list、str、bytearray等,len(list)實際上不會呼叫__len__(),而是會抄近路去呼叫,由C語言實現的PyVarObject結構體中的ob_size屬性。直接呼叫這個屬性會比呼叫函式快很多哦~

一般而言,許多特殊方法都是隱式呼叫的,比如for i in obj:這個語句,其實隱式的呼叫了obj.__iter__()特殊方法。並且大多數特殊方法是通過len、str這些內建函式呼叫的。

對於熟悉C++的各位,可以把python的特殊方法理解為虛擬函式

1. 模擬數值型別

我們通過實現一個二維向量類Vector來看一看數值型別是如何定義的。

from math import hypot   # 引入取模函式

class Vector2(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Vector(%r, %r)' % (self.x, self.y)

    def __abs__(self):      # 取模
        return hypot(self.x, self.y)

    def __add__(self, other):
        return Vector2(self.x + other.x, self.y + other.y)

    def __mul__(self, scalar):
        return Vector2(self.x * scalar, self.y * scalar)

    def __bool__(self):
        return bool(abs(self))

首先,值得一提的是,我們定義了__repr__()方法,該方法返回一個物件的字串以描述這個物件。在沒有定義這個方法之前,我們在控制檯輸入print(Vector2(1, 2))會得到物件的地址,而不是輸出物件的內容。在定義了這個特殊方法之後,輸入同樣內容,在沒有定義__str__()的情況下,直譯器會呼叫repr()內建函式,而repr內建函式則會呼叫物件的__repr__()方法。

之後,我們還定義了__bool__()方法,當我們呼叫bool()函式時,__bool__()特殊方法便會被呼叫。對於一個新的數值型別,難免會在條件語句中進行判斷,因此__bool__()方法必不可少。當我們需要一個型別的bool值時,python直譯器首先會看該型別內有沒有__bool__()方法,如果沒有則會根據__len__()方法的返回值確定bool值。

3. 總結

  • 特殊方法是為了使自定義型別表現的與內建型別一樣而存在的。
  • 特殊方法是python直譯器呼叫的,基本不需要自行呼叫
  • 特殊方法的呼叫棧一般為:某函式->直譯器自動呼叫內建函式->內建函式呼叫特殊方法

關於str與repr

class test(object):
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return 'test(%r)' % (self.val)

a = test(10)

a
>>> <__main__.a at 0x7fa91c314e50>
print(a)
>>> test(10)


class test(object):
    def __init__(self, val):
        self.val = val
    def __repr__(self):
        return 'test(%r)' % (self.val) 

a = test(10)

a
>>> test(10)
print(a)
>>> test(10)

可以看出,對於__str__()而言,輸入物件名並不執行該函式,輸出的依然是物件地址,輸入print時才會執行。

當我們輸入print(obj)時,python直譯器首先呼叫str()內建函式,str()呼叫__str__()特殊方法。

如果當前類沒有定義__str__()特殊方法,那麼直譯器會呼叫repr()內建函式,呼叫__repr__()特殊方法。

可以看出,str是處於外層的,repr是處於底層的,若是定義了__str__()__repr__()會被覆蓋。因此,str一般面向使用者,而repr面向程式設計師。

相關推薦

fluent python筆記——資料模型

資料模型 python最好的品質之一就是一致性,當使用python工作一會兒之後,就可以正確的猜出語句的意思。而這都歸功於python的資料模型。 資料模型其實是對python框架的描述,它規範了這門語言自身 構建模組 的介面,這些模組包括序列、迭代器、函式

MongoDB學習筆記~資料模型屬性為集合時應該為它初始化

回到目錄 今天要說一下技術點,我們在設計mongodb的資料模型時,如果屬性是陣列或者集合型別,我們在模型初始化時,需要為它們初始化一下,否則在資料庫裡將會被儲存為NULL,當被儲存為NULL時,我們將無法進行元件的push,pull等操作。 之間在設計模型時沒有注意這點,然後產生的問題就是,沒有被集合賦

《流暢的python》讀書筆記,第一章:python資料模型

這本書上來就講了魔法方法,也叫雙下方法、特殊方法,通過兩個例子對讓讀者瞭解了雙下方法的用法,更重要的是,讓我一窺Python的語言風格和給使用者的自由度。 第一個例子:一摞Python風格的紙牌: import collections Card = collections.namedtuple

【caffe學習筆記之7】caffe-matlab/python訓練LeNet模型並應用於mnist資料集(2)

【案例介紹】 LeNet網路模型是一個用來識別手寫數字的最經典的卷積神經網路,是Yann LeCun在1998年設計並提出的,是早期卷積神經網路中最有代表性的實驗系統之一,其論文是CNN領域第一篇經典之作。本篇部落格詳細介紹基於Matlab、Python訓練lenet手

《流暢的python》學習筆記 - python資料模型

  python資料模型,就是對python語言框架的描述,規範了這門語言自身構建模組的介面。   每次都要提醒自己,python是面向物件的,要用面向物件的方法來思考問題。 私有和被保護的屬性 類的私有屬性:兩個下劃線開頭(簡稱dunder),宣告該屬性為私有,不能在物件(

流暢的python 學習筆記Python資料模型

python和其他語言大不相同的是,python具有自己的‘’python風格‘’如在python中的len(collection)在其他語言中可能是collection.len( ).這種設計思想完全體現在python的資料模型上,而資料模型所描述的API為使用最地道的語言

[讀書筆記]流暢的PythonFluent Python

python基礎 政府 基本 管理 map ocs fis tactic 機會 《流暢的Python》這本書是圖靈科技翻譯出版的一本書,作者Luciano Ramalho。 作者從Python的特性角度出發,以Python的數據模型和特殊方法為主線,主要介紹了python的

python筆記-基本資料型別

數字型別及操作: 1.pow(x,y)冪次運算 2.浮點數運算時存在不確定尾數,可用round函式進行四捨五入: round(x,d):對x四捨五入,d是小數擷取位數 e:科學計數法:比如:4.3e-3 3.複數型別【進行空間變換和複變函式中使用,平時很少使用】 4.數值運算操作符 +,—,

python初級資料結構(list,tuple,dict)(補充筆記,初級)

List: 遞推式構造列表(List Comprehension),例: list = [x*2 for x in lm] 切片list[start: stop: step] sort 和 sorted: sort會改變list(in-place),而sorted返回排序好的列表(retu

python筆記之基礎資料型別

八大基礎資料型別 int python 中沒有溢位,再大的值也可以用int num = 10 num++ 報錯,num只是儲存資料10的容器,容器不可以自增自減 print(num) # 列印容器中存放的值10 地址 print(id(num)) # id

筆記1:利用python進行資料分析

#筆記1:利用python進行資料分析 numpy模組,各種函式等等 因為不想使用編碼軟體,所以直接文字編輯器,cmd執行結果; 提一個小技巧:cmd中複製資訊操作,右擊–》標記–》選擇需要複製的資訊(一般為白色背景)–》在複製區外右擊,之後在需要的地方-》ctrl+v 就可以了; 直

易學筆記-系統分析師考試-第5章 資料庫系統/5.2 資料模型/5.2.3 規範化理論

錯誤關係模式舉例:關係模式R(學生姓名,選修的課程名,任課老師,任課老師地址) 資料冗餘:不同學生的任課老師資料可能重複 修改異常:修改了一個一條記錄的任課老師地址後,其它同一個老師的地址都要修改 插入異常:如果不知道學生姓名,那麼任課老師的資訊就無法插入資料庫

易學筆記-系統分析師考試-第5章 資料庫系統/5.2 資料模型/5.2.2 關係模型

關係模式表示 關係表示為:R(A1,A2,A3,...An),其中R為關係名,A為屬性名 R可以理解為資料表,R的關係是靜態的,A的值是動態的 關係運算 並:指的是兩個關係在集合上的並集,表示為 差:指的是兩個關係區別的集合,表示為:

易學筆記-系統分析師考試-第5章 資料庫系統/5.2 資料模型/5.2.1 資料模式的分類

資料模式 概念:是對現實世界問題的抽象、然後轉換到計算機進行分析和解決 內容包括三部分: 資料結構:是資料模型的基礎 ,描述資料的型別、內容、性質和資料間的聯絡等 資料操作:主要描述在相應資料結構上的操作型別和操作方法 資料約束:描述的

利用Python進行資料分析閱讀筆記(一)

資料規整化:清理,轉換,合併,重塑 轉置(transpose)     實現的幾種方式:  import numpy as np arr = np.arange(15).reshape((3,5)) print(arr) print(arr.T) pri

廖雪峰Python筆記[1] - 運算和資料結構

目錄   1 輸入輸出 2 布林運算 3 四則運算 4 list和tuple  5 dict和set 1 輸入輸出        輸出:逗號被空格代替,print也可以進行簡單的計算,字串前加r表示不轉義

Python資料科學入門》 讀書筆記第四章 2018-8-2011:30開始

接著看這本書。。看到第三章的時候,腦闊又疼了。用的時候再說吧,而且R軟體功能很強大。蹦過去了。 接著到了第四章。我一想說第四章講的線性代數。。我特麼高等代數都學過還看這個幹嘛啊。 又到了第五章,將統計,我說真巧,我就是統計專業的。 又到了第六章,一看,哇概率論,他咋知道我的專業是概率論與

python資料科學入門》學習筆記第二章 2018-8-17開始

昨天早晨發現新買不到一週的自行車被偷了,我的2000大洋啊,心在滴血,小偷我草你媽,去學校安保處與派出所報警也花了一上午,下午接到朋友電話,被告知那個她找了新的男朋友,生活真是日了狗了。苟延殘喘。 經過三個來月的python程式設計,雖然能夠寫一些複雜的演算法。但是編寫速度很慢,原因是基本功不紮

Python學習筆記-資料分析-Numpy01

Numpy是Python開源的科學計算工具包,主要的特點如下: 強大的N維陣列物件:ndarray 對陣列結構資料進行運算(不用遍歷迴圈) 隨機數、線性代數、傅立葉變換等多種功能 說明:

Python學習筆記-資料分析-Numpy02-通用函式

Numpy通用函式 一、陣列形狀— —.T/.reshape()和.resize()** 1、numpy.T :轉置,例如原shape為(3,4)/(2,3,4),轉置結果為(4,3)/(4,3,2)