项目有个需求要动态获取模块内的所有协程方法,查了点资料发现 python 里面反射对象可以使用getattr()和对象内置的__dict__属性两种方式,但是我发现两种方式再处理静态的协程方法时结果不一样:
- 使用
getattr()
a = __import__('a') print('===========getattr()=============') func_sync = getattr(a, 'func_sync') func_async = getattr(a, 'func_async') print(func_sync) # <function func_sync at 0x7f827b98f510> print(func_async) # <function func_async at 0x7f8279cd01e0> print(asyncio.iscoroutinefunction(func_async)) # True # getattr class A = getattr(a, 'A') print(A) # <class 'a.A'> method_aa = getattr(A, 'aa') method_bb = getattr(A, 'bb') method_cc = getattr(A, 'cc') print(method_aa) # <bound method A.aa of <class 'a.A'>> <----这里的 bound method 是什么意思? print(method_bb) # <function A.bb at 0x7f8279cd00d0> print(method_cc) # <function A.cc at 0x7f8279cd0158> print(asyncio.iscoroutinefunction(method_aa)) # True <---- 注意这里 print(asyncio.iscoroutinefunction(method_bb)) # True print(asyncio.iscoroutinefunction(method_cc)) # False - 使用
__dict__
print('=========== __dict__ =============') A = a.__dict__['A'] func_sync = a.__dict__['func_sync'] func_async = a.__dict__['func_async'] print(asyncio.iscoroutinefunction(func_async)) # True print(A) # <class 'a.A'> method_aa = A.__dict__['aa'] method_bb = A.__dict__['bb'] method_cc = A.__dict__['cc'] print(method_aa) # <classmethod object at 0x7f827a21c908> <---- 变成了 classmethod print(method_bb) # <function A.bb at 0x7f8279cd00d0> print(method_cc) # <function A.cc at 0x7f8279cd0158> print(asyncio.iscoroutinefunction(method_aa)) # False <----- 不应该是 True 吗? print(asyncio.iscoroutinefunction(method_bb)) # True print(asyncio.iscoroutinefunction(method_cc)) # False 我感觉__dict__和getattr()在反射对象的机制上应该有一些区别,但是 google 了半天也没搞明白为什么,求指教!
class A: @classmethod async def aa(cls): return 123 async def bb(self): return 456 def cc(self): return 789 def func_sync(): return 'sync' async def func_async(): return 'async' 