目录 | 上一节 (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
>>> d
datetime.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 call
49010.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.name
setattr(obj, 'name', value) # Same as obj.name = value
delattr(obj, 'name') # Same as del obj.name
hasattr(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)
>>> goog
Stock('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 = GOOG
shares = 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