Python特殊方法

《流畅的Python》

# 特殊方法
# 特殊方法的存在是为了被 Python 解释器调用的,你自己并不需要调用它们

# 然而如果是 Python 内置的类型,比如列表(list)、字符串(str)、字节序列(bytearray)
# 等,那么 CPython 会抄个近路,__len__ 实际上会直接返回 PyVarObject 里的 ob_size 属
# 性。PyVarObject 是表示内存中长度可变的内置对象的 C 语言结构体。直接读取这个值比
# 调用一个方法要快很多
import collections
from random import choice

# namedtuple 用来构建只有少数属性,没有方法的对象。比如数据库条目
Card = collections.namedtuple('Card', ['rank', 'suit'])


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, item):
        return self._cards[item]


deck = FrenchDeck()
# 因为 __getitem__ 方法把 [] 操作交给了 self._cards 列表,所以我们的 deck 类自动支持切片(slicing)操作
print(deck[12::13])
choice(deck)
# 另外,仅仅实现了 __getitem__ 方法,这一摞牌就变成可迭代的了
for card in deck: # doctest: +ELLIPSIS
    print(card)
# 迭代通常是隐式的,譬如说一个集合类型没有实现 __contains__ 方法,那么 in 运算符就会按顺序做一次迭代搜索。
print(Card('Q', 'hearts') in deck)

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]


for card in sorted(deck, key=spades_high):
    print(card)

# 在测试(doctest)中,如果可能的输出过长的话,那么过长的
# 内容就会被如上面例子的最后一行的省略号(...)所替代。此时就需要
# #doctest: +ELLIPSIS 这个指令来保证 doctest 能够通过。
# 模拟数值类型
from math import hypot

class Vector:

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

    # 交互式控制台和调试程序(debugger)用 repr 函数来获取字符串表示形式
    # __repr__ 和 __str__ 的区别在于,后者是在 str() 函数被使用,或是在用 print 函数打印一个对象的时候才被调用的,并且它返回的字符串对终端用户更友好
    def __repr__(self):
        return 'Vector(%r, %r)' % (self.x, self.y)

    def __abs__(self):
        # 求平方和开根
        return hypot(self.x, self.y)

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

    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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值