我有一个由静态方法( A
)的“列表”组成的类。我想用类装饰器Meta
来改变它的行为,在这个例子中,content
通过执行m
方法对一个特定的静态方法起作用。
我最初的尝试CASE=2
没有像预期的那样起作用,所以我开始了我的案例研究。我引入了一个新的类B
,它与另一个方法info
的实现略有不同,但引发了一个有趣的错误,以及一个新的C
类,而不使用该方法info
。
d[i] = classmethod(lambda cls, *args: mcs.m( getattr(target_cls, i)(*args)) )
它不能正常工作,也许嵌套的动态表达式太多了?
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的错误
发布于 2021-10-23 22:38:58
我猜这个问题是由循环引起的,原因是每个语句都没有自己的作用域(在循环中)。通过传递i
作为lambda
的一个关键参数,解决了这个问题。
class Meta:
def __new__(mcs, target_cls):
d = {}
for i in dir(target_cls):
if i == 'content':
d[i] = classmethod(lambda cls, *args, m_name=i: mcs.m( getattr(target_cls, m_name)(*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
print(A.content)
print(Meta(A).content)
print(Meta(A).content('a'))
print(Meta(A).info)
输出
<function A.content at 0x7f04500740d0> # original static method
<bound method Meta.__new__.<locals>.<lambda> of <class '__main__.AAA'>> # class method
('--> ', ('static_method', 'a'))
<function A.info at 0x7f0450074040>
https://stackoverflow.com/questions/69243583
复制相似问题