我可以“挂钩”变量重新分配吗?

cat*_*cat 3 python variables

Python 是一种可以实现以下功能的语言:

>>> class A(object):
...  def __eq__(self, _):
...   return True
... 
>>> a = A()
>>> a == "slfjghsjdfhgklsfghksjd"
True
>>> a == -87346957234576293847658734659834628572384657346573465
True
>>> a == None
True
>>> a is None
False
Run Code Online (Sandbox Code Playgroud)

其他东西,比如gtlt也可以通过这种方式“重载” 1,在我看来,这是一个很棒的功能。

我很好奇赋值运算符是否也可以以类似的方式=“重载” 1 ,或者我是否必须将 Python 重新编译为NotPython才能执行此操作。

(据我所知,类和对象不实现某些__assign__方法;这是使用 C 字节码运行器/编译器实现的。)

具体来说,我想通过迭代令牌列表来实现 LL( k ) 解析器,而不使用迭代器,这样我就可以任意更改迭代器的索引以跳转到给定令牌。

问题是,在给定的循环周期中,如果我已经任意修改了索引以准备下一个周期(我肯定会做很多事情),我想做的最后一件事就是通过以下方式弄乱该变量给它加一,就好像它没有被改变一样。

也许最简单、最简单的解决方案是在跳转时设置一个标志,并在False每个周期重置该标志,但这可能并且会引入我想提前避免的微小隐藏错误。(请参阅此处了解我的意思 - 这是我正在重写的可悲的迭代 LL( 1 ) 解析器,我希望它的转世在某种程度上可维护和/或可读。)

标志解决方案:

idx = 0
while True:
  jmpd = False
  # maybe we jumped, maybe we didn't; how am I to know!?!?
  if jmpd == False:
    idx += 1 
Run Code Online (Sandbox Code Playgroud)

伟大的!一个很大的缺点:在导致索引任意更改的每个可能的分支中,我必须设置该标志。也许是微不足道的(显然在这个例子中),但对我来说,这似乎是不可读的、容易出错的代码的预兆。

在不使用第二个变量的情况下测试某个值是否随时间变化的最佳方法是什么?

如果您的答案是“没有,只需保持安静并使用标志变量”,那么我祝贺您提倡糟糕的代码设计。/秒


1是的,我知道这在技术上不是运算符重载;你有更好、更容易理解的术语吗?

Yar*_*min 5

您可以使用另一种魔术方法来拦截属性的分配。它被称为__setattr__(). 以下是如何使用它的示例:

In [2]: class Test(object):
    def __setattr__(self, name, value):
        print(name, "changed to", value)
        super().__setattr__(name, value)
   ...:

In [3]: t = Test()

In [4]: t.name = 4
name changed to 4

In [5]: t.name = 5
name changed to 5
Run Code Online (Sandbox Code Playgroud)