__Python中的new_uu和_uuinit_uuu
我正在学习Python,到目前为止,我可以讲述以下关于__Python中的new_uu和_uuinit_uuu,python,class,Python,Class,我正在学习Python,到目前为止,我可以讲述以下关于\uuu new\uuu和\uuu init\uuu的内容: \uuuu new\uuuu用于对象创建 \uuuu init\uuuu用于对象初始化 \uuuuuu new\uuuuu在\uuuuu init\uuuuuu作为\uuuuu new\uuuuu返回一个新实例,然后调用\uuuuu init\uuuuuuu,以初始化内部状态 \uuuuu new\uuuuuu适用于不可变对象,因为一旦分配它们,它们就无法更改。因此,我们可以返回具
\uuu new\uuu
和\uuu init\uuu
的内容:
\uuuu new\uuuu
用于对象创建\uuuu init\uuuu
用于对象初始化\uuuuuu new\uuuuu
在\uuuuu init\uuuuuu
作为\uuuuu new\uuuuu
返回一个新实例,然后调用\uuuuu init\uuuuuuu
,以初始化内部状态\uuuuu new\uuuuuu
适用于不可变对象,因为一旦分配它们,它们就无法更改。因此,我们可以返回具有新状态的新实例\uuuuu new\uuuu
和\uuuu init\uuuu
,因为它的内部状态可以更改a=MyClass(“hello”,“world”)
时,这些参数是如何传递的?我的意思是我应该如何使用\uuuu init\uuuu
和\uuu new\uuuuu
构造类,因为它们是不同的,除了默认的第一个参数之外,它们都接受任意参数self
关键字的名称是否可以更改为其他名称?但我想知道cls
是在名称方面,还是会更改为其他名称,因为它只是一个参数名称>>> class MyClass(tuple):
def __new__(tuple):
return [1,2,3]
我做到了以下几点:
>>> a = MyClass()
>>> a
[1, 2, 3]
尽管我说我想返回元组
,但这段代码运行良好,并返回了我[1,2,3]
。我知道在调用\uuuu new\uuuu
函数后,我们将第一个参数作为我们想要接收的类型进行传递。我们正在谈论新的功能,对吗?除了绑定类型,我不知道其他语言的返回类型
我还做了其他事情:
>>> issubclass(MyClass,list)
False
>>> issubclass(MyClass,tuple)
True
>>> isinstance(a,MyClass)
False
>>> isinstance(a,tuple)
False
>>> isinstance(a,list)
True
我没有做更多的实验,因为更远的地方不亮,我决定停在那里,决定问斯塔克
我看到的这些帖子是:
我应该如何使用\uuuu init\uuuu
和\uuu new\uuuuu
构造类,因为它们是不同的,除了默认的第一个参数外,它们都接受任意参数
您很少需要担心\uuuuu new\uuuuu
。通常,您只需定义\uuuuu init\uuuu
,并让默认的\uuuu new\uuuuu
将构造函数参数传递给它
self
关键字的名称是否可以更改为其他名称?但我想知道cls
是在名称方面,还是会更改为其他名称,因为它只是一个参数名称
两者都只是参数名,在语言中没有特殊意义。但是它们的使用在Python社区是一个非常强大的惯例;大多数Pythonistas在这些上下文中永远不会更改名称self
和cls
,当其他人更改时,他们会感到困惑
请注意,使用def\uuuu new\uuu(tuple)
在构造函数中重新绑定名称tuple
。在实际实现\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
时,您需要按照以下
def __new__(cls, *args, **kwargs):
# do allocation to get an object, say, obj
return obj
尽管我说我想返回元组
,但这段代码运行良好,并返回了我[1,2,3]
MyClass()
将具有\uuuu new\uuu
返回的值。Python中没有隐式类型检查;程序员有责任返回正确的类型(“我们都在这里”)。能够返回与请求不同的类型对于实现工厂非常有用:您可以返回请求类型的子类
这也解释了您观察到的issubclass
/isinstance
行为:使用class MyClass(tuple)
时会产生子类关系,isinstance
反映了您从\uuuuuuuu new\uuuuuu
返回的“错误”类型
如需参考,请查看Python语言参考中的
编辑:好的,下面是一个使用\uuuu new\uuuu
的潜在有用示例。类Eel
跟踪过程中有多少条鳗鱼存活,如果超过某个最大值,则拒绝分配
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
请注意,有很多方法可以完成此行为。@Braveyard:inherit from
object
获取\uuuuuuu new\uuuu
。事实上,除非您正在为非常旧的Python版本编写向后兼容的代码,否则最好始终从对象继承。在Python3中,旧样式的类已经消失,而类定义中隐含了从对象继承的内容。您不应该从\uuuuuuu新的调用\uuuuuuuu
,如果您返回类型为cls
的实例,Python将自己完成这项工作。我想补充一点,能够从\uuuuuu new\uuuuu
返回某些内容的看似奇怪的行为(至少在理论上)是有用的。我可以想象类似于BalancedBinaryTree
类的东西,它可以从列表中初始化。它有LeafNode
和EmptyTree
的子类,如果输入列表中有0或1个元素,则\uuuuuuuuuuu
返回其中一个。本质上,这意味着您可以实现工厂,而不需要看起来是工厂,因此您可以更改您的类是使用工厂还是直接实例化,而不必破坏您的接口。我认为存在一个bug,它应该是类型(self)。n_eels-=1
,不self.n_-eels-=1
。在讨论您的鳗鱼示例之前,我给了您+1。希望我能再给你一个