[英]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.