class Vector2d: def __init__(self, x, y): self.x = x self.y = y def __iter__(self): return (n for n in (self.x, self.y))
class Vector2d: def __init__(self, x, y): self.__x = x self.__y = y @property def x(self): return self.__x @property def y(self): return self.__y def __iter__(self): return (i for i in (self.x, self.y))
>>> class Foo: ... def __getitem__(self, pos): ... return range(0, 30, 10)[pos] ... >>> f = Foo() >>> f[1] >>> for i in f: print(i) ... >>> 20 in f True >>> 15 in f False
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Cards(rank, suit) for suit in self.suits
for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, pos):
return self._cards[pos]
>>> from random import shuffle >>> my_list = list(range(1, 11)) >>> shuffle(my_list) >>> my_list [5, 7, 9, 2, 10, 1, 8, 6, 4, 3]
Traceback (most recent call last): File "/Users/demon/PycharmProjects/FluentPython/接口:从协议到抽象基类/FrenchDeck.py", line 37, in <module> shuffle(deck) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/random.py", line 274, in shuffle x[i], x[j] = x[j], x[i] TypeError: 'FrenchDeck' object does not support item assignment
from collections import namedtuple
from random import shuffle
Cards = namedtuple('Cards', ['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 = [Cards(rank, suit) for suit in self.suits
for rank in self.ranks]
def __len__(self): #获取长度的len
return len(self._cards)
def __getitem__(self, position): #能够支持切片取值的处理
return self._cards[position]
deck = FrenchDeck() #实例化
def set_card(deck, position, card): #猴子不定,其实就是启动调用内部__setitem__设置值得外部函数
deck._cards[position] = card
FrenchDeck.__setitem__ = set_card #把猴子补丁传递给内部的魔术方法
shuffle(deck) #打乱洗牌的序列
print(deck[:5]) #获取前五个卡牌的值
[Cards(rank='K', suit='diamonds'), Cards(rank='4', suit='spades'), Cards(rank='A', suit='clubs'), Cards(rank='K', suit='spades'), Cards(rank='6', suit='clubs')]
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck2(collections.MutableSequence):
ranks = [str(i) for i in range(1, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Card(rank, suit) for suit in self.suits
for rank in self.ranks]
def __len__(self): #支持查看长度
return len(self._cards)
def __getitem__(self, position): #支持切片
return self._cards[position]
def __setitem__(self, position, value): #支持洗牌
self._cards[position] = value
def __delitem__(self, position): #但是继承MutableSequence的类必须实现 __delitem__ 方法,这是MutableSequence 类的一个抽象方法。
del self._cards[position]
def insert(self, position, value): #此外,还要实现insert方法,这是MutableSequence类的第三个抽象方法
self._cards.insert(position, value)
import abc class Tombola(abc.ABC): #自己定义的抽象基类要继承abc.ABC @abc.abstractmethod def load(self, iterable): #抽象方法使用@abstractmethod装饰器标记,而且定义体中通常只有文档字符串 """从可迭代对象中添加元素""" @abc.abstractmethod def pick(self): #根据文档字符串,如果没有元素可选,应该抛出LookupError """随机删除元素,然后返回 如果实例为空,这个方法应该抛出'LookupError' """ def loaded(self): #抽象基类可以包含具体方法 """如果至少有一个元素,返回`True`,否则返回`False`。""" return bool(self.inspect()) def inspect(self): """返回一个有序元组,由当前元素构成。""" items = [] while True: try: items.append(self.pick()) except LookupError: break self.load(items) #使用 .load(...)把所有元素放回去 return tuple(sorted(items)) #返回排序好的items攻loaded调用
BaseException ├── SystemExit ├── KeyboardInterrupt ├── GeneratorExit └── Exception ├── StopIteration ├── ArithmeticError │ ├── FloatingPointError │ ├── OverflowError │ └── ZeroDivisionError ├── AssertionError ├── AttributeError ├── BufferError ├── EOFError ├── ImportError ├── LookupError #我们在 Tombola.inspect 方法中处理的是 LookupError 异常 │ ├── IndexError #IndexError 是 LookupError 的子类,尝试从序列中获取索引超过最后位置的元素时抛出 │ └── KeyError #使用不存在的键从映射中获取元素时,抛出 KeyError 异常 ├── MemoryError ... etc.
>>> from tombola import Tombola >>> class Fake(Tombola): # 把Fake声明为Tombole的子类,继承抽象类 ... def pick(self): ... return 13 ... >>> Fake # 创建Fake类,目前木有毛线问题~ <class '__main__.Fake'> >>> f = Fake() # 报错了,Python认为Fake类是抽象类,因为没有实现load方法 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class Fake with abstract methods load
class Tombola(metaclass=abc.ABCMeta): # ...
class Tombola(object): # 这是Python 2!!! __metaclass__ = abc.ABCMeta # ...
class MyABC(abc.ABC): @classmethod @abc.abstractmethod def an_abstract_classmethod(cls, ...): pass
import random
import abc
class Tombola(abc.ABC): #自己定义的抽象基类要继承abc.ABC
@abc.abstractmethod
def load(self, iterable): #抽象方法使用@abstractmethod装饰器标记,而且定义体中通常只有文档字符串
"""从可迭代对象中添加元素"""
@abc.abstractmethod
def pick(self): #根据文档字符串,如果没有元素可选,应该抛出LookupError
"""随机删除元素,然后返回
如果实例为空,这个方法应该抛出'LookupError'
"""
def loaded(self): #抽象基类可以包含具体方法
"""如果至少有一个元素,返回`True`,否则返回`False`。"""
return bool(self.inspect())
def inspect(self):
"""返回一个有序元组,由当前元素构成。"""
items = []
while True:
try:
items.append(self.pick())
except LookupError:
break
self.load(items) #使用 .load(...)把所有元素放回去
return tuple(sorted(items)) #返回排序好的items攻loaded调用
#下面的代码应该单端放到一个py文件中,为了省事,就不在单独放到一个模块里面导入了~
class BigoCage(Tombola): #明确指定BingoCage类扩展Tombola类
def __init__(self, items):
self._randomizer = random.SystemRandom() #假设我们将在线上游戏中使用这个。random.SystemRandom使用os.urandom(...) 函数实现randomAPI
self._items = []
self.load(items) #委托.load(...)方法实现初始加载
def load(self, items):
self._items.extend(items) #如果通过load方法传递一个可迭代的对象进来,可以扩展到以后的self._items的列表中
self._randomizer.shuffle(self._items) #没有使用random.shuffle而是使用了SystemRandom中的shuffle方法
def pick(self):
try:
return self._items.pop()
except IndexError:
raise LookupError('pick from empty BingoCage')
def __call__(self):
self.pick()
b = BigoCage(range(10))
print(b.pick())
import random
from tombola import Tombola
class LotteryBlower(Tombola):
def __init__(self, iterable):
self._balls = list(iterable) #创建一个副本
def load(self, iterbale):
self._balls.extend(iterbale) #把一个可迭代的对象添加到列表中
def pick(self):
try:
position = random.randrange(len(self._balls)) #获取一个随机数
except ValueError:
raise LookupError('pick from empty LotteryBlower')
return self._balls.pop(position) #删除列表中通过列表长度获取的随机数位置的索引值
def loaded(self):
return bool(self._balls)
def inspect(self):
return tuple(sorted(self._balls))
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有