python - python 类 __init__ 方法会隐式返回 None 吗?

标签 python

我试图在类构造函数中返回一个值( init ):

class A:
  def __init__(self):
    return 1

但是有一个运行时错误说 初始化 应该返回无。如果是这种情况,如何理解:
a=A()

其中“a”被分配为类实例?

最佳答案

严格来说,不是A.__new__()正在创建实例 a .

当您定义 class A(object): (或者 class A: 如果你使用的是 Python3, class A:old-style class that has been deprecated ),它是 __new__从继承object.__new__()被调用以创建实例 a .

a = A()被执行,会发生什么:

  • A()A.__call__ 的简写
  • object.__new__(cls, *args, **kwargs)哪里cls=A , 是在引擎盖下实际发生的创建实例 a .它为新对象分配内存,然后返回一个新对象(实例)。
  • 当且仅当返回新创建的对象时 __init__(self)然后使用传递给它的新创建的对象调用以“初始化”该对象。

  • 考虑以下演示:
  • 当我们覆盖 __new__并且不再返回对象,__init__将要
    不被调用:
    class A(object):
    
        def __new__(cls, *args, **kwargs):
            print cls, args, kwargs
    
        def __init__(self):
            self.x = 'init!'
            print self.x
    
    
    In : a = A()
    <class '__main__.A'> () {}
    
    # note that "init!" has not appeared here because __new__ didn't return an
    # new instance
    
  • 现在,使用 object.__new__ 返回一个新实例,你会看到
    之后 __new__ , __init__也将被称为:
    class A(object):
    
        def __new__(cls, *args, **kwargs):
            print cls, args, kwargs
            return object.__new__(cls, args, kwargs)
    
        def __init__(self):
            self.x = 'init!'
            print self.x
    
    In : a = A()
    <class '__main__.A'> () {}
    init!
    


  • 这是显示差异的另一个演示,请注意实例 a无需调用即可创建__init__() :
    class A(object):
        def __init__(self):
            self.x = "init!"
            print self.x
    
    In : a = object.__new__(A)
    
    In : a
    Out: <__main__.A at 0x103466450>
    
    In : a.__dict__
    Out: {}
    
    
    In : aa = A()
    init!
    
    In : aa
    Out: <__main__.A at 0x1033ddf50>
    
    In : aa.__dict__
    Out: {'x': 'init!'}
    

    现在对于好奇(以及刷新我自己的内存=]):

    粗略地说,在 Python 中创建新对象有两种主要方式:

    通过子类化创建新对象(类型/类):
    class语句告诉 Python 创建一个新的类型/类对象(通过
    子类化现有类型/类,例如 object ):
    class Hello(object):
        pass
    >>> Hello.__class__
    <type 'type'>
    

    实际上所有的类/类型对象都有类型 type . type的类型
    ( type(type) ) 仍然是类型。

    您可以对类型/类对象进行子类化。

    通过实例化创建新对象(实例):

    您还可以通过实例化现有类型对象来创建新对象。
    这是通过使用 __call__ 来完成的。运算符(由 () 简写):
    >>> h = hello()
    >>> type(h)
    <class '__main__.Hello'>
    >>> type(int('1'))
    <type 'int'>
    

    您不能子类化实例对象。

    (请注意,您还可以通过其他方式创建新的实例对象,例如
    使用列表运算符 [1,2,3] ,在这种情况下,它会创建一个列表实例)

    您可以通过 type(my_obj) 检查对象的类型或 my_object.__class__ .

    现在您知道实例对象是如何创建的,但真正创建类型/类对象(允许创建实例对象)的是什么?

    事实上,这些对象也是通过实例化创建的,尽管它是一个
    与前面提到的实例化略有不同。

    除了 class声明,你也可以使用type(cls_name, parent_class_tuple, attr_dict)创建一个新类。
    例如:
    type('Hello', (object,), {})
    

    将创建 Hello类与前面显示的类相同。

    什么是type ?进入元类。
    type是一个元类,它是类的类,即类是
    元类的实例。 __class__type还在type .

    所以这是一个图表,显示了元类、类之间的关系,
    实例:
                instantiate             instantiate
    metaclass   --------------> class   ---------------->    instance
                type.__new__()          object.__new__()
    

    当元类type被调用以创建一个新类,类似的流程是:
  • type.__call__()已执行
  • type.__new__()分配内存然后返回新的类(元类实例),然后调用 type.__init__() .
  • type.__init__()初始化从步骤 2 传递的新创建的类。

  • 您甚至可以通过子类化 type 来创建新的元类。 :
    class MyMeta(type):
        def __new__(meta, name, bases, dct):
            # do something
            return super(MyMeta, meta).__new__(meta, name, bases, dct)
        def __init__(cls, name, bases, dct):
            # do something
            super(MyMeta, cls).__init__(name, bases, dct)
    

    然后你可以从这个 MyMeta 创建一个新类元类就像你一样
    type :
    MyClass = MyMeta('MyClass', (object, ), {'x': 1})
    

    或者,使用 __metaclass__在定义您的类时,它具有
    效果与上图相同:
    class MyClass(object):
        __metaclass__ = MyMeta
        x = 1
    

    关于python - python 类 __init__ 方法会隐式返回 None 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13043359/

    相关文章:

    python - 在我的 Python 脚本中的模块之间共享记录器实例的惯用方法是什么?

    python - 高效读取文件中的某一行

    python - Firebase .validate 无法按预期使用 $location

    Python SocketServer死锁问题

    python - Flask 中从字符串到 unixepoch 的日期转换

    python - 在 python 中使用 os.popen 转换 linux 命令

    python - 为什么 Selenium 在 Chrome 和 Firefox 中可以单击单选按钮,但在 IE 9 中却失败?

    python - 如何使用 pandas 取消数据透视

    python - 在附加模式下,我的文件是否在 RAM 中打开?

    python - 批量保存复杂对象 SQLAlchemy