如何从以_init__参数为条件的对象实例中删除方法?

2024-04-23 12:05:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我想编写一个类,在访问某个特定方法时删除对该方法的访问或抛出一个错误,并且这种行为应该由类实例化时设置的变量进行调节

因此,在代码中,我希望如下所示:

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()

这很好,但是,如果我想有两个这样的方法,那么我必须复制粘贴到每个方法这2行。这“似乎不是很复杂”,我想知道是否存在一种“更好的”/“干燥的方法”

我考虑过使用decorator,但decorator在类执行时执行,因此它们似乎不适合此任务,因为属性has_non_available_method(在本例中)将不会在该点设置


3条回答

一个装饰师是完美的

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

使用装饰器

  • 我添加了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

  • 您可以尝试delattrdel动态删除类方法

代码:

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

您可以使用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')

相关问题 更多 >