目录 | 上一节 (4.2 继承) | [下一节 (4.4 异样)]()

4.3 非凡办法

能够通过非凡办法(或者称为"魔术"办法(magic method))自定义 Python 行为的各局部。本节介绍非凡办法的思维。此外,还将探讨动静属性拜访和绑定办法。

简介

类能够定义非凡办法。非凡办法对于 Python 解释器而言具备非凡的意义。非凡办法总是以双下划线 __ 结尾和结尾,例如 __init__

class Stock(object):    def __init__(self):        ...    def __repr__(self):        ...

尽管有很多非凡办法,然而咱们只钻研几个具体的例子。

字符串转换的非凡办法

对象有两种字符串示意模式。

>>> from datetime import date>>> d = date(2012, 12, 21)>>> print(d)2012-12-21>>> ddatetime.date(2012, 12, 21)>>>

str() 函数用于创立格局良好的、可打印的输入:

>>> str(d)'2012-12-21'>>>

repr() 函数用于创立具体的、面向程序员的输入。

>>> repr(d)'datetime.date(2012, 12, 21)'>>>

str()repr() 函数都是应用类中定义的非凡办法生成要显示的字符串。

class Date(object):    def __init__(self, year, month, day):        self.year = year        self.month = month        self.day = day    # Used with `str()`    def __str__(self):        return f'{self.year}-{self.month}-{self.day}'    # Used with `repr()`    def __repr__(self):        return f'Date({self.year},{self.month},{self.day})'

留神:依照常规,__repr__() 返回一个字符串,当该字符串被传递给 eval() 函数,将会从新创立底层对象(译注:eval(repr(obj)) == obj)。如果不行,则应用某种易于浏览的表现形式。

数学操作的非凡办法

数学运算符波及的非凡办法如下:

a + b       a.__add__(b)a - b       a.__sub__(b)a * b       a.__mul__(b)a / b       a.__truediv__(b)a // b      a.__floordiv__(b)a % b       a.__mod__(b)a << b      a.__lshift__(b)a >> b      a.__rshift__(b)a & b       a.__and__(b)a | b       a.__or__(b)a ^ b       a.__xor__(b)a ** b      a.__pow__(b)-a          a.__neg__()~a          a.__invert__()abs(a)      a.__abs__()

元素拜访的非凡办法

这些是实现容器的非凡办法:

len(x)      x.__len__()x[a]        x.__getitem__(a)x[a] = v    x.__setitem__(a,v)del x[a]    x.__delitem__(a)

你能够在类中应用这些非凡办法。

class Sequence:    def __len__(self):        ...    def __getitem__(self,a):        ...    def __setitem__(self,a,v):        ...    def __delitem__(self,a):        ...

办法调用

调用办法有两个步骤。

1、查找:. 运算符

2、办法调用: () 运算符

>>> s = Stock('GOOG',100,490.10)>>> c = s.cost  # Lookup>>> c<bound method Stock.cost of <Stock object at 0x590d0>>>>> c()         # Method call49010.0>>>

绑定办法

尚未被函数调用运算符 () 调用的办法称为绑定办法( 译注:bound method,如果直译应该译作“绑定的办法”,然而,就像“类办法”一样,能够省略“的”这个字,译为“绑定办法”,绑定在这里不是动词,而应了解为形容词“绑定的”)。它对本人生成的实例进行操作:

>>> s = Stock('GOOG', 100, 490.10)>>> s<Stock object at 0x590d0>>>> c = s.cost>>> c<bound method Stock.cost of <Stock object at 0x590d0>>>>> c()49010.0>>>

如果应用绑定办法时有些粗心,那么容易导致谬误。示例:

>>> s = Stock('GOOG', 100, 490.10)>>> print('Cost : %0.2f' % s.cost)Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: float argument required>>>

或者:

f = open(filename, 'w')...f.close     # Oops, Didn't do anything at all. `f` still open.

在这两种情景中,谬误都是由遗记尾部括号引起的。例如:s.cost() or f.close()

属性拜访

还有一种拜访、操作和治理属性的代替办法。

getattr(obj, 'name')          # Same as obj.namesetattr(obj, 'name', value)   # Same as obj.name = valuedelattr(obj, 'name')          # Same as del obj.namehasattr(obj, 'name')          # Tests if attribute exists

示例:

if hasattr(obj, 'x'):    x = getattr(obj, 'x'):else:    x = None

留神: getattr() 函数的默认参数十分有用。

x = getattr(obj, 'x', None)

练习

练习 4.9:更好的输入

请批改 stock.py 文件中定义的 Stock 对象,以便 __repr__() 办法生成更有用的输入。示例:

>>> goog = Stock('GOOG', 100, 490.1)>>> googStock('GOOG', 100, 490.1)>>>

批改实现后,请查看读取股票投资组合时会产生什么,以及生成什么样的后果。示例:

>>> import report>>> portfolio = report.read_portfolio('Data/portfolio.csv')>>> portfolio... see what the output is ...>>>

练习 4.10:应用 getattr() 的例子

getattr() 是读取属性的另一种机制。能够应用它编写极其灵便的代码。首先,请尝试以下示例:

>>> import stock>>> s = stock.Stock('GOOG', 100, 490.1)>>> columns = ['name', 'shares']>>> for colname in columns:        print(colname, '=', getattr(s, colname))name = GOOGshares = 100>>>

仔细观察会发现输入数据齐全由 columns 变量中列出的属性名决定。

tableformat.py 文件中,应用该思维将其扩大为通用函数 print_table()print_table()打印一个表格,显示用户指定的任意对象的属性。与晚期的 print_report() 函数一样,print_table() 办法还应承受一个 TableFormatter 实例来管制输入格局。它们的工作形式如下:

>>> import report>>> portfolio = report.read_portfolio('Data/portfolio.csv')>>> from tableformat import create_formatter, print_table>>> formatter = create_formatter('txt')>>> print_table(portfolio, ['name','shares'], formatter)      name     shares---------- ----------        AA        100       IBM         50       CAT        150      MSFT        200        GE         95      MSFT         50       IBM        100>>> print_table(portfolio, ['name','shares','price'], formatter)      name     shares      price---------- ---------- ----------        AA        100       32.2       IBM         50       91.1       CAT        150      83.44      MSFT        200      51.23        GE         95      40.37      MSFT         50       65.1       IBM        100      70.44>>>

目录 | 上一节 (4.2 继承) | [下一节 (4.4 异样)]()

注:残缺翻译见 https://github.com/codists/practical-python-zh