Python中实例的动态装饰方法

Dynamically decorating method of instance in Python

提问人:jeandut 提问时间:9/1/2023 更新时间:9/1/2023 访问量:28

问:

我最近遇到了一些可以做一些可以说是黑客但有趣的事情,例如:MethodType

from types import MethodType
class MyClass():
    def __init__(self, n : int):
        self.list_of_items = list(range(n))
    def __getitem__(self, idx):
        return self.list_of_items[idx]
    def foo(self):
        return "foo"

def bar(self):
    return "bar"
a = MyClass(10)
a.foo = MethodType(bar, a)
a.foo()
## prints bar
a[0]
# 0 (int) is printed

但是,如果我想以类似的精神动态装饰呢? 我想到的第一个想法是:__getitem__a

def new_getitem(self, idx):
    return str(self.__getitem__(idx))
a.__getitem__ = MethodType(new_getitem, a)

但是,这有两个问题:第一,第一。 在语法未修改的意义上不会更改。__getitem__[]

a[0]
# 0 (int) is printed

这可以通过在实例的初始化中发生的一些有趣的业务来解释,以链接到最糟糕的是显式调用:[]__getitem____getitem__

a.__getitem__(0)

当我们无限地重新定义时,会遇到无限递归。__getitem__

我想知道是否有一种语法允许执行此黑客,以便:

a[0] = "0" (string)

我对任何允许动态影响实例的解决方案持开放态度(使用 MethodType 不是必需的)。[]

Python 方法 动态 实例

评论

0赞 RomanPerekhrest 9/1/2023
如果将其更改为:?def new_getitem(self, idx): return str(self[idx])
0赞 jeandut 9/1/2023
@RomanPerekhrest好主意!2. 现在解决了无限递归,但 [] 语法不受影响,因为 1.又名 a.__getitem__(0) 有效,但 a[0] 无效。
0赞 jeandut 9/1/2023
事实上,如果我们成功解决了 1.通过您的修复,我们最终可能会无限递归,因为我们想要的是最终实际更改 self[idx]。我想过使用deepcopys,但它感觉不自然,容易出现更复杂的问题。
0赞 RomanPerekhrest 9/1/2023
我根本不会那样做。动态覆盖是不可靠的。想要更改的行为 - 在此处创建或创建另一种方法来辅助表示数据a.__getitem____getitem__def __getitem__(self, idx) ...
0赞 jeandut 9/1/2023
是的,我的意思是它肯定是黑客,而不是好的做法,我同意你的看法。最简单的方法是从一开始就根据自我的属性使 getitem 的行为不同,然后动态更改此属性,但如果您对类/实例没有权力,这并不总是可能的,我只是想知道这是否可能。

答: 暂无答案