為什麼 super().__new__(cls, name, bases, dct) 中的 cls 是顯式傳遞的,而不是像 self 那樣隱式傳遞

EricS9999發表於2024-12-09

問題來源:為什麼定義元類和自定義元類時,在呼叫父類的__new__方法時都是需要顯式傳遞cls的,而__init__在呼叫父類__init__方法時就是隱式的。

# 自定義元類
class MyMeta(type):
    def __new__(cls, name, bases, dct):
        print(f"Creating class {name} using MyMeta")
        return super().__new__(cls, name, bases, dct)

    def __init__(cls, name, bases, dct):
        print(f"Initializing class {name} using MyMeta")
        super().__init__(name, bases, dct)
# 使用自定義元類建立類
class MyClass(metaclass=MyMeta):
    def __new__(cls, *args, **kwargs):
        print(f"Creating an instance of {cls.__name__}")
        instance = super().__new__(cls,*args, **kwargs)  # 呼叫父類的 __new__ 方法
        return instance

    def __init__(self, name):
        print(f"Initializing an instance of {self.__class__.__name__}")
        self.name = name

    def __call__(self):
        print(f"Instance of {self.__class__.__name__} is being called!")

# 例項化 MyClass
print("\n-- Step 1: Create an instance --")
obj = MyClass("Alice")

# 呼叫例項
print("\n-- Step 2: Call the instance --")
obj()

原因:這是因為__new__是靜態方法,不依賴於例項呼叫,而依賴於類本身。 因此,Python 要顯式地將 cls 傳遞給__new__方法。

那麼為什麼 cls 需要顯式傳遞?

在元類中,cls 是動態決定的

在元類的 __new__ 方法中,cls 代表將要建立的類。
•  呼叫 super().__new__(cls, name, bases, dct) 時:
•  super() 呼叫的是父類(通常是 type)的 __new__ 方法。
•  cls 需要明確告訴 type.__new__ 它要建立哪個類。
•  type.__new__ 會根據 cls 建立一個類。

具體呼叫流程:
•  Python 呼叫元類的 __new__ 時,會顯式傳遞 cls。
•  元類的 __new__ 需要將 cls 傳遞給 type.__new__,否則父類不知道該建立哪個類。

相關文章