zoukankan      html  css  js  c++  java
  • 流畅的Python (Fluent Python) —— 第一部分

    Python 最好的品质之一是一致性。
    魔术方法(magic method)是特殊方法的昵称。特殊方法也叫双下方法。

    1.1 一摞Python风格的纸牌 

     1 import collections
     2 Card = collections.namedtuple('Card', ['rank', 'suit'])  # 创建了一个有名字的元组
     3 
     4 
     5 class FrenchDeck:  # 隐式继承了Object类
     6     ranks = [str(n) for n in range(2, 11)] + list('JQKA')  # 可选的序号
     7     suits = 'spades diamonds clubs hearts'.split()  # 可选的花色
     8 
     9     def __init__(self):  # 创建该类的对象时,会执行此方法
    10         self._cards = [Card(rank, suit) for suit in self.suits
    11                        for rank in self.ranks]
    12 
    13     def __len__(self):  # 调用 len(deck) 时,实际上是执行 len.__len__ 方法
    14         return len(self._cards)
    15 
    16     def __getitem__(self, position):  # 调用 deck[0] 时,实际上是执行 deck.__getitem__(key=0)
    17         return self._cards[position]
    18 
    19 
    20 deck = FrenchDeck()
    21 print(len(deck))  # 判断个数的定义,是由__len__实现的
    22 print(deck[0])  # 根据位置抽取,此方法是由__getitem__实现的

    通过实现特殊方法来利用 Python 数据模型的两个好处 :

    1. 作为你的类的用户,他们不必去记住标准操作的各式名称(怎么得到元素的总数? 是 .size() 还是 .length() 还是别的什么? )。
    2. 可以更加方便地利用 Python 的标准库,比如 random.choice 函数,从而不用重新发明轮子。

    同时,__getitem__ 方法把  [ ]  操作交给了 self._cards 列表,所以我们的 deck 类自动支持切片(slicing)操作。 另外,仅仅实现了 __getitem__ 方法,这一摞牌就变成可迭代的了 。

    迭代通常是隐式的,譬如说一个集合类型没有实现 __contains__ 方法,那么 in 运算符就会按顺序做一次迭代搜索。

    对牌堆进行排序:

     1 # 对牌堆排序
     2 suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
     3 
     4 
     5 def spades_high(card):
     6     rank_value = FrenchDeck.ranks.index(card.rank)
     7     '''
     8     card.rank:某张牌对象的rank属性(2-A),FrenchDeck.ranks.index(card.rank)返回该属性的位置
     9     len(suit_values): 花色的种类,也就是4
    10     suit_values[card.suit]: 就是根据某张牌对象的花色,取出该花色对应的值(权重)
    11     '''
    12     return rank_value * len(suit_values) + suit_values[card.suit]  # 返回这张排在牌堆中的序号(唯一)
    13 
    14 
    15 for card in sorted(deck, key=spades_high):
    16     print(card)

    如何洗牌

      按照目前的设计, FrenchDeck 是不能洗牌的,因为这摞牌是不可变的(immutable):卡牌和它们的位置都是固定的,除非我们破坏这个类的封装性,直接对 _cards 进行操作。第 11 章会讲到,其实只需要一行代码来实现 __setitem__方法,洗牌功能就不是问题了。

    1.2 如何使用特殊方法

      首先明确一点,特殊方法(双下方法)的存在是为了被 Python 解释器调用的,你自己并不需要调用它们。

      然而如果是 Python 内置的类型,比如列表(list)、字符串(str)、字节序列(bytearray)等,那么 CPython 会抄个近路, __len__ 实际上会直接返回 PyVarObject 里的 ob_size 属性。 PyVarObject 是表示内存中长度可变的内置对象的 C语言结构体。直接读取这个值比调用一个方法要快很多。
      很多时候,特殊方法的调用是隐式的,比如 for i in x: 这个语句,背后其实用的是iter(x),而这个函数的背后则是 x.__iter__() 方法。当然前提是这个方法在 x 中被实现了。
      通常你的代码无需直接使用特殊方法。除非有大量的元编程(meta programming)存在,直接调用特殊方法的频率应该远远低于你去实现它们的次数。唯一的例外可能是 __init__ 方法,你的代码里可能经常会用到它,目的是在你自己的子类的 __init__ 方法中调用超类的构造器。通过内置的函数(例如 leniterstr,等等)来使用特殊方法是最好的选择。这些内置函数不仅会调用特殊方法,通常还提供额外的好处,而且对于内置的类来说,它们的速度更快。 14.12 节中有详细的例子。不要自己想当然地随意添加特殊方法,因为虽然现在这个名字没有被 Python 内部使用,以后就不一定了。

     1 from math import hypot
     2 
     3 
     4 class Vector:
     5     def __init__(self, x=0, y=0):
     6         self.x = x
     7         self.y = y
     8 
     9     '''
    10     一个对象用字符串的形式表达出来以便辨认,如果没有实现 __repr__,当我们在控制台里打印一个向量的实例时,得到的字符串可能会是 <Vector object at 0x10e100070>。
    11     '''
    12     def __repr__(self):
    13         return 'Vector(%r, %r)' % (self.x, self.y)
    14     # __repr__方便我们调试和记录日志,
    15     # __str__是给终端用户用的
    16 
    17     def __abs__(self):
    18         return hypot(self.x, self.y)
    19 
    20     # 模是 0 就返回 False,其他返回 True
    21     def __bool__(self):
    22         # return bool(abs(self))
    23         return bool(self.x or self.y)  # 高效写法
    24 
    25     # + 操作
    26     def __add__(self, other):
    27         x = self.x + other.x
    28         y = self.y + other.y
    29         return Vector(x, y)
    30 
    31     # * 操作
    32     def __mul__(self, other):
    33         return Vector(self.x * other, self.y * other)

      如果一个对象没有 __str__ 函数,而 Python 又需要调用它的时候,解释器会用 __repr__ 作为替代。




      

  • 相关阅读:
    C# 添加敏感词
    C# 获取Get请求返回
    git使用之eclipse使用
    git使用之远程仓库(四)
    git使用之分支(三)
    git使用之创建仓库(二)
    git使用基本认识和配置(一)
    Thymeleaf 模板布局
    用Eclipse搭建第一个springboot应用
    前端鼠标点击弹出浮动文字--民主、和谐、爱国、自由等
  • 原文地址:https://www.cnblogs.com/shihaoyu/p/10465095.html
Copyright © 2011-2022 走看看