簡體   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