Python中的__new__和__init__
我正在学习Python,到目前为止,我可以告诉下面关于__new__
和__init__
:
-
__new__
是用于创build对象的 -
__init__
用于对象初始化 - 在
__init__
之前调用__new__
因为__new__
返回一个新的实例,之后调用__init__
来初始化内部状态。 -
__new__
适用于不可变对象,因为它们一旦被赋值就不能被修改。 所以我们可以返回具有新状态的新实例。 - 我们可以使用
__new__
和__init__
这两个可变对象,因为它的内部状态是可以改变的。
但是我现在还有其他问题。
- 当我创build一个新的实例如
a = MyClass("hello","world")
,这些参数是如何传递的? 我的意思是我应该如何使用__init__
和__new__
构造类,因为它们是不同的,除了缺省的第一个参数,它们都接受任意的参数。 -
self
关键字是在名称方面可以改成别的东西? 但是我想知道cls
在名称方面是可以改变的,因为它只是一个参数名称?
我做了一些如下的实验:
>>> class MyClass(tuple): def __new__(tuple): return [1,2,3]
我在下面做了:
>>> a = MyClass() >>> a [1, 2, 3]
尽pipe我说我想返回tuple
,这个代码工作正常,并返回我[1,2,3]
。 我知道,一旦调用了__new__
函数,我们将第一个参数作为我们想要接收的types传递。 我们在谈论New
function的权利? 我不知道其他语言返回types以外的绑定types?
我也做了一些其他的事情:
>>> issubclass(MyClass,list) False >>> issubclass(MyClass,tuple) True >>> isinstance(a,MyClass) False >>> isinstance(a,tuple) False >>> isinstance(a,list) True
我没有做更多的实验,因为进一步不明亮,我决定在那里停下来,并决定问StackOverflow。
我读的SOpost:
- Python对象的创build
- Python使用__new__和__init__?
我应该如何使用
__init__
和__new__
构造类,因为它们是不同的,除了默认的第一个参数,它们都接受任意的参数。
你很less会担心__new__
。 通常,您只需定义__init__
并让默认的__new__
传递构造函数参数。
self
关键字是在名称方面可以改成别的东西? 但是我想知道cls
在名称方面是可以改变的,因为它只是一个参数名称?
两者都只是参数名称,在语言中没有特殊含义。 但是它们的使用在Python社区中是一个非常强大的约定。 大多数Pythonistas将永远不会改变这些上下文中的名称self
和cls
,并且会在其他人做的时候感到困惑。
请注意,您使用def __new__(tuple)
重新绑定构造函数中的名称tuple
。 当实际实现__new__
,你会想要这样做
def __new__(cls, *args, **kwargs): # do allocation to get an object, say, obj return obj
尽pipe我说我想返回
tuple
,这个代码工作正常,并返回我[1,2,3]
。
MyClass()
将具有__new__
返回的值。 Python中没有隐式types检查; 程序员有责任返回正确的types(“我们都是在这里同意的成年人 ”)。 能够返回不同于请求的types对于实现工厂很有用:您可以返回所请求types的子类。
这也解释了您观察到的issubclass
/ isinstance
行为:子类关系跟随您使用class MyClass(tuple)
, isinstance
反映您从__new__
返回“错误”types。
作为参考,请查看Python语言参考中 对__new__
的要求 。
编辑 :好吧,这是一个可能有用的__new__
。 Eel
类跟踪有多less鳗鱼在这个过程中活着,拒绝分配,如果这超过了一些最大值。
class Eel(object): MAX_EELS = 20 n_eels = 0 def __new__(cls, *args, **kwargs): if cls.n_eels == cls.MAX_EELS: raise HovercraftFull() obj = super(Eel, cls).__new__(cls) cls.n_eels += 1 return obj def __init__(self, voltage): self.voltage = voltage def __del__(self): type(self).n_eels -= 1 def electric(self): """Is this an electric eel?""" return self.voltage > 0
请注意,有更聪明的方法来完成这一行为。