你可以在这里用__getattribute__
,意思是:
In [1]: class MyClass:
...: def __init__(self) -> None:
...: self.acting = False
...: self.att1 = None
...: self.att2 = None
...: self.att3 = None
...:
...: def __getattribute__(self, attribute):
...: if attribute.startswith("set_") and not self.acting:
...: raise RuntimeError(f"{self} is not acting")
...: return super().__getattribute__(attribute)
...:
...: def set_att1(self, value):
...: self.att1 = value
...:
...: def set_att2(self, value):
...: self.att2 = value
...:
...: def set_att3(self, value):
...: self.att3 = value
...:
...: def switch_acting(self):
...: self.acting = not self.acting
...:
In [2]: instance = MyClass()
In [3]: instance.set_att1(10)
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-3-ead9d2b57142> in <module>
----> 1 instance.set_att1(10)
<ipython-input-1-585c5de84d26> in __getattribute__(self, attribute)
8 def __getattribute__(self, attribute):
9 if attribute.startswith("set_") and not self.acting:
---> 10 raise RuntimeError(f"{self} is not acting")
11 return super().__getattribute__(attribute)
12
RuntimeError: <__main__.MyClass object at 0x7f9a00520af0> is not acting
In [4]: instance.switch_acting()
In [5]: instance.set_att1(10)
In [6]: instance.att1
Out[6]: 10
但是,正如注释中所指出的,这将在查找属性时判断self.acting
标志,而不一定是在调用方法时判断.
我们可以更仔细地处理验证应该在方法is called而不是被访问时发生的事实:
class MyClass:
def __init__(self) -> None:
self.acting = False
self.att1 = None
self.att2 = None
self.att3 = None
def __getattribute__(self, attribute):
if attribute.startswith("set_"):
bound_method = super().__getattribute__(attribute).__get__(self, type(self))
def _wrapper(*args, **kwargs):
if not self.acting:
raise RuntimeError(f"{self} is not acting")
return bound_method(*args, **kwargs)
return _wrapper
return super().__getattribute__(attribute)
def set_att1(self, value):
self.att1 = value
def set_att2(self, value):
self.att2 = value
def set_att3(self, value):
self.att3 = value
def switch_acting(self):
self.acting = not self.acting
演示:
In [29]: instance = MyClass()
In [30]: instance.set_att1(10)
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-30-ead9d2b57142> in <module>
----> 1 instance.set_att1(10)
<ipython-input-28-53d1a32f1498> in _wrapper(*args, **kwargs)
11 def _wrapper(*args, **kwargs):
12 if not self.acting:
---> 13 raise RuntimeError(f"{self} is not acting")
14 return bound_method(*args, **kwargs)
15 return _wrapper
RuntimeError: <__main__.MyClass object at 0x7f99e05bf340> is not acting
In [31]: instance.switch_acting()
In [32]: instance.set_att1(10)
In [33]: instance.att1
Out[33]: 10
In [34]: f = instance.set_att2
In [35]: instance.switch_acting()
In [36]: f(20)
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-36-a5c3c0536773> in <module>
----> 1 f(20)
<ipython-input-28-53d1a32f1498> in _wrapper(*args, **kwargs)
11 def _wrapper(*args, **kwargs):
12 if not self.acting:
---> 13 raise RuntimeError(f"{self} is not acting")
14 return bound_method(*args, **kwargs)
15 return _wrapper
RuntimeError: <__main__.MyClass object at 0x7f99e05bf340> is not acting
In [37]: instance.switch_acting()
In [38]: f(20)
In [39]: instance.att2
Out[39]: 20
编辑:我想我做的与你想要的相反,但同样的方法应该有效,只需勾选if self.acting
而不是if not self.acting