本文最后更新于 1789 天前,其中的信息可能已经有所发展或是发生改变。
# 多行输出结果
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
自定义类的使用例子
1. 例子一:
class Money(object):
currency_rates = {
'$': 1,
'€': 0.88,
}
def __init__(self, symbol, amount):
self.symbol = symbol
self.amount = amount
def __repr__(self):
return '%s%.2f' % (self.symbol, self.amount)
def convert(self, other):
''' Convert other amount to our currency '''
new_amount = (
other.amount / self.currency_rates[other.symbol] \
* self.currency_rates[self.symbol]
)
return Money(self.symbol, new_amount)
soda_cost = Money('$', 5.25)
soda_cost
pizza_cost = Money('€', 7.99)
pizza_cost
$5.25
€7.99
该类定义为给定的货币符号和汇率定义了一个货币汇率,指定了一个初始化器(也称为构造函数),并实现 __repr__
,因此当我们打印这个类时,我们会看到一个友好的表示,例如 $2.00
,这是一个带有货币符号和金额的 Money('$', 2.00)
实例。最重要的是,它定义了一种方法,允许你使用不同的汇率在不同的货币之间进行转换。
我们可以使用魔术方法使得这个类的实例之间可以相互交互。假设我们希望能够将这个类的两个实例一起加在一起,即使它们是不同的货币。为了实现这一点,我们可以在 Money
类上实现 __add__
这个魔术方法:
class Money(object):
currency_rates = {
'$': 1,
'€': 0.88,
}
def __init__(self, symbol, amount):
self.symbol = symbol
self.amount = amount
def __repr__(self):
return '%s%.2f' % (self.symbol, self.amount)
def convert(self, other):
''' Convert other amount to our currency '''
new_amount = (
other.amount / self.currency_rates[other.symbol] \
* self.currency_rates[self.symbol]
)
return Money(self.symbol, new_amount)
def __add__(self, other):
''' Add 2 Money instances using "+" '''
new_amount = self.amount + self.convert(other).amount
return Money(self.symbol, new_amount)
soda_cost = Money('$', 5.25)
pizza_cost = Money('€', 7.99)
soda_cost + pizza_cost
pizza_cost + soda_cost
$14.33
€12.61
2. 例子二: 魔术方法映射到内置函数,
例如__len__()
映射到len()
.
class Alphabet(object):
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def __len__(self):
return len(self.letters)
my_alphabet = Alphabet()
len(my_alphabet)
26
3. 例子三: 自定义迭代器
迭代我们自己的自定义类?首先,让我们来澄清一些术语。
- 要成为一个可迭代对象,一个类需要实现
__iter__()
__iter__()
方法需要返回一个迭代器- 要成为一个迭代器,一个类需要实现
__next__()
(或在 Python 2中是 next()),当没有更多的项要迭代时,必须抛出一个StopIteration
异常。
使用场景:
我们有一个 Server 实例在不同的端口上运行不同的服务,如 http 和 ssh。其中一些服务处于 active 状态,而其他服务则处于 inactive 状态。
class Server(object):
services = [
{'active': False, 'protocol': 'ftp', 'port': 21},
{'active': True, 'protocol': 'ssh', 'port': 22},
{'active': True, 'protocol': 'http', 'port': 21},
]
def __iter__(self):
for service in self.services:
if service['active']:
yield service['protocol'], service['port']
for protocol, port in Server():
print('service %s is running on port %d' % (protocol, port))
service ssh is running on port 22
service http is running on port 21
yield
关键字到底是什么?在定义生成器函数时使用 yield
。这有点像 return
,虽然 return
在返回值后退出函数,但 yield
会暂停执行直到下次调用它。这允许你的生成器的功能在它恢复之前保持状态。