代码之家  ›  专栏  ›  技术社区  ›  Cyker

`__在类和对象上新建和初始化

  •  0
  • Cyker  · 技术社区  · 7 年前

    在Python3中,定义子类时,为什么需要使用 cls 作为 __new__ ,但不可使用 self 作为 __init__

    例如:

    class MyClass(object):
        def __new__(cls, *args, **kwargs):
            return super(MyClass, cls).__new__(cls, *args, **kwargs) # with `cls`
        def __init__(self, *args, **kwargs):
            return super(MyClass, self).__init__(*args, **kwargs) # without `self`
    

    当我比较这些函数时,我更加困惑:

    >>> cls = object
    >>> self = cls()
    >>> cls.__new__ is self.__new__
    True
    >>> cls.__init__ is self.__init__
    False
    >>> self.__init__()
    >>> cls.__init__()
    Traceback (most recent call last): ...
    

    那么,它们之间的区别是什么 __新的__ 和 这些结果的背后是什么?哪些方法是绑定的,哪些是自由的?你为什么能打电话 self.__init__() 但不是 cls.__init__() cls.__init__ cls 它本身还是在它的元类中?

    3 回复  |  直到 7 年前
        1
  •  4
  •   user2357112    7 年前

    你可能错过的最重要的部分是 __new__ 是一种静态的方法, special-cased 即使你不使用 @staticmethod 室内装修设计师

    通过调用方法时 super() 执行通常针对该类方法执行的相同类型的参数绑定(使用 descriptor protocol ).对于一个静态方法,如 ,这意味着不会自动绑定任何参数,因此 cls __init__ ,就是说 self 是自动绑定的,这就是您不必通过的原因 到 super().__init__ .

        2
  •  1
  •   Hou Lu    7 年前

    cls 代表阶级本身,而 self 表示对象本身。这些只是惯例。
    这个 __new__ 方法被调用 事实上,这个对象是被创建的, 应该创建对象并返回它。因此,它需要一个 创建对象。在那之后 __init__ 被叫去 初始化 对象,因此它需要对象作为第一个参数。

    例如:

    class MyClass:
        def __new__(cls, *args, **kwargs):
            # cls == MyClass
            return super().__new__(cls, *args, **kwargs)
            # cls here is because __new__ is staticmethods so you have to pass the cls explicitly
    
            # You can't use cls() here because it will call this methods again and again
            # causing recusion error
    
        def __init__(self, *args, **kwargs):
            # Here self is the instance(or object) of MyClass
            # So you can initialize it by self.xxx
            self.xxx = 'xxx'
    

    __新的__ 是静态方法,因此类和实例共享相同的 __新的__ 方法 __初始化__ 是实例的方法。如果要通过类调用它,则需要显式地将实例作为第一个参数传递。

    cls.__init__(self)
    

    Python中的任何东西都是对象,包括类本身。所以对于班级来说,它有自己的特点 __新的__ __初始化__ metaclass 到 创造 阶级和 初始化 班
    这些都是Python的元编程,我建议阅读Python烹饪书的第九章。

        3
  •  1
  •   user2357112    7 年前

    主要目的 __new__ 是分配类的新实例,而 __init__ 的工作是设置现有实例。

    根据文件:

    __new__() 是一个静态方法(特殊情况,因此不需要声明)

    另一方面,是一个合适的实例方法。顺便说一下,它可以在同一个实例上被多次调用。

    这足以解释您的终端会话:

    >>> cls = object
    >>> self = cls()
    

    object.__call__ ,基本上是这样的

    self = cls.__new__()
    if isinstance(self, cls):
        cls.__init__(self)
    return self
    

    请注意 __新的__ 不要求是其所属类的实例,但 __初始化__

    >>> cls.__new__ is self.__new__
    True
    

    __新的__ 是一个静态方法,因此尝试将其绑定到实例没有任何作用:它保持类方法。这也是你必须通过考试的原因 cls 在调用时显式地 super().__new__

     >>> cls.__init__ is self.__init__
     False
    

    这些不仅是不同的东西,而且它们的类型也不同。 cls.__init__ 是一个正则函数。 self.__init__ 是一个绑定方法,它缺少 cls.\uuuu init__ .

    >>> self.__init__()
    

    object

    >>> cls.__init__()
    

    这就是所谓的原始 __初始化__ 函数,它要求 self

    >>> cls.__init__(self)
    
    推荐文章