说我有一个简单的类Foo
,它来自外部库,因此我不能直接更改它:
class Foo(object):
def __init__(self, x):
self.x = x
我想创建一个子类
Bar
并防止x
从Bar
实例更改,但仍在x
的方法中使用Bar
。这是我尝试过的方法,它可能会启发基本概念,但不幸的是,它不起作用:
class Bar(Foo):
@property
def x(self):
return super().x
@x.setter
def x(self, value):
raise NotImplementedError('Do not change x directly, use "do_stuff()" instead')
def do_stuff(self, value):
if <something>:
super().x = value
因此,基本上我已经围绕属性创建了一些包装函数(
do_stuff()
),现在我想防止直接更改该属性,因为这可能会使包装函数的某些功能困惑。这有可能以合理的方式吗?编辑了,其中提供了我想要的更好示例。我不是要阻止他们看到变量
x
,而是要从do_stuff()
外部进行更改 最佳答案
如果您完全希望避免继承,则这应该更容易实现:
def main():
bar = Bar(123)
bar.fizz()
bar.buzz()
bar.fizz()
bar.set_x(456)
print('bar.x =', bar.x)
try:
bar.x = 123
except AttributeError:
print('bar.x cannot be set directly')
else:
raise AssertionError('an AttributeError should have been raised')
bar.mutate_x(789)
bar.fizz()
bar.set_x(0)
bar.fizz()
bar.mutate_x(1)
bar.fizz()
bar.set_x('Hello World')
bar.fizz()
class Foo:
def __init__(self, x):
self.x = x
def fizz(self):
print(self.x)
def buzz(self):
self.x = None
class Bar:
def __init__(self, x):
self.__foo = foo = Foo(x)
self.__copy_methods(foo)
def __copy_methods(self, obj):
for name in dir(obj):
if name.startswith('__') or name.endswith('__'):
continue
attr = getattr(obj, name)
if callable(attr):
setattr(self, name, attr)
@property
def x(self):
return self.__foo.x
def set_x(self, value):
if isinstance(value, int) and value > 0:
self.__foo.x = value
mutate_x = set_x
if __name__ == '__main__':
main()
关于python - 防止从子类访问实例变量,而不会影响基类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33368552/