python 数据模型

魔术方法

python 中的魔术方法以 __ 开头和结尾,例如:__len____getitem__ 等,详细的列表可以参考 Data model
这些特殊方法能够让你自己的对象实现和支持以下的语言构架,并与之交互:

  • 迭代
  • 集合类
  • 属性访问
  • 运算符重载
  • 函数和方法的的调用
  • 对象的创建和销毁
  • 字符串的表示形式和格式化
  • 管理上下文(即 with 块)

隐式调用

特殊方法的存在是为了被 python 解释器隐式所调用,而不会被显示调用(除了 __init__),也就是应该使用 len(my_object) 的方式,而不会是 my_object.__len__ 的形式。
如果 my_object 是一个自定义对象,python 解释器也会直接调用实现的 __len__ 方法。
如果my_object 是一个 python 内置对象,CPython 会直接抄近路,__len__ 会直接返回 PyVarObject 里的 ob_size 属性,直接读取这个值比调用一个方法要快很多。PyVarObject 是表示内存长度可变的内置对象的 C 语言结构体。

for i in range x 这一句其实调用的是 iter(x) 函数,这个函数其实又是调用 x.__iter__() 方法。

repr() 函数可以把一个对象用字符串的形式表示出来,这个函数实际上调用的是 __repr__ 方法。类似的 str() 函数调用的是 __str__() 方法。

+ 调用 __add__() 方法,* 调用 __mul__() 方法。

bool(x) 调用的是 x.__bool__() 方法,如果 __bool__() 方法不存在,则会调用 __len__() 方法。

实现一个纸牌类

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import collections

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

if __name__ == "__main__":
    deck = FrenchDeck()
    # 计算纸牌数量
    print(len(deck))
    
    # 使用索引
    print(deck[0])
    print(deck[-1])
    
    # 随机抽取
    from random import choice
    print(choice(deck))
    
    print(Card('Q', 'hearts') in deck)

通过实现 __len____getitem__ 两个特殊方法,使得自定义类 FrenchDeck 具有了和 python 内建序列类型数据一样的迭代和索引特性。

实现一个二维向量类

#!/usr/bin/python
# -*- coding: UTF-8 -*-

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)
    

if __name__ == "__main__":
    v1 = Vector(2,4)
    v2 = Vector(1,5)

    print(v1 + v2)

    v3 = Vector(3,4)
    print(abs(v3))
    
    v4 = v3 * 10
    print(v4)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值