Re: [問題] function物件可以透過class呼叫嗎

看板Python作者 (梅郭曲)時間4年前 (2020/08/22 10:27), 4年前編輯推噓1(109)
留言10則, 2人參與, 4年前最新討論串2/2 (看更多)
我把原Po文章放在底下,方便對照。 試試我寫的程式碼, 看看有無達成你的需求。 麻煩特別注意一下註解的部份︰ ****************************************************************************** def nonMemberFunc(arg): print("nonMemberFunc is called with arg: " + str(arg)) class Logger(object): def __getfunc__(self, func, arg): print(func.__name__) ## 移除"func()"的括號,將傳入的func變成object並 ## 呼叫其 member "__name__" print(func) ## 移除"func()"的括號,將傳入的func變成object並 ## 印出其資訊 return func(arg) def method1(self, arg): print("method1 is called with argument: "+str(arg) + "\n") def method2(self, arg): print("method2 is called with argument: "+str(arg) + "\n") def method3(self, arg): print("method3 is called with argument: "+str(arg) + "\n") if __name__ == "__main__": L1 = Logger() L1.__getfunc__(L1.method1, "m1") L1.__getfunc__(L1.method2, "m2") L1.__getfunc__(L1.method1, "m3") L1.__getfunc__(nonMemberFunc, "nonMemberFuncArg") ****************************************************************************** 輸出結果: method1 <bound method Logger.method1 of <__main__.Logger object at 0x7f0ff113b9d0>> method1 is called with argument: m1 method2 <bound method Logger.method2 of <__main__.Logger object at 0x7f0ff113b9d0>> method2 is called with argument: m2 method1 <bound method Logger.method1 of <__main__.Logger object at 0x7f0ff113b9d0>> method1 is called with argument: m3 nonMemberFunc <function nonMemberFunc at 0x7f0ff112c1f0> nonMemberFunc is called with arg: nonMemberFuncArg ※ 引述《XperiaZ6C (索尼)》之銘言: : Python一個很方便的功能是函數可以當作參數傳遞 : 那請問我可以在class裡面取得調用的函數物件嗎 : 例如我想做到在函數被調用前 : 可以做其他處理 : 拿print來舉例好了 : 像是下面程式碼這樣 : class Logger(object): : def int(self, value): : print('Call int()') : return int(value) : def float(self, value): : print('Call float()') : return float(value) : logger = Logger() : logger.int('123') : logger.float('123') : 我只知道可以用下面的方法取得函數的名稱 : class Logger(object): : def __getattr__(self, name): : print('Call %s()' % name) : 但是函數物件要怎麼抓? : 像是如果我有20個函數的話 : 那class裡面就要寫20遍 : 如果之後又需要擴充到40個函數 : 那就還要在class裡面加40個 : 有沒有什麼方法是可以把logger.func()裡的func()直接抓來用的 : 例如什麼 : class Logger(object): : def __getfunc__(self, func, arg): : # do something : return func(arg) : 之類的 : 這樣我只要定義一個函數 : 後面不過擴充幾個需要做一樣處理的函數 : 我都不需要再增加class裡面的函數數量 : 感謝 : -- : ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.184.77.196 (臺灣) : ※ 文章網址: https://www.ptt.cc/bbs/Python/M.1598058491.A.1F6.html : ※ 編輯: XperiaZ6C (111.184.77.196 臺灣), 08/22/2020 09:11:06 : → gmccntzx1: 你的意思是,每當一個 member method 被呼叫時,就要 08/22 09:23 : → gmccntzx1: 抓到是誰被呼叫嗎? 08/22 09:23 : → gmccntzx1: 如果要的效果是這樣,我目前是有想到可以透過 metacla 08/22 09:25 : → gmccntzx1: ss 去做 08/22 09:25 : 也不算是member method被呼叫 : 因為像是int()一開始是沒有定義在class Logger裡面 : 之所以會在裡面定義是因為要在直接執行int()前做一些處理 : 假設今天有個函數是 ringing(1) : 那我不用管這個函數實際做了什麼 : 我只要用 logger.ringing(1) 這樣去呼叫它 : 這個Logger class就會在執行完預處理後直接return ringing(1) : 像是上面的概念這樣 : class Logger(object): : def __getfunc__(self, func, arg): : # do something : return func(arg) : ※ 編輯: XperiaZ6C (111.184.77.196 臺灣), 08/22/2020 09:51:15 : → gmccntzx1: 我釐清一下你想做的事:也就是說,任何一個沒有定義在 08/22 09:58 : → gmccntzx1: Logger class 裡的 function ‘foo’,只要透過 logg 08/22 09:58 : → gmccntzx1: er.foo() 這種方式呼叫,你就可以先透過 logger 去做 08/22 09:58 : → gmccntzx1: 你想做的事再讓那個 function 做自己的事囉? 08/22 09:58 : → gmccntzx1: 先說好了,如果要透過這種呼叫方式來達到這種功能是有 08/22 10:06 : → gmccntzx1: 點奇怪。雖然說你可以硬是透過 `__getattr__()` 讓 08/22 10:06 : → gmccntzx1: logger 在找不到 member method 時(也就是上述的情況 08/22 10:09 : → gmccntzx1: ),去其他 scope 找你要的 function ,如 globals() 08/22 10:11 : → gmccntzx1: 。但是這樣你就要自己處理 name resolution 的問題。 08/22 10:12 : → gmccntzx1: 再來,怎麼取得 caller 的 arguments 又是另一個問題 08/22 10:13 : → gmccntzx1: 但是如果你沒有需要處理 caller arguments 的話,那上 08/22 10:19 : → gmccntzx1: 面那個問題就省了 08/22 10:19 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.124.207.79 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Python/M.1598063228.A.DA5.html

08/22 10:33, 4年前 , 1F
痾,這樣並沒有達到原 PO 要的那種呼叫方式呀
08/22 10:33, 1F
加上一個未定義在Logger class中的Non-member function "nonMemberFunc(arg)" 並呼叫其member "__name__"的實例。這樣應該是有解決如何取得該函數"物件"的問題, 並且作為function運作上也沒問題。不知道我哪裡誤解了嗎? ※ 編輯: skyconquer (59.124.207.79 臺灣), 08/22/2020 10:44:11

08/22 10:47, 4年前 , 2F
從他的回文來看,要的呼叫方式應該是 `logger.func()`
08/22 10:47, 2F

08/22 10:47, 4年前 , 3F
但是那個 `func` 並不在 logger 內
08/22 10:47, 3F

08/22 10:48, 4年前 , 4F
你可以看上一篇我貼的那個,不過還是等原 PO 說明吧
08/22 10:48, 4F
看到回文了,所以他是要把一個non-member function 用 member-function的方式來 呼叫? ※ 編輯: skyconquer (59.124.207.79 臺灣), 08/22/2020 10:53:12

08/22 10:54, 4年前 , 5F
對,我對後來回文的理解是這樣
08/22 10:54, 5F

08/22 10:55, 4年前 , 6F
只是這種做法很少見,所以我才想說等原 PO 說明他實際
08/22 10:55, 6F

08/22 10:55, 4年前 , 7F
上想做什麼功能
08/22 10:55, 7F

08/22 10:56, 4年前 , 8F
一般來說也會用類似你這種的方式或前篇 TitanEric 提到
08/22 10:56, 8F

08/22 10:57, 4年前 , 9F
的 decorator 去做,因為這樣也能處理 caller argument
08/22 10:57, 9F
看來只能等說明了。 ※ 編輯: skyconquer (59.124.207.79 臺灣), 08/22/2020 11:11:43

08/22 11:55, 4年前 , 10F
拍謝,我好像整個會錯意了,有更新在原文
08/22 11:55, 10F
文章代碼(AID): #1VG89ysb (Python)
文章代碼(AID): #1VG89ysb (Python)