【发布时间】:2021-09-19 13:10:33
【问题描述】:
我有一个由静态方法“列表”组成的类A。我想用一个类装饰器Meta 来改变它的行为,它作用于一个特定的静态方法,在这个例子中是content,通过执行方法m。
我最初的尝试,CASE=2,没有按预期工作,所以我开始了我的案例研究。我介绍了一个新类B,它对另一个方法info 的实现略有不同,但引发了一个有趣的错误,还有一个新类C,只是没有方法info。
- 案例2:贪婪案例
d[i] = classmethod(lambda cls, *args: mcs.m( getattr(target_cls, i)(*args)) ) 不能正常工作,可能是嵌套的动态表达式太多?
- 案例 1:本质上是案例 2,但表达式分为两行,有效
o = getattr(target_cls, i)
d[i] = classmethod(lambda cls, *args: mcs.m(o(*args)))
这里是代码
class Meta:
def __new__(mcs, target_cls):
if CASE == 1:
print('case 1')
d = {}
for i in dir(target_cls):
if i == 'content':
o = getattr(target_cls, i)
d[i] = classmethod(lambda cls, *args: mcs.m(o(*args)))
if CASE == 2:
print('case 2')
d = {}
for i in dir(target_cls):
if i == 'content':
d[i] = classmethod(lambda cls, *args: mcs.m( getattr(target_cls, i)(*args)) )
return type('AAA', (target_cls,), d)
@classmethod
def m(mcs, p):
return '--> ', p
class A:
@staticmethod
def content(response):
return 'static_method', response
@staticmethod
def info(response):
return response
class B:
@staticmethod
def content(response):
return 'static_method', response
@staticmethod
def info(response):
response.sort()
return response
class C:
@staticmethod
def content(response):
return 'static_method', response
# call the "content" class-method of each class for all different cases
for cls in (A, B, C):
print(cls.__name__)
for case in range(1,3):
CASE = case
R = Meta(cls)
try:
print(R.content('ppp'))
except Exception as e: print(e)
print()
输出
A
case 1
('--> ', ('static_method', 'ppp'))
case 2
('--> ', 'ppp') # no decoration
B
case 1
('--> ', ('static_method', 'ppp'))
case 2
'str' object has no attribute 'sort' # <- complained about the other method
C # <- this is ok BUT I removed the other method!
case 1
('--> ', ('static_method', 'ppp'))
case 2
('--> ', ('static_method', 'ppp')) # <- here the decoration took place
问题是为什么案例 2 不起作用,如果是语言限制,那是什么类型的限制?
额外问题:B案例2类的错误如何解释
【问题讨论】:
-
使用 Python 3.9
标签: python-3.x dynamic metaprogramming