它可能会过载Python分配吗?

2024-05-15 22:21:13 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有一种神奇的方法可以重载赋值运算符,比如__assign__(self, new_value)

例如,我想禁止重新绑定:

class Protect():
  def __assign__(self, value):
    raise Exception("This is an ex-parrot")

var = Protect()  # once assigned...
var = 1          # this should raise Exception()

有可能吗?是不是疯了?我应该吃药吗?


Tags: 方法selfnewisvaluevardefexception
3条回答

不,因为赋值是没有修改挂钩的language intrinsic

你这样描述是绝对不可能的。对名称的赋值是Python的一个基本特性,并且没有提供任何钩子来更改其行为。

但是,通过重写.__setattr__(),可以根据需要控制类实例中成员的赋值。

class MyClass(object):
    def __init__(self, x):
        self.x = x
        self._locked = True
    def __setattr__(self, name, value):
        if self.__dict__.get("_locked", False) and name == "x":
            raise AttributeError("MyClass does not allow assignment to .x member")
        self.__dict__[name] = value

>>> m = MyClass(3)
>>> m.x
3
>>> m.x = 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in __setattr__
AttributeError: MyClass does not allow assignment to .x member

注意,有一个成员变量_locked,它控制是否允许赋值。您可以解锁它以更新值。

我觉得不可能。在我看来,赋值给变量对它之前引用的对象没有任何作用:只是变量现在“指向”了另一个对象。

In [3]: class My():
   ...:     def __init__(self, id):
   ...:         self.id=id
   ...: 

In [4]: a = My(1)

In [5]: b = a

In [6]: a = 1

In [7]: b
Out[7]: <__main__.My instance at 0xb689d14c>

In [8]: b.id
Out[8]: 1 # the object is unchanged!

但是,您可以通过使用引发异常的__setitem__()__setattr__()方法创建包装器对象来模拟所需的行为,并在其中保留“不可更改”的内容。

相关问题 更多 >