我有一个类,它有自己的几个方法,为了简单起见,这里没有显示:
class Foo:
def __init__(self, arg: str):
self.bar = arg
比如说,除了它自己的方法,我希望Foo
的示例使用str
的方法来代替bar
属性(确保是字符串)。这可以通过__getattr__
dunder方法实现:
class Foo:
def __getattr__(self, item):
return getattr(self.foo, item)
调用的结果应该是.bar
的新值。然而,由于Python字符串是不可变的,因此方法调用(例如str.strip()
)产生的字符串需要重新赋值,这看起来不太好。此外,如果调用没有返回字符串,则需要if
:
result = instance_of_Foo.strip()
if isinstance(result, str):
instance_of_Foo.bar = result
else:
...
我和一个装潢师解决了这个问题:
def decorator(function, *, self):
def wrapper(*args, **kwargs):
result = function(*args, **kwargs)
if isinstance(result, str):
self.bar = result
else:
return result
return wrapper
class Foo:
def __init__(self, arg: str):
self.bar = arg
def __getattr__(self, item):
method = decorator(getattr(self.bar, item), self = self)
return method
foo = Foo(' foo ')
print(foo.bar) # ' foo '
foo.strip()
print(foo.bar) # 'foo'
...但肯定有一种更“Python”的方式,最好使用dunder方法而不是装饰器来拦截调用,不是吗?请注意,我的类不能替换字符串(违反Liskov原则),所以继承是不可能的。
2条答案
按热度按时间s8vozzvw1#
你不仅仅是把对字符串方法的调用委托给一个底层的字符串属性。你是在尝试使用字符串方法调用的结果来修改属性。这本身应该由你的 Package 类上的一个单独的方法来处理。
传递一个字符串,而不是一个显式的未绑定方法,在处理
str
的可能子类时效果更好。iqih9akk2#
回答我自己的问题:
您(或我)可以使用 Package 器缓存
__getattr__
dunder方法,但是chepner's answer应该是首选,因为它可以处理任意给定的函数,而且设计得更好。试试看: