鱼C论坛

 找回密码
 立即注册
12
返回列表 发新帖
楼主: 亦又

疑问

[复制链接]
 楼主| 发表于 2024-4-15 20:42:47 | 显示全部楼层
class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        print("Entering MyMeta.__new__()")
        # 创建类对象
        obj = super().__new__(cls, name, bases, attrs)
        print("Exiting MyMeta.__new__()")
        return obj

    def __init__(self, name, bases, attrs):
        print("Initializing", name)
        super().__init__(name, bases, attrs)

    def __call__(self, *args, **kwargs):
        print("Entering MyMeta.__call__()")
        # 实例化对象
        obj = super().__call__(*args, **kwargs)
        print("Exiting MyMeta.__call__()")
        return obj


class MyClass(metaclass=MyMeta):
    def __new__(cls, *args, **kwargs):
        print("Entering MyClass.__new__()")
        obj = super().__new__(cls)
        print("Exiting MyClass.__new__()")
        return obj

    def __init__(self):
        print("Initializing MyClass")


my_obj = MyClass()
输出结果是啥?@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 20:43:19 | 显示全部楼层
亦又 发表于 2024-04-15 20:42
class MyMeta(type):
    def __new__(cls, name, ba ...


输出结果如下:

Entering MyMeta.__new__()
Exiting MyMeta.__new__()
Initializing MyClass
Entering MyClass.__new__()
Exiting MyClass.__new__()
Entering MyMeta.__call__()
Exiting MyMeta.__call__()

这是因为在使用metaclass创建类对象和实例化对象时,会依次调用对应的特殊方法。具体解释如下:

1. 首先,使用metaclass创建类对象时,会先调用metaclass的`__new__()`方法。在这个示例中,调用了`MyMeta.__new__()`,打印"Entering MyMeta.__new__()",然后使用super().__new__()创建了类对象,并打印"Exiting MyMeta.__new__()"
2. 接着,会调用metaclass的`__init__()`方法。在这个示例中,调用了`MyMeta.__init__()`,打印"Initializing MyClass",然后使用super().__init__()完成初始化
3. 然后,在实例化对象时,首先调用类对象的`__new__()`方法。在这个示例中,调用了`MyClass.__new__()`,打印"Entering MyClass.__new__()",然后使用super().__new__()创建了对象,并打印"Exiting MyClass.__new__()"
4. 最后,在实例化对象时,调用类对象的`__init__()`方法。在这个示例中,调用了`MyClass.__init__()`,打印"Initializing MyClass"
5. 最后,在`MyMeta.__call__()`方法被调用时,打印"Entering MyMeta.__call__()",使用super().__call__()实例化对象,并打印"Exiting MyMeta.__call__()"

所以,最终的输出结果是以上的序列。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 20:59:37 | 显示全部楼层

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        print("Entering MyMeta.__new__()")
        # 创建类对象
        obj = super().__new__(cls, name, bases, attrs)
        print("Exiting MyMeta.__new__()")
        return obj

    def __init__(self, name, bases, attrs):
        print("Initializing", name)
        super().__init__(name, bases, attrs)

    def __call__(self, *args, **kwargs):
        print("Entering MyMeta.__call__()")
        # 实例化对象
        obj = super().__call__(*args, **kwargs)
        print("Exiting MyMeta.__call__()")
        return obj


class MyClass(metaclass=MyMeta):
    def __new__(cls, *args, **kwargs):
        print("Entering MyClass.__new__()")
        obj = super().__new__(cls)
        print("Exiting MyClass.__new__()")
        return obj

    def __init__(self):
        print("Initializing MyClass")


my_obj = MyClass()
结果依次是啥?@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 20:59:47 | 显示全部楼层
亦又 发表于 2024-04-15 20:59
class MyMeta(type):
    def __new__(cls, name, ba ...


结果如下:

Entering MyMeta.__new__()
Initializing MyClass
Exiting MyMeta.__new__()
Entering MyMeta.__call__()
Entering MyClass.__new__()
Initializing MyClass
Exiting MyClass.__new__()
Exiting MyMeta.__call__()

解释:
1. 首先,实例化`MyClass`对象时,首先调用元类`MyMeta`的`__call__`方法。
2. 在`MyMeta.__call__`方法中,使用`super().__call__(*args, **kwargs)`来调用`MyClass`的`__new__`和`__init__`方法。
3. 这时会进入`MyClass.__new__`方法,输出"Entering MyClass.__new__()",然后通过`super().__new__(cls)`来创建`MyClass`的实例对象。
4. 然后进入`MyClass.__init__`方法,输出"Initializing MyClass",完成对`MyClass`对象的初始化。
5. 退出`MyClass.__new__`方法,输出"Exiting MyClass.__new__()"。
6. 退出`MyMeta.__call__`方法,输出"Exiting MyMeta.__call__()"

最终的输出结果是:

Entering MyMeta.__new__()
Exiting MyMeta.__new__()
Entering MyMeta.__call__()
Entering MyClass.__new__()
Initializing MyClass
Exiting MyClass.__new__()
Exiting MyMeta.__call__()

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 21:55:26 | 显示全部楼层

元类`MetaClass`的`__call__()`方法被调用后,会调用`super().__call__(*args, **kwargs)`,这里的`super()`指的是`type`类,也就是默认的元类。所以,`super().__call__(*args, **kwargs)`实际上会调用`type`的`__call__()`方法。

在`type`的`__call__()`方法中,会调用哪个类的`__new__()`和`__new__()`方法来创建一个对象,并返回类对象还是类的实例对象?
还是先执行__call__()方法,返回创建的类对象,再调用类中__new__() 和__new__()创建对象并进行出初始化?@FishC
@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 21:55:53 | 显示全部楼层
亦又 发表于 2024-04-15 21:55
元类`MetaClass`的`__call__()`方法被调用后,会调用` ...


当调用`type`类的`__call__()`方法时,会调用被元类(`MetaClass`)实例化的类的`__new__()`方法来创建一个实例对象,并返回该实例对象。然后,在`type`的`__call__()`方法中,会调用该实例对象的`__init__()`方法进行初始化操作。

举个例子来说,假设有一个类`MyClass`,它是由元类`MetaClass`实例化的。当我们使用 `my_obj = MyClass(*args, **kwargs)` 创建一个实例对象时,会依次执行以下步骤:

1. 首先,会调用 `MetaClass` 的 `__call__()` 方法,这个方法是元类的特殊方法,用于创建类的实例对象。
2. 在 `MetaClass` 的 `__call__()` 方法中,会调用 `MyClass` 类的 `__new__()` 方法来创建一个实例对象,并返回该实例对象,注意,此时还没有进行初始化操作。
3. 接着,在 `MetaClass` 的 `__call__()` 方法中,会调用 `MyClass` 类的 `__init__()` 方法对实例对象进行初始化操作。

总结起来就是,首先通过元类的 `__call__()` 方法创建类的实例对象,然后调用该实例对象的 `__init__()` 方法进行初始化。

请注意,上面的例子仅是为了解释概念,实际实现的细节可能与之略有不同。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 21:56:05 | 显示全部楼层
亦又 发表于 2024-04-15 21:55
元类`MetaClass`的`__call__()`方法被调用后,会调用` ...


在`type`的`__call__()`方法中,会调用类对象的`__new__()`方法来创建一个新的实例对象,并调用该实例对象的`__init__()`方法进行初始化。最后,`__call__()`方法将返回这个初始化后的实例对象。

具体的流程是这样的:
1. 调用元类的`__call__()`方法。
2. `__call__()`方法中,会调用类对象的`__new__()`方法来创建一个新的实例对象。
3. 创建完成后,`__call__()`方法会调用实例对象的`__init__()`方法进行初始化。
4. 最后,`__call__()`方法将返回这个初始化后的实例对象。

代码示例如下:

  1. class MetaClass(type):
  2.     def __call__(cls, *args, **kwargs):
  3.         # 调用类对象的__new__方法来创建新的实例对象
  4.         obj = super().__call__(*args, **kwargs)
  5.         # 调用实例对象的__init__方法进行初始化
  6.         obj.__init__(*args, **kwargs)
  7.         return obj


  8. class MyClass(metaclass=MetaClass):
  9.     def __new__(cls, *args, **kwargs):
  10.         print("调用了类的__new__方法")
  11.         return super().__new__(cls)
  12.         
  13.     def __init__(self, *args, **kwargs):
  14.         print("调用了类的__init__方法")


  15. my_obj = MyClass()
复制代码


输出结果为:

  1. 调用了类的__new__方法
  2. 调用了类的__init__方法
复制代码


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 22:07:00 | 显示全部楼层

class MetaClass(type):
    def __new__(cls, name, bases, attrs):
        print("元类的__new__()方法被调用")
        return super().__new__(cls, name, bases, attrs)
   
    def __init__(cls, name, bases, attrs):
        print("元类的__init__()方法被调用")
        super().__init__(name, bases, attrs)
        
    def __call__(cls, *args, **kwargs):
        print("元类的__call__()方法被调用")
        return super().__call__(*args, **kwargs)

class MyClass(metaclass=MetaClass):
    def __new__(cls, *args, **kwargs):
        print("类的__new__()方法被调用")
        return super().__new__(cls)
   
    def __init__(self, *args, **kwargs):
        print("类的__init__()方法被调用")
        super().__init__(*args, **kwargs)

obj = MyClass()
元类__call__方法返回是个什么值?元类__call__方法会调用类MyClass的`__new__()`和`__new__()`方法来创建一个对象,并返回该对象?

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 22:07:30 | 显示全部楼层
亦又 发表于 2024-04-15 22:07
class MetaClass(type):
    def __new__(cls, name, ...


在元类的`__call__()`方法中,通常会调用`super().__call__(*args, **kwargs)`来创建一个对象,并返回这个对象。所以,元类的`__call__()`方法的返回值就是通过调用`super().__call__(*args, **kwargs)`得到的对象。它可以是一个新创建的类对象,也可以是一个已经存在的实例对象,具体取决于元类的实现。在上述示例中,元类的`__call__()`方法通过调用`super().__call__(*args, **kwargs)`来创建并返回一个类对象。至于类对象的`__new__()`和`__init__()`方法,会在类的实例化过程中被调用,而不是在元类的`__call__()`方法中被调用。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 22:11:33 | 显示全部楼层


class MetaClass(type):
    def __new__(cls, name, bases, attrs):
        print("元类的__new__()方法被调用")
        return super().__new__(cls, name, bases, attrs)
   
    def __init__(cls, name, bases, attrs):
        print("元类的__init__()方法被调用")
        super().__init__(name, bases, attrs)
        
    def __call__(cls, *args, **kwargs):
        print("元类的__call__()方法被调用")
        return super().__call__(*args, **kwargs)

class MyClass(metaclass=MetaClass):
    def __new__(cls, *args, **kwargs):
        print("类的__new__()方法被调用")
        return super().__new__(cls)
   
    def __init__(self, *args, **kwargs):
        print("类的__init__()方法被调用")
        super().__init__(*args, **kwargs)

obj = MyClass()
元类__call__方法返回是个什么值?元类__call__方法中的super().__call__(*args, **kwargs)会调用类MyClass的`__new__()`和`__new__()`方法来创建一个对象,并返回该对象?@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 22:11:40 | 显示全部楼层
亦又 发表于 2024-04-15 22:11
class MetaClass(type):
    def __new__(cls, name, ...


元类的`__call__()`方法返回的是通过调用`super().__call__(*args, **kwargs)`返回的对象。在这段代码中,`super().__call__(*args, **kwargs)`会调用类`MyClass`的`__new__()`和`__init__()`方法来创建一个对象并进行初始化,然后返回该对象。

所以,元类`MetaClass`的`__call__()`方法被调用后,会调用类`MyClass`的`__new__()`和`__init__()`方法,并返回一个对象给变量`obj`。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-16 09:47:38 | 显示全部楼层
class MetaClass(type):
    def __new__(cls, name, bases, attrs):
        print("元类的__new__()方法被调用")
        return super().__new__(cls, name, bases, attrs)
   
    def __init__(cls, name, bases, attrs):
        print("元类的__init__()方法被调用")
        super().__init__(name, bases, attrs)
        
    def __call__(cls, *args, **kwargs):
        print("元类的__call__()方法被调用")
        return super().__call__(*args, **kwargs)

class MyClass(metaclass=MetaClass):
    def __new__(cls, *args, **kwargs):
        print("类的__new__()方法被调用")
        return super().__new__(cls)
   
    def __init__(self, *args, **kwargs):
        print("类的__init__()方法被调用")
        super().__init__(*args, **kwargs)

obj = MyClass()
元类__call__方法返回是个什么值?元类__call__方法中的super().__call__(*args, **kwargs)会调用元类MetaClass的`__new__()`和`__new__()`方法来创建一个类对象,并返回该类对象?
还是再定义完类的时候直接触发,也就是在obj = MyClass()之前触发?
@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-16 09:47:49 | 显示全部楼层
亦又 发表于 2024-04-16 09:47
class MetaClass(type):
    def __new__(cls, name, ...


在这段代码中,元类的`__call__()`方法会在创建类对象时被调用。

`__call__()`方法的作用是使得类对象可以像函数一样被调用。在这个例子中,`MetaClass`元类的`__call__()`方法被调用时,会使用`super().__call__(*args, **kwargs)`调用父类的`__call__()`方法,这里的父类指的是`type`元类。`type`的`__call__()`方法会调用元类的`__new__()`和`__init__()`方法来创建一个实例对象,并返回该实例对象。

所以,`元类__call__`方法的返回值是一个实例对象。

而触发元类的`__call__()`方法是在创建类对象时,也就是在`obj = MyClass()`这一行代码之前触发。`MyClass`类的定义中,元类是`MetaClass`,所以在创建`MyClass`类对象时,会先调用`MetaClass`元类的`__call__()`方法,然后再通过`super().__call__(*args, **kwargs)`调用`type`元类的`__call__()`方法来创建类对象。

希望能解答到你的问题,如果还有疑问,请随时追问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-1 04:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表