【问题标题】:Why is `self` in Python objects immutable?为什么 Python 对象中的“self”是不可变的?
【发布时间】:2009-06-18 22:51:21
【问题描述】:

为什么我不能执行如下操作:

class Test(object):
    def __init__(self):
        self = 5

t = Test()
print t

我希望它打印5,因为我们正在用它覆盖实例,但它根本不做任何事情。甚至不会抛出错误。只是忽略分配。

我知道几乎没有人愿意这样做,但你不能这样做似乎仍然很奇怪。

更新:我现在明白了为什么它不起作用,但我仍然想知道是否有任何方法可以从实例中替换实例.

【问题讨论】:

  • “从内部”,不是真的:我建议的 new 属于类,而不是实例。您通常可以更改大多数对象的 class 和/或状态(通过 dict)(“大多数”,因为有些是不可变的和/或不使用 dict),但不是对象的 IDENTITY - id(obj) 在您更改之前和之后将是相同的。 Telemachus' Ship 浮现在脑海中,但另一个主题似乎更适合另一个问题,因为它与这个主题的标题无关。
  • -1:替换实例打破了一个基本概念:对象具有唯一标识。返回一个新实例——即一个工厂——是有道理的。你想做什么?

标签: python object


【解决方案1】:

Anyany 函数的 any 参数的简单赋值在 Python 中的行为方式完全相同:将该名称绑定到不同的值,然后什么都不做。正如 Python 之禅所说,“没有任何特殊情况足以打破规则”!-)

因此,远非奇怪(简单地=分配给特定函数中的特定参数没有任何外部可见的影响),如果这种特定情况在任何情况下都有效,那将是完全惊人其他方式,只是因为有问题的函数和参数的名称。

如果你想创建一个类来构造一个不同于自身类型的对象,这种行为当然是很有可能的——但它是通过重写特殊方法__new__ 获得的,不是 __init__:

class Test(object):
    def __new__(cls):
        return 5

t = Test()
print t

确实发出5。 Python 中的__new__ / __init__ 行为是“两步构造”设计模式的一个示例:“构造函数”本身就是__new__(它构建并返回一个(通常未初始化的)对象(通常是一个新的)有问题的类型/类);__init__ 是正确初始化新对象的“初始化程序”。

例如,这允许构造一旦构造就不可变的对象:在这种情况下,所有事情都必须在构造不可变对象之前在__new__ 中完成,因为鉴于对象是不可变的,__init__无法对其进行变异以对其进行初始化。

【讨论】:

  • 啊,有道理。你知道我将如何实现我的目标吗?
  • 已经编辑了答案来解释:使用 new,“构造函数正确”,而不是 init,“初始化程序”。
【解决方案2】:

它不会“忽略”分配。分配工作正常,您创建了一个指向数据的本地名称 5.

如果你真的想做你正在做的事......

class Test(object):
    def __new__(*args):
        return 5

【讨论】:

  • 确实如此。但是手头的真正任务是从实例中替换实例,而这实际上并没有做到这一点。
【解决方案3】:

我刚刚运行了一个快速测试,你可以分配给自己。在你的 init() 方法中,打印出 self 的值。你会看到它是 5。

您在这里缺少的是参数在 Python 中按值传递。因此,更改函数或方法中变量的值不会为外界改变它。

话虽如此,我强烈建议不要改变自己。

【讨论】:

  • 我同意改变自我是一个糟糕的想法。但是很高兴知道是否有任何方法可以从实例中替换实例。
【解决方案4】:

博士。 Egon Spengler:那会很糟糕。
Peter Venkman 博士:我对整个好/坏的事情都一头雾水。 “坏”是什么意思?
Egon Spengler 博士:试着想象一下你所知道的所有生命都会瞬间停止,你体内的每个分子都以光速爆炸。

【讨论】:

  • 不会是那么坏。例如,这是 Smalltalk 中的一个众所周知的习语,Smalltalk 程序员通常不会让他们体内的每个分子都以光速爆炸......我认为 grin
  • 对。那很糟。好的。好的。重要的安全提示。谢谢,安东尼。
【解决方案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;
            }
    }
    

    我不明白这有什么意义。用值替换实例?

    【讨论】:

    • 怎么没有意义?这与执行以下操作相同: $test = new Test(); $测试 = 5;但从内部而不是外部。
    猜你喜欢
    • 2017-05-02
    • 1970-01-01
    • 2011-06-02
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 2011-02-27
    相关资源
    最近更新 更多