我试图在类构造函数(init)中返回一个值:
class A:
def __init__(self):
return 1
但是有一个运行时错误说init应该返回 None。如果是这种情况,如何理解:
a=A()
其中“a”被分配为类实例?
我试图在类构造函数(init)中返回一个值:
class A:
def __init__(self):
return 1
但是有一个运行时错误说init应该返回 None。如果是这种情况,如何理解:
a=A()
其中“a”被分配为类实例?
严格来说,这并不是A.__new__()
在创建实例a
。
当您定义class A(object):
(或者class A:
如果您使用的是 Python3,class A:
是已弃用的旧式类)时,它来自被调用以创建实例__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
现在,通过 using 返回一个新实例,object.__new__
您将看到 after也会被调用:__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
所以这里有一张图,显示了metaclass、class、 instance之间的关系:
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
它是这样工作的:
你做:
a = A()
A.__new__()
被调用,并返回类的一个实例A
。
等效地:
a = A.__new__(A)
然后 Python 调用
a.__init__()
正如错误消息所说,它不应该返回一个值。
如您所知,Python 中的一切都是对象,类也不例外。类A
是一个具有方法的对象,__call__(...)
它允许您编写诸如a = A()
. 在后台,将首先使用静态方法(具有合理的默认实现)A.__call__
创建一个对象,然后使用适当的构造函数参数调用新对象。__new__
__init__
__init__
应该返回的要求None
是一个有意识的实现选择,它让您依赖于类类型的对象始终返回类实例类型的对象这一事实。在许多其他语言(例如 C++)中也是如此。
如果以不同的方式实施,它将造成无用的混乱。