文章导读:
1. 了解Python数据模型是什么
2. Python常见特殊方法示例

数据模型其实是对Python框架的描述,它规范了这门语言自身构架模块的接口,这些模块包括但不限于序列、迭代器、函数、类和上下文管理器。简单来说,数据模型就是Python自身的数据类型,及其包含的特殊方法。这些特殊方法在Java中也被成为‘魔术方法’

如len(object)调用了__len__特殊方法,list[]调用了__getitem__方法。从根本来说,这些特殊方法能让你的对象实现和支持与迭代、集合、属性访问、运算符、函数和方法、对象创建与销毁、字符串以及管理上下文的语言框架。list[]、+、-、*、/、for i in x这些写法是为了更简介和更具有可读性,实际都是通过特殊方法实现的。

特殊方法一览

python 开发的模型部署为什么这么大 python模型有哪些_Python


python 开发的模型部署为什么这么大 python模型有哪些_scala_02

如何调用特殊方法

  1. 特殊方法的调用是隐式的,通常你的代码无需直接使用特殊方法。除非有大量的元编程存在,直接调用特殊方法的频率应该远远低于你去实现它们的次数。唯一的例外可能是__init__方法,你的代码里可能经常会用到它,目的是在你的子类的__init__方法中调用超类的构造器。
  2. 通过内置的函数(例如len、iter、str等)来使用特殊方法是最好的选择。这些内置函数不仅会调用特殊方法,通常还提供额外的好处,而且对于内置的类来说,它们的速度更快。
  3. 不要自己想当然地随意添加特殊方法,比如_foo_之类的,因为虽然现在这个名字没有被python内部使用,以后就不一定了。

部分示例

__len__

class Test:
    def __len__(self): #重写__len__方法
        return 1

if __name__=="__main__":
   t = Test()
   print(len(t)) #输出为1

__getitem__

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 rank in self.ranks
                       for suit in self.suits]

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

if __name__=="__main__":
    deck = FrenchDeck()
    print(deck[0]) #使用deck[0]时会调用__getitem__方法,解释器会将0传递给__getitem__(self, item)中的item参数
    print(deck[1:4]) #使用切片操作时也会调用__getitem__方法,解释器会传递slice(1, 4, None)item参数

__repr__、__str__、__abs__、__add__、__mul__、__bool__

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 __str__(self):  # 如果类中同时有__str__和__repr__,则调用print是会先使用__str__
        return "Vector(%r,%r)" % (self.x,self.y)

    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    def __abs__(self):  # abs本来是绝对值,在二维向量中指模
        return hypot(self.x, self.y) #返回三角形的斜边

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

    def __bool__(self):
        return bool(abs(self))



if __name__ == "__main__":
    v = Vector(3,4)
    print(v)    #返回Vector(3,4)
    if v:
        print(abs(v)) #返回5.0
    v2 = Vector(1,2)
    print(v * 3)    #返回Vector(9,12)
    print(v + v2)   #返回Vector(4,6)

__repr__和__str__的区别在于,后者是在str()函数中被使用,或是在用print打印函数打印一个对象的时候才被调用。如果你只想实现这两个特殊方法中的一个,__repr__是更好的选择,因为如果一个对象没有__str__函数,而python又需要调用它的时候,解释器会用__repr__作为代替。
因此在使用print()函数时,解释器会按照__str__,__repr__的顺序寻找

———————————————-文章来源于对《流畅的Python》学习