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

看板Python作者 (索尼)時間4年前 (2020/08/22 09:08), 4年前編輯推噓3(3037)
留言40則, 4人參與, 4年前最新討論串1/2 (看更多)
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

08/22 09:23, 4年前 , 1F
你的意思是,每當一個 member method 被呼叫時,就要
08/22 09:23, 1F

08/22 09:23, 4年前 , 2F
抓到是誰被呼叫嗎?
08/22 09:23, 2F

08/22 09:25, 4年前 , 3F
如果要的效果是這樣,我目前是有想到可以透過 metacla
08/22 09:25, 3F

08/22 09:25, 4年前 , 4F
ss 去做
08/22 09:25, 4F
也不算是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

08/22 09:58, 4年前 , 5F
我釐清一下你想做的事:也就是說,任何一個沒有定義在
08/22 09:58, 5F

08/22 09:58, 4年前 , 6F
Logger class 裡的 function ‘foo’,只要透過 logg
08/22 09:58, 6F

08/22 09:58, 4年前 , 7F
er.foo() 這種方式呼叫,你就可以先透過 logger 去做
08/22 09:58, 7F

08/22 09:58, 4年前 , 8F
你想做的事再讓那個 function 做自己的事囉?
08/22 09:58, 8F

08/22 10:06, 4年前 , 9F
先說好了,如果要透過這種呼叫方式來達到這種功能是有
08/22 10:06, 9F

08/22 10:06, 4年前 , 10F
點奇怪。雖然說你可以硬是透過 `__getattr__()` 讓
08/22 10:06, 10F

08/22 10:09, 4年前 , 11F
logger 在找不到 member method 時(也就是上述的情況
08/22 10:09, 11F

08/22 10:11, 4年前 , 12F
),去其他 scope 找你要的 function ,如 globals()
08/22 10:11, 12F

08/22 10:12, 4年前 , 13F
。但是這樣你就要自己處理 name resolution 的問題。
08/22 10:12, 13F

08/22 10:13, 4年前 , 14F
再來,怎麼取得 caller 的 arguments 又是另一個問題
08/22 10:13, 14F

08/22 10:19, 4年前 , 15F
但是如果你沒有需要處理 caller arguments 的話,那上
08/22 10:19, 15F

08/22 10:19, 4年前 , 16F
面那個問題就省了
08/22 10:19, 16F

08/22 10:27, 4年前 , 17F
我回了一篇文在底下,請參考看看。
08/22 10:27, 17F

08/22 10:37, 4年前 , 18F
怎麼覺得跟decorator有關
08/22 10:37, 18F

08/22 10:39, 4年前 , 19F
我是這樣覺得,但目前還不清楚原 PO 真正的問題
08/22 10:39, 19F

08/22 10:40, 4年前 , 20F
怕變成 XY problem
08/22 10:40, 20F

08/22 10:45, 4年前 , 21F
先給原 PO 看看這個是不是你想要的結果:
08/22 10:45, 21F

08/22 10:45, 4年前 , 22F
感謝您的詳細解說 讓我發現我整個會錯意了 因為函數並不是定義在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

08/22 12:30, 4年前 , 23F
試試看這是不是你要的效果:
08/22 12:30, 23F

08/22 12:30, 4年前 , 24F

08/22 12:31, 4年前 , 25F
但是這個做法就如同前面提到的,若你需要處理 caller
08/22 12:31, 25F

08/22 12:31, 4年前 , 26F
arguments 的話,還要額外透過 frame 去抓資訊
08/22 12:31, 26F

08/22 12:33, 4年前 , 27F
另一個做法是改成用 function wrapper 把每一個 rpc
08/22 12:33, 27F

08/22 12:33, 4年前 , 28F
提供的 function 都包過一次,這種方法對於也要處理
08/22 12:33, 28F

08/22 12:34, 4年前 , 29F
arguments 的話會比較方便,但是缺點就是一旦 wrapper
08/22 12:34, 29F

08/22 12:34, 4年前 , 30F
太多,要轉進呼叫到實際上 rpc 的 function 也需越多層
08/22 12:34, 30F

08/22 12:58, 4年前 , 31F
接續上面第一種方式,也可以不透過 frame 去抓 caller
08/22 12:58, 31F

08/22 12:58, 4年前 , 32F
argument
08/22 12:58, 32F

08/22 12:58, 4年前 , 33F
非常感謝您! 第二個方法看起來可以解決這個問題 再次感謝 ※ 編輯: XperiaZ6C (111.184.77.196 臺灣), 08/22/2020 13:27:21

08/22 17:27, 4年前 , 34F
(`・∀・)b
08/22 17:27, 34F

08/23 18:03, 4年前 , 35F
看了這些討論之後我覺得自己好菜
08/23 18:03, 35F

08/23 20:51, 4年前 , 36F
@azuel 不用這樣說,每個人都嘛是從新手開始走起。覺
08/23 20:51, 36F

08/23 20:51, 4年前 , 37F
得自己不足的時候,就繼續努力把能力練起來,這才是該
08/23 20:51, 37F

08/23 20:51, 4年前 , 38F
做的事。而且說實在的,我也沒有解決了什麼高深的問題
08/23 20:51, 38F

08/23 20:51, 4年前 , 39F
,純粹只是分享以我目前所知所能構成的解法。以後對 P
08/23 20:51, 39F

08/23 20:51, 4年前 , 40F
ython 了解更透徹後,說不定又會有更好的解法。共勉之
08/23 20:51, 40F
文章代碼(AID): #1VG6_x7s (Python)
文章代碼(AID): #1VG6_x7s (Python)