我想写一个类,在访问特定方法的情况下删除访问或抛出错误,这种行为应该由类实例化时设置的变量决定。
所以在代码中我想这样写:class NewClass:
def __init__(self, has_non_available_method):
self.has_non_available_method = has_non_available_method
def some_method(self):
if self.has_non_available_method:
raise SomeError()
这很好,但是,如果我想有几个这样的方法,那么我必须复制粘贴这两行到每个方法。这看起来并不是很复杂我想知道是否存在"更好的"/DRY方法。
我考虑过使用装饰器,但是装饰器在类执行时执行,所以它们似乎不适合这个任务,因为属性has_non_available_method
(在这个例子中)在那个时候不会被设置。
一个装饰器是完美的。
def checkavail(func):
def wrapper(self, *args, **kwargs):
if self.has_non_available_method:
raise SomeError()
func(self, *args, **kwargs)
return wrapper
class NewClass:
def __init__(self, has_non_available_method):
self.has_non_available_method = has_non_available_method
@checkavail
def some_method(self):
# do stuff
你可以使用decorator使这个行为更动态。
def check_permission(method):
def call(self, *args, **kwargs):
if getattr(self, 'has_{}_permission'.format(method.__name__), False):
method(self, *args, **kwargs)
else:
raise Exception('{} needs permission'.format(method.__name__))
return call
class PermissionRequiredMethodClass(object):
def __init__(self, has_secret_method_permission: bool = False):
self.has_secret_method_permission = has_secret_method_permission
super().__init__()
def open_method(self):
print('in open method')
@check_permission
def secret_method(self):
# secret stuff
print('in secret')
use decorator
- 我添加了
decorate_all_functions
,所以你不需要复制粘贴装饰本身到每个类方法。
代码:
def decorate_all_functions(function_decorator):
def decorator(self):
for name, obj in vars(self).items():
if callable(obj):
try:
obj = obj.__func__
except AttributeError:
pass
setattr(self, name, function_decorator(obj))
return self
return decorator
from functools import wraps
def check_permission(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
if func.__name__ in self.has_non_available_method:
raise Exception("Some Error")
func(self,*args, **kwargs)
return wrapper
@decorate_all_functions(check_permission)
class NewClass:
has_non_available_method = []
def __init__(self, has_non_available_method):
self.has_non_available_method = has_non_available_method
def some_method(self):
print("do something")
def another_method(self):
print("do another thing")
x = NewClass(["another_method"])
x.some_method()
try:
x.another_method()
except Exception as e:
print(e)
结果:
do something
Some Error
使用del
- 您可以尝试
delattr
或del
动态删除类方法。
代码:
class NewClass:
def some_method(self):
print("do something")
def another_method(self):
print("do another thing")
x = NewClass()
x.some_method()
x.another_method()
delattr(type(x),"some_method")
# del NewClass.some_method
# both work
try:
x.some_method()
except Exception as e:
print(e)
x.another_method()
结果:
do something
do another thing
'NewClass' object has no attribute 'some_method'
do another thing
- 但是它会删除类方法,而不是实例。
y = NewClass()
y.some_method()#raise AttributeError