簡體   English   中英

如何使用Python的__metaclass__?

[英]How does this use of Python's __metaclass__ work?

在此IPython Notebook中,我找到了有關生成器和函數式編程的演示。 我偶然發現__metaclass__

  1. 為什么Accounting Realfloat參數? 現在在bases通常有什么,但是需要寫Real並在其中float嗎?

  2. __abstractmethods__做什么? 我無法在通常的特殊方法列表中找到它。

  3. 作者是否通過使用這兩個for循環使用其他類的方法來豐富自己的Accounting類?

  4. 為什么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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM