1. 數(shù)據(jù)模型:其實是對 Python 框架的描述噪伊,它規(guī)范了這門語言自身構(gòu)建模塊
的接口囚戚,這些模塊包括但不限于序列窿锉、迭代器酌摇、函數(shù)、類和上下文管理器嗡载。
Python 解釋器碰到特殊的句法時窑多,會使用特殊方法去激活一些基本的對象操作,這些特殊方法的名字以兩個下
劃線開頭洼滚,以兩個下劃線結(jié)尾埂息;
這些特殊方法名能讓你自己的對象實現(xiàn)和支持以下的語言構(gòu)架,并與之交互:
* 迭代
* 集合類
* 屬性訪問
* 運算符重載
* 函數(shù)和方法的調(diào)用
* 對象的創(chuàng)建和銷毀
* 字符串表示形式和格式化
* 管理上下文(即 with 塊)
案例:
import collections
'''
collections.namedtuple用以構(gòu)建只有少數(shù)屬性但是沒有方法的對象;
命名元組為元組中的每個位置賦予意義,并允許使用更可讀的自文檔化代碼千康。它們可以在使用
常規(guī)元組的任何地方使用享幽,并且它們添加了按名稱而不是位置索引訪問字段的能力。
返回名為typename的新元組子類吧秕。新的子類用于創(chuàng)建類元組的對象琉闪,這些對象具有可通過屬性查找訪問的字段以及可索引和可iterable迹炼。
'''
Card=collections.namedtuple('Card',['rank','suit'])
beer_card = Card('7', 'diamonds')
例:
# 定義撲克類
class FrenchDeck:
? ? ranks = [str(n) for n in range(2, 11)] + list('JQKA')
? ? suits = 'spades diamonds clubs hearts'.split()
? ? def __init__(self):
? ? ? ? self._cards = [Card(rank, suit) for suit in self.suits
? ? ? ? for rank in self.ranks]
? ? def __len__(self):
? ? ? ? return len(self._cards)
? ? def __getitem__(self, position):
? ? ? ? return self._cards[position]
# 從一疊牌中抽取特定的一張紙牌
# __getitem__ 方法把 [] 操作交給了 self._cards 列表
# 用 len() 函數(shù)來查看一疊牌有多少張:
deck = FrenchDeck()
len(deck)
# Python 內(nèi)置了從一個序列中隨機選出一個元素的函數(shù) random.choice
from random import choice
t=choice(deck)
# 實現(xiàn)了 __getitem__ 方法砸彬,這一摞牌就變成可迭代的了
for c in deck:
? ? print(c)
# 反向迭代, doctest: +ELLIPSIS 過長的內(nèi)容就會被如上面例子的最后一行的省略號(...)所替代
for card in reversed(deck):# doctest: +ELLIPSIS
? ? print(card)
# 一個集合類型沒有實現(xiàn) __contains__ 方法,那么 in 運算符就會按順序做一次迭代搜索斯入。
Card('Q', 'hearts') in deck
例:
# 按照常規(guī)砂碉,用點數(shù)來判定撲克牌的大小,2 最小刻两、A
# 最大增蹭;同時還要加上對花色的判定,黑桃最大磅摹、紅桃次之滋迈、方塊再次、梅花最小户誓。
suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
def spades_high(card):
? ? rank_value = FrenchDeck.ranks.index(card.rank)
? ? return rank_value * len(suit_values) + suit_values[card.suit]
# 有了 spades_high 函數(shù)饼灿,就能對這摞牌進行升序排序了
for card in sorted(deck, key=spades_high): # doctest: +ELLIPSIS
? ? print(card)
2 重寫符號
from math import hypot
class Vector:
? ? def __init__(self, x=0, y=0):
? ? ? ? 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 __bool__(self):
? ? ? ? return bool(abs(self))
? ? def __add__(self, other):
? ? ? ? x = self.x + other.x
? ? ? ? y = self.y + other.y
? ? ? ? return Vector(x, y)
? ? def __mul__(self, scalar):
? ? ? ? return Vector(self.x * scalar, self.y * scalar)
調(diào)用
v1 = Vector(2, 4)
v2 = Vector(2, 1)
v1+v2
v = Vector(3, 4)
abs(v)
例:字符串函數(shù)
內(nèi)置的函數(shù)叫 repr,它能把一個對象用字符串的形式表達出來以便辨認帝美,這就是“字符串表示形式”
# __repr__ 和 __str__ 的區(qū)別在于碍彭,后者是在 str() 函數(shù)被使用,或是在用 print 函數(shù)打印一個對象的時候才被調(diào)用的悼潭,并且它返回的字
# 符串對終端用戶更友好庇忌。
class Tea:
? ? def __repr__(self):
? ? ? ? return "我是一個repr"
#? ? def __str__(self):
#? ? ? ? return "我是一個str"
t=Tea()
print(t)