Skip to content

Latest commit

 

History

History
143 lines (126 loc) · 5.21 KB

第一章 数据模型.md

File metadata and controls

143 lines (126 loc) · 5.21 KB

Python 数据模型

  • 数据模型是对Python框架的描述,它规范了这门语言自身构建模块的接口,这些模块不仅限于序列、迭代器、函数、类和上下文管理器。
  • Python解释器碰到特殊的句法时,会使用特殊方法去激活一些基本的对象操作,这些特殊方法一般以两个下划线开头,以两个下划线结尾(例如__getitem__)。
  • 魔术方法(magic method)是特殊方法的昵称。
__author__ = 'liuhui'

'''
实现__getitem__和__len__这两个特殊方法,写一个card.py
'''

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]

在控制台导入card

>>> import card                            
>>> deck = card.FrenchDeck()
>>> len(deck)
52
>>> deck[0]                #抽取特定的一张纸牌,比如第一张或最后一张,deck[0]或deck[-1]。这都是由__getitem__方法提供的
Card(rank='2', suit='spades')
>>> deck[-1]
Card(rank='A', suit='hearts')
>>> from random import choice        #导入python内置的从一个序列中随机选取一个元素的函数random.choice,随机选取deck实例的元素
>>> choice(deck)
Card(rank='7', suit='diamonds')
>>> choice(deck)
Card(rank='10', suit='diamonds')
>>> choice(deck)
Card(rank='7', suit='diamonds')
#因为__getitem__方法把[]操作交给了self._cards列表,所以deck类自动支持切片(slicing)操作。
>>> deck[:3]
[Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades')]
>>> deck[12:13]
[Card(rank='A', suit='spades')]
#另外,实现了__getitem__方法,这一副牌就变得可以迭代了
>>> for card in deck:
...     print(card)
... 
Card(rank='2', suit='spades')
Card(rank='3', suit='spades')
Card(rank='4', suit='spades')
Card(rank='5', suit='spades')
......
  • 如何使用特殊方法: 特殊方法是为了被Python解释器调用的,你自己并不需要调用它们。也就是说没有my_object.len()这种写法,而应该使用len(my_object)。在执行len(my_object)时,如果my_object是一个自定义类的对象,python会去调用由你实现的__len__方法。
  • 模拟数值类型: Python内置的complex类可以用来表示二维向量。
__author__ = 'liuhui'
'''
实现一个简单的二维向量类
'''

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)
>>> from vector import Vector
>>> v1 = Vector(2,4) 
>>> v2 = Vector(2,1)
>>> v1 + v2
Vector(4, 5)
>>> v = Vector(3,4)
>>> abs(v)
5.0
>>> v * 3
Vector(9, 12)
>>> abs(v * 3)
15.0
  • 字符串表示形式 Python有一个内置的函数叫repr,它能把一个对象用字符串的形式表达出来以便辨认,这就是'字符串表示形式'
>>> v.__repr__
<bound method Vector.__repr__ of Vector(3, 4)>
  • 特殊方法一览: 跟运算符无关的特殊方法
字符串/字节序列    __repr__、__str__、__format__、__bytes__
数值转换          __abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__
集合模拟           __len__、__getitem__、__setitem__、__delitem__、__contains__
迭代枚举           __iter__、__reversed__、__next__
可调用模拟         __call__
上下文管理         __enter__、__exit__
实例创建和销毁      __new__、__init__、__del__
属性管理           __getattr__、__getattribute__、__setattr__、__delattr__、__dir__
属性描述符         __get__、__set__、__delete__
跟类相关的服务      __prepare__、__instancecheck__、__subclasscheck__    

跟运算符相关的特殊方法

一元运算符         __neg__ -、__pos__ +、__abs__ abs()
众多比较运算符      __lt__ <、__le__ <=、__eq__ ==、__ne__ !=、__gt__ >、__ge__ >=
算术运算符         __add__ +、__sub__ -、__mul__ *、__truediv__ /、__floordiv__ //、__mod__ %、__divmod__ divmod()、__pow__ **或pow()、__round__ round()
反向算术运算符      __radd__、__rsub__、__rmul__、__rtruediv__、__rfloordiv__、__rmod__、__rdivmod__、__rpow__
增量赋值算术运算符  __iadd__、__isub__、__imul__、__itruediv__、__ifloordiv__、__imod__、__idivmod__、__ipow__
位运算符        __invert__ ~、__lshift__ <<、__rshift >>、__add__ &、__or__ |、__xor__ ^
反向位运算符    __rlshift__、__rrshift__、__rand__、__rxor__、__ror__
增量赋值位运算符 __ilshift__、__irshift__、__iand__、__ixor__、__ior__