簡體   English   中英

當給定方法不存在時,在類中調用另一個方法?

[英]Call another method in a class when the given method does not exist?

說我有一個包含幾個功能的類。

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

當用戶實例化一個Person時,我希望他們能夠調用該類的任何方法。 如果所請求的方法不存在(例如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"

但是,我不知道這種魔術方法。

有沒有辦法使一個類中不存在的方法重定向到另一個類?

最終用戶不必做任何事情很重要-從他們的角度來看,它應該可以工作。

捕獲未定義屬性的標准方法是使用__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}'")

您的用戶可能會發現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__ ,以便訪問被調用的不存在的方法的名稱和參數。

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM