[英]How does this use of Python's __metaclass__ work?
在此IPython Notebook中,我找到了有關生成器和函數式編程的演示。 我偶然發現__metaclass__
:
為什么Accounting
Real
和float
參數? 現在在bases
通常有什么,但是需要寫Real
並在其中float
嗎?
__abstractmethods__
做什么? 我無法在通常的特殊方法列表中找到它。
作者是否通過使用這兩個for循環使用其他類的方法來豐富自己的Accounting
類?
為什么Accounting(getattr(float,meth)(*args, **kwargs))
不會導致無限循環? 與第二版相比,這里發生了什么?
首先,這是與我的問題有關的摘錄:
class Accounting(Real, float):
def __metaclass__(name, bases, body):
for method in Real.__abstractmethods__:
if method not in body:
body[method] = (lambda meth: lambda *args, **kwargs: Accounting(getattr(float,meth)(*args, **kwargs)))(method)
for method in ('__ne__','__nonzero__',):
if method not in body:
body[method] = (lambda meth: lambda *args, **kwargs: getattr(float,meth)(*args, **kwargs))(method)
return Real.__metaclass__(name, bases, body)
__new__ = float.__new__
這是整個代碼:
from numbers import Real
class Accounting(Real, float):
def __metaclass__(name, bases, body):
for method in Real.__abstractmethods__:
if method not in body:
body[method] = (lambda meth: lambda *args, **kwargs: Accounting(getattr(float,meth)(*args, **kwargs)))(method)
for method in ('__ne__','__nonzero__',):
if method not in body:
body[method] = (lambda meth: lambda *args, **kwargs: getattr(float,meth)(*args, **kwargs))(method)
return Real.__metaclass__(name, bases, body)
__new__ = float.__new__
def __format__(self, fmt):
return { 1: ' %s'%float.__format__(self, fmt),
0: ' %s'%float.__format__(self, fmt).replace('0', '-'),
-1: '(%s)'%float.__format__(self, fmt) }[cmp(self,0)]
然后在這里使用代碼:
template = '{region:<{align}} {profit:>14,.0f}'.format
def output(markets, write=print, template=template):
align = max(map(len,markets))
for region, profit in markets.items():
line = template(region=region, profit=profit, align=align)
write(line)
output({region:Accounting(profit) for region, profit in markets.items()})
輸出:
Central America ( -675,140)
US ( -2,724,620)
Antarctica -
Asia ( -3,614,396)
UK ( -2,380,001)
EU 771,665
CEMEA 3,480,172
答案的一部分:
for method in Real.__abstractmethods__:
if method not in body:
body[method] = (lambda meth: lambda *args, **kwargs: Accounting(getattr(float,meth)(*args, **kwargs)))(method)
Number.Real是一個抽象類(即,您__abstractmethods__
它的實例,但可以將其用作子類。Real類具有一個稱為__abstractmethods__
的特殊凍結__abstractmethods__
,它似乎列出了Real類期望的所有方法。被定義為。 :
在交互式解釋器中:
from numbers import Real
Real.__abstractmethods__
frozenset(['__rtruediv__', '__radd__', '__truediv__', '__pow__', '__add__', '__rdiv__', '__rmul__', '__rmod__', '__eq__', '__lt__', '__float__', '__rpow__', '__mod__', '__trunc__', '__abs__', '__pos__', '__div__', '__le__', '__rfloordiv__', '__neg__', '__floordiv__', '__mul__'])
因此,此循環確保主體(實際上是元類創建的類)具有針對每個方法的具體定義。
我承認我並沒有完全理解嵌套的lambda定義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.