首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >动态查找和“替换”方法时的冲突

动态查找和“替换”方法时的冲突
EN

Stack Overflow用户
提问于 2021-09-19 13:10:33
回答 1查看 40关注 0票数 0

我有一个由静态方法( A )的“列表”组成的类。我想用类装饰器Meta来改变它的行为,在这个例子中,content通过执行m方法对一个特定的静态方法起作用。

我最初的尝试CASE=2没有像预期的那样起作用,所以我开始了我的案例研究。我引入了一个新的类B,它与另一个方法info的实现略有不同,但引发了一个有趣的错误,以及一个新的C类,而不使用该方法info

  • 案例2:贪婪案例

d[i] = classmethod(lambda cls, *args: mcs.m( getattr(target_cls, i)(*args)) ) 它不能正常工作,也许嵌套的动态表达式太多了?

  • case 1:它本质上是用例2,但表达式被分成两行,it

代码语言:javascript
运行
复制
   o = getattr(target_cls, i)
   d[i] = classmethod(lambda cls, *args: mcs.m(o(*args)))

这里的代码

代码语言:javascript
运行
复制
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()

输出

代码语言:javascript
运行
复制
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的错误

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-23 22:38:58

我猜这个问题是由循环引起的,原因是每个语句都没有自己的作用域(在循环中)。通过传递i作为lambda的一个关键参数,解决了这个问题。

代码语言:javascript
运行
复制
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)

输出

代码语言:javascript
运行
复制
<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>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69243583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档