当给定的方法不存在时调用类中的另一个方法?

2024-06-15 18:39:09 发布

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

假设我有一个包含几个函数的类。你知道吗

class Person:
    def __init__(self): pass
    def say(self, speech): pass
    def walk(self, destination): pass
    def jump(self): pass

当用户实例化一个人时,我希望他们能够调用类的任何方法。如果请求的方法不存在(例如Person.dance()),则应该调用默认函数。你知道吗

我想这可以通过理论上的魔法方法来实现-

class Person:
    def __init__(self): pass
    def say(self, speech): pass
    def walk(self, destination): pass
    def jump(self): pass
    def sleep(self): print("Zzz")

    def __method__(self, func):
        if func.__name__ not in ['say','walk','jump']:
            return self.sleep
        else
            return func

billy = Person()
billy.dance()
>> "Zzz"

然而,我知道没有这种神奇的方法。你知道吗

有没有办法让一个类中不存在的方法重定向到另一个类?你知道吗

重要的是,最终用户不必做任何事情-从他们的角度来看,它应该只是工作。你知道吗


Tags: 方法函数selfinitdefpassdestinationspeech
3条回答

您的用户可能会发现API行为令人困惑。然而,如果你确定你需要这种模式,你可以尝试类似的方法

# getattr will get the function attribute by a string name version
# None is returned if no function is found
my_func = getattr(self, 'my_func', None)

# callable ensures `my_func` is actually a function and not a generic attribute
# Add your if-else logic here
if callable(my_func):
    my_func(args)
else:
    ...

捕获未定义属性的标准方法是使用__getattr__

# But see the end of the answer for an afterthought
def __getattr__(self, attr):
    return self.sleep

Python不区分“常规”属性和方法;方法调用从普通属性查找开始,其结果恰好是可调用的。也就是说

billy.run()

与相同

f = billy.run
f()

这意味着__getattr__将为任何未定义的属性调用;在查找时无法判断是否要调用结果。你知道吗


但是,如果您只想为一个公共方法定义“别名”,那么可以在class语句之后使用循环来实现。你知道吗

class Person:
    def __init__(self): pass
    def say(self, speech): pass
    def walk(self, destination): pass
    def jump(self): pass
    def do_all(self): pass

for alias in ["something", "something_else", "other"]:
    setattr(Person, alias, Person.do_all)

您也可以在的class语句中进行硬编码赋值,但是如果您提到的这种情况有数百种,那么这将是很难处理的:

class Person:
    def do_all(self): pass

    something = do_all
    something_else = do_all

(我没有尝试使用exec在循环中自动执行此类分配;这可能是可能的,但不建议这样做。)

您还可以将别名列表嵌入到__getattr__的定义中,想想看:

 def __getattr__(self, attr):
     if attr in ["something", "something_else", "other"]:
         return self.sleep
     else:
         raise AttributeError(f"type object 'Person' has no attribute '{attr}'")

您可以将“default”函数嵌套在__getattr__中,以便访问被调用的不存在的方法的名称和参数。你知道吗

class Test:
    def __getattr__(self, attr):
        def default(*args, **kwargs):
            return attr, args, kwargs
        return default

test = Test()
print(test.test('test'))
# ('test', ('test',), {})

相关问题 更多 >