看板 Python 關於我們 聯絡資訊
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: 如果要的效果是這樣,我目前是有想到可以透過 metacla08/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’,只要透過 logg08/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
skyconquer: 我回了一篇文在底下,請參考看看。08/22 10:27
TitanEric: 怎麼覺得跟decorator有關08/22 10:37
gmccntzx1: 我是這樣覺得,但目前還不清楚原 PO 真正的問題08/22 10:39
gmccntzx1: 怕變成 XY problem08/22 10:40
gmccntzx1: 先給原 PO 看看這個是不是你想要的結果:08/22 10:45
感謝您的詳細解說 讓我發現我整個會錯意了 因為函數並不是定義在global 或是 local scope 而是客戶給的一個Java Code裡面 我這邊是要用RPC去呼叫 這樣好像是根本找不到function沒錯 客戶給的Java code會像這樣 package com.example.java.rpc; public class JavaCode implements RpcInterface { public boolean click() { // do something } 而我Python端可以繼承現有的RpcInterface 然後給他Java的package name 就能產生一個接口去呼叫Java裡面的函數 class UseJavaCode(RpcInterface): def test_java_code(self): self.java = self.load_interface('com.example.java.rpc') self.java.click() 而我這邊是希望寫一個Python wrapper去把這個interface包起來 在呼叫Java之前做一些處理 class Wrapper(object): def __init__(self, rpc): self.java = rpc.load_interface('com.example.java.rpc') def click(self): # do something return self.java.click() class UseJavaCode(RpcInterface): def test_java_code(self): self.java = Wrapper(self) self.java.click() 但是這樣客戶以後擴充他的Java code 我這邊的Python wrapper就也要跟著擴充 所以才想說有沒有辦法直接抓到class.func()的.func()進來到class裡面跑 像是 class Wrapper(object): def __init__(self, rpc): rpc.java = load_interface('com.example.java.rpc') self.java = rpc.java def __getfunc__(self, func): # do something return self.java.func() 抱歉造成大家誤解了QQ ※ 編輯: XperiaZ6C (111.184.77.196 臺灣), 08/22/2020 11:51:58 ※ 編輯: XperiaZ6C (111.184.77.196 臺灣), 08/22/2020 11:54:09 ※ 編輯: XperiaZ6C (111.184.77.196 臺灣), 08/22/2020 12:06:14
gmccntzx1: 試試看這是不是你要的效果:08/22 12:30
gmccntzx1: 但是這個做法就如同前面提到的,若你需要處理 caller08/22 12:31
gmccntzx1: arguments 的話,還要額外透過 frame 去抓資訊08/22 12:31
gmccntzx1: 另一個做法是改成用 function wrapper 把每一個 rpc08/22 12:33
gmccntzx1: 提供的 function 都包過一次,這種方法對於也要處理08/22 12:33
gmccntzx1: arguments 的話會比較方便,但是缺點就是一旦 wrapper08/22 12:34
gmccntzx1: 太多,要轉進呼叫到實際上 rpc 的 function 也需越多層08/22 12:34
gmccntzx1: 接續上面第一種方式,也可以不透過 frame 去抓 caller08/22 12:58
gmccntzx1: argument08/22 12:58
非常感謝您! 第二個方法看起來可以解決這個問題 再次感謝 ※ 編輯: XperiaZ6C (111.184.77.196 臺灣), 08/22/2020 13:27:21
gmccntzx1: (`・∀・)b 08/22 17:27
azuel: 看了這些討論之後我覺得自己好菜 08/23 18:03
gmccntzx1: @azuel 不用這樣說,每個人都嘛是從新手開始走起。覺 08/23 20:51
gmccntzx1: 得自己不足的時候,就繼續努力把能力練起來,這才是該 08/23 20:51
gmccntzx1: 做的事。而且說實在的,我也沒有解決了什麼高深的問題 08/23 20:51
gmccntzx1: ,純粹只是分享以我目前所知所能構成的解法。以後對 P 08/23 20:51
gmccntzx1: ython 了解更透徹後,說不定又會有更好的解法。共勉之 08/23 20:51