我尝试在类构造函数( init )中返回一个值:
class A:
def __init__(self):
return 1
但是有一个运行时错误,说 init 应该返回None。如果是这种情况,如何理解:
a=A()
其中" a"被指定为类实例?
答案 0 :(得分:27)
严格地说,创建实例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)
然后调用新传入的对象传递给它“initilize”对象考虑以下演示:
当我们覆盖__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__
的{{1}}仍为type
。
所以这是一个显示元类,类之间关系的图表, 实例:
type
当调用元类 instantiate instantiate
metaclass --------------> class ----------------> instance
type.__new__() object.__new__()
来创建新类时,类似的流程如下:
type
已被罚款type.__call__()
分配内存,然后返回一个新类(元类实例),然后调用type.__new__()
。type.__init__()
初始化从步骤2传递的新创建的类。您甚至可以通过继承type.__init__()
:
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__
答案 1 :(得分:8)
它的工作原理如下:
你这样做:
a = A()
调用 A.__new__()
,并返回类A
的实例。
等效地:
a = A.__new__(A)
然后Python调用
a.__init__()
正如错误消息所示,不应返回值。
答案 2 :(得分:4)
如您所知,Python中的所有内容都是对象,类也不例外。类A
是一个方法__call__(...)
的对象,它允许您编写a = A()
之类的内容。在引擎盖下,A.__call__
将首先使用静态方法__new__
(具有合理的默认实现)创建对象,然后使用适当的构造函数args调用新对象的__init__
。
答案 3 :(得分:2)
__init__
应返回None
的要求是一个有意义的实现选择,它允许您依赖类型类的对象一致地返回一个对象的事实
类的实例类型。在许多其他语言中也是如此,例如C ++。
如果实施方式不同,会造成无用的混淆。