Python的元类是如何使用的?

2024-04-20 06:05:39 发布

您现在位置:Python中文网/ 问答频道 /正文

Here in this IPython Notebook我发现了一个关于生成器和函数式编程的演示文稿。我偶然发现__metaclass__

  1. 为什么Realfloat的参数是Accounting?现在通常在bases中有什么,但是否需要在其中写入Realfloat

  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

Tags: lambdainforargsbodyfloatrealmethod
1条回答
网友
1楼 · 发布于 2024-04-20 06:05:39

答案的一部分:

for method in Real.__abstractmethods__:
           if method not in body:
               body[method] = (lambda meth: lambda *args, **kwargs: Accounting(getattr(float,meth)(*args, **kwargs)))(method)

你知道吗数字。真的是一个抽象类(也就是说,你不能证实它的一个实例,但是你可以把它作为一个子类使用。Real类有一个名为__abstractmethods__的特殊frozenset,它似乎列出了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__'])

因此,这个循环确保body(实际上是由元类创建的类)对每个方法都有一个具体的定义。你知道吗

我承认我并没有完全理解嵌套的lambda定义。你知道吗

相关问题 更多 >