第一章 - Python数据模型

1.1  一摞Python风格的纸牌

知识点: collections.nametuple

import collections
from pprint import pprint

Card = collections.namedtuple("card", ("rank", "suit"))


class FrenchDeck(object):
    ranks = [str(n) for n in range(2, 11)] + list("JQKA")   # 字符串拼接“2345678910JQKA”
    suits = "spades diamonds clubs hearts".split()  # 四种花色 黑桃,方片,梅花,红心

    def __init__(self):
        self._cards = [Card(rank, suit)
                       for suit in self.suits
                       for rank in self.ranks]  # 利用列表生成式生成52张花色的扑克牌

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, position):
        return self._cards[position]


deck = FrenchDeck()
pprint(list(deck))

运行结果:

[card(rank='2', suit='spades'),
 card(rank='3', suit='spades'),
 card(rank='4', suit='spades'),
 card(rank='5', suit='spades'),
 card(rank='6', suit='spades'),
 card(rank='7', suit='spades'),
 card(rank='8', suit='spades'),
 card(rank='9', suit='spades'),
 card(rank='10', suit='spades'),
 card(rank='J', suit='spades'),
 card(rank='Q', suit='spades'),
 card(rank='K', suit='spades'),
 card(rank='A', suit='spades'),
 card(rank='2', suit='diamonds'),
 card(rank='3', suit='diamonds'),
 card(rank='4', suit='diamonds'),
 card(rank='5', suit='diamonds'),
 card(rank='6', suit='diamonds'),
 card(rank='7', suit='diamonds'),
 card(rank='8', suit='diamonds'),
 card(rank='9', suit='diamonds'),
 card(rank='10', suit='diamonds'),
 card(rank='J', suit='diamonds'),
 card(rank='Q', suit='diamonds'),
 card(rank='K', suit='diamonds'),
 card(rank='A', suit='diamonds'),
 card(rank='2', suit='clubs'),
 card(rank='3', suit='clubs'),
 card(rank='4', suit='clubs'),
 card(rank='5', suit='clubs'),
 card(rank='6', suit='clubs'),
 card(rank='7', suit='clubs'),
 card(rank='8', suit='clubs'),
 card(rank='9', suit='clubs'),
 card(rank='10', suit='clubs'),
 card(rank='J', suit='clubs'),
 card(rank='Q', suit='clubs'),
 card(rank='K', suit='clubs'),
 card(rank='A', suit='clubs'),
 card(rank='2', suit='hearts'),
 card(rank='3', suit='hearts'),
 card(rank='4', suit='hearts'),
 card(rank='5', suit='hearts'),
 card(rank='6', suit='hearts'),
 card(rank='7', suit='hearts'),
 card(rank='8', suit='hearts'),
 card(rank='9', suit='hearts'),
 card(rank='10', suit='hearts'),
 card(rank='J', suit='hearts'),
 card(rank='Q', suit='hearts'),
 card(rank='K', suit='hearts'),
 card(rank='A', suit='hearts')]
View Code

 

1.2  如何使用特殊方法

__len__方法: 如Python内置类型 list, str, bytearray 等, CPython会抄近路,__len__实际上会直接返回PyVarObject里的ob_size属性;PyVarObject是表示内存中长度可变的内置对象的C语言结构体, 直接读取这个值比调用一个方法要快很多。

很多时候,特殊方法的调用是隐式的,比如for i in x: 这个语句背后其实用的是iter(x), 而这个函数的背后则是x.__iter__()方法。

 

1.2.1 模拟数值类型

from math import hypot  # 计算直角三角形的斜边长


class Vector(object):

    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 __add__(self, other):  # 实现加法运算
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    def __mul__(self, other):
        return Vector(self.x * other, self.y * other)

    def __bool__(self):
        return bool(self.x or self.y)

v1 = Vector(2, 4)
v2 = Vector(2, 1)
print(v1 + v2)
v = Vector(3, 4)
print(abs(v))
print(v.__bool__())
print(v)

运行结果:

Vector(4, 5)
5.0
True
Vector(3, 4)

 

1.2.2 字符串表示形式

__repr__与__str__; repr是给机器看的,str是给人看的。

print(repr("0"))
>>>
'0'

print(str("0"))
>>>
0

__repr__返回的字符串应该准确、无歧义, 以方便我们调试和记录日志。

 

1.2.4 自定义的布尔值

默认情况下,我们自己定义的类的实例总是被认为是真的,除非这个类对__bool__或者__len__方法有自己的实现。 bool(x)的背后是调用 x.__bool__()的结果;如果不存在__bool__方法,那么boo(x)会尝试调用x.__len__()。若返回0,则bool会返回False,否则返回True.

class BoolTest(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __bool__(self):
        return True if self.x or self.y else False

    def __len__(self):
        return True

a = BoolTest(0, 0)
b = BoolTest(0, 1)
print(bool(a))
print(bool(b))

运行结果:
False
True

如果想让__bool__更高效,可以直接使用:

    def __bool__(self):
        return bool(self.x or self.y)


1.3 特殊方法一览表

 

posted @ 2017-07-17 22:40  Vincen_shen  阅读(247)  评论(0)    收藏  举报