繁体   English   中英

我不明白以下代码的行为。 有人可以帮我吗

[英]I don't understand the behavior of this below code. Can someone help me here

class A(type):
    _l = []
    def __call__(cls,*args,**kwargs):
        if len(cls._l)<=5:
            cls._l.append(super().__call__(*args,**kwargs))
        else:
            return cls._l

class B(metaclass=A):
    pass


#testing starts

a=B()
a1=B()

assert a is a1

以上陈述成功了。但据我所知,它不应成功。 因为同一类的两个实例应该共享不同的内存位置。

任何建议表示赞赏。

尝试在给定类中实现5个实例的限制似乎是一个失败的尝试,就像单例是给定类中一个实例的限制一样。

而且,测试也被破坏了。

事实是,每当您尝试在Python中实例化一个类时,它都与调用任何其他对象没有什么不同: __call__方法在该类的类(即其元类)中运行。 通常,元类的__call__负责调用类的__new____init__方法-在上例中调用super().__call__时,便完成了此操作。 然后,将__call__返回的值用作新实例-上面可能是最严重的错误:在A.__call__运行的前5次中,它返回None

因此,没有为aa1都分配None,并且None为单例-这就是您的断言起作用的原因。

现在,如果要解决该问题并在len(l) < 5时返回新创建的实例,这将限制所有将A作为元类的类的实例总数,而不仅是B五个实例。 Thatis因为每类工作, _l属性应位于类本身-代码上面设定的方式,它将从class'class检索-这是A._l - (除非我们明确地创建一个_l属性在B和其他班级)。

最后,在上面的代码中没有机制可以对有限的已创建实例进行循环查询,这可以想象为可以具有某种实用性的事物-而不是选择实例,而是列出所有已创建实例的列表原始返回。

因此,在发布此版本的工作版本之前,我们先弄清楚一件事:您问

同一类的两个实例应该共享不同的内存位置。

是的-但是实际上创建两个不同的对象的是type.__call__ A.__call__不会每次都调用此方法,它返回的任何对象都将用于代替新实例。 如果它返回一个预先存在的对象,那就是调用者代码得到的。

重新命名它,因此毫无疑问:实例化类与在Python中调用任何其他对象没有什么不同:关联对象的__call__运行并返回一个值。

现在,如果要限制类的实例并平衡要检索的实例,则元类代码可以是:

MAX_INSTANCES = 5

class A(type):

    def __call__(cls, *args, **kw):
        cls._instances = instances = getattr(cls, "_instances", [])
        cls._index = getattr(cls, "_index", -1)
        if len(instances) < MAX_INSTANCES:
            # Actually creates a new instance:
            instance = super().__call__(cls, *args, **kw)
            instances.append(instance)
        cls._index = (cls._index + 1) % MAX_INSTANCES
        return cls._instances[cls._index]


class B(metaclass=A):
    pass

b_list = [B() for B in range(MAX_INSTANCES * 2)]

for i in range(MAX_INSTANCES):
    assert b_list[i] is b_list[i + MAX_INSTANCES]
    for j in range(1, MAX_INSTANCES):
        assert b_list[i] is not b_list[i + j]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM