为什么 Python 对象中的“self”是不可变的?
- 2025-03-21 09:06:00
- admin 原创
- 38
问题描述:
为什么我不能执行如下操作:
class Test(object):
def __init__(self):
self = 5
t = Test()
print t
我本来希望它能够打印,5
因为我们用它覆盖了实例,但它什么都没做。甚至没有抛出错误。只是忽略了分配。
我知道很少有人愿意这样做,但你不能这样做似乎还是很奇怪。
更新:我现在明白为什么它不起作用,但我仍然想知道是否有任何方法可以从实例内部替换实例。
解决方案 1:
对任何函数的任何参数的任何简单赋值在 Python 中的行为都完全相同:将该名称绑定到不同的值,而不执行任何其他操作。正如 Python 之禅所说,“没有特殊情况足以打破规则”!-)
因此,这远非奇怪(即简单地分配给特定函数中的特定参数没有任何外部可见的效果),如果这种特定情况以任何其他方式起作用,那将是令人惊讶的,仅仅因为所讨论的函数和参数的名称。
如果你想创建一个类来构造一个不同于其自身的类型对象,这种行为当然是完全可能的 —— 但它是通过重写特殊方法获得的__new__
,而不是 __init__
:
class Test(object):
def __new__(cls):
return 5
t = Test()
print t
这确实会发出5
。Python中的__new__
/__init__
行为是“两步构造”设计模式的一个示例:正确的“构造函数”是__new__
(它构建并返回一个(通常未初始化的)对象(通常是所讨论类型/类的新对象);__init__
是正确初始化新对象的“初始化程序”。
例如,这允许构造一旦构造就不可变的对象:在这种情况下,必须在__new__
构造不可变对象之前完成所有操作,因为鉴于该对象是不可变的,__init__
因此无法通过变异来初始化它。
解决方案 2:
它不会“忽略”分配。分配工作正常,您创建了一个指向数据 5 的本地名称。
如果你真的想做你正在做的事情……
class Test(object):
def __new__(*args):
return 5
解决方案 3:
我刚刚进行了快速测试,您可以将其分配给self
。在您的__init__()
方法中,打印出 的值self
。您会看到它是 5。
您忽略的是,Python 中的参数是通过值传递的。因此,在函数或方法中更改变量的值不会改变外界对其的影响。
尽管如此,我还是强烈建议不要进行任何改变self
。
解决方案 4:
埃贡·斯宾格勒博士:那会很糟糕。
彼得·文克曼博士:我搞不清楚这到底是好事还是坏事。你指的“坏”是什么意思?
埃贡·斯宾格勒博士:试想一下,你所知道的所有生命瞬间停止,你体内的每一个分子都以光速爆炸。
解决方案 5:
有时你想这样做,但不能使用如下不可变类型int
:
>>> class Test(list):
... def __init__(self):
... list.__init__(self, [1,2,3]) # self = [1,2,3] seems right, but isn't
>> t = Test()
>> print t
[1, 2, 3]
解决方案 6:
class Test(object):
def __init__(self):
self = 5
t = Test()
print t
就像有这个 PHP(我只知道其他语言,抱歉)
class Test {
function __construct() {
$this = 5;
}
}
我不明白这有什么意义。用值替换实例?
扫码咨询,免费领取项目管理大礼包!