In Python, decorate two methods with the same name

2019-05-26 09:28发布

I am writing a framework to be used by people who know some python. I have settled on some syntax, and it makes sense to me and them to use something like this, where Base is the Base class that implements the framework.

class A(Base):
    @decorator1
    @decorator2
    @decorator3
    def f(self):
        pass

    @decorator4
    def f(self):
        pass

    @decorator5
    def g(self)
        pass

All my framework is implemented via Base's metaclass. This set up is appropriate for my use case because all these user-defined classes have a rich inheritance graph. I expect the user to implement some of the methods, or just leave it with pass. Much of the information that the user is giving here is in the decorators. This allows me to avoid other solutions where the user would have to monkey-patch, give less structured dictionaries, and things like that.

My problem here is that f is defined twice by the user (with good reason), and this should be handled by my framework. Unfortunately, by the time this gets to the metaclass'__new__ method, the dictionary of attributes contains only one key f. My idea was to use yet another decorator, such as @duplicate for the user to signal this is happening, and the two f's to be wrapped differently so they don't overwrite each other. Can something like this work?

3条回答
Root(大扎)
2楼-- · 2019-05-26 09:39

Yes, you could, but only with an ugly hack, and only by storing the function with a new name.

You'd have to use the sys._getframe() function to retrieve the local namespace of the calling frame. That local namespace is the class-in-construction, and adding items to that namespace means they'll end up in the class dictionary passed to your metaclass.

The following retrieves that namespace:

callframe = sys._getframe(1)
namespace = callframe.f_locals

namespace is a dict-like object, just like locals(). You can now store something in that namespace (like __function_definitions__ or similar) to add extra references to the functions.

查看更多
迷人小祖宗
3楼-- · 2019-05-26 09:45

You should use a namespace to distinguish the different fs.

Heed the advice of the "Zen of Python":

Namespaces are one honking great idea -- let's do more of those!

查看更多
Root(大扎)
4楼-- · 2019-05-26 09:47

You might be thinking java - methods overloading and arguments signature - but this is python and you cannot do this. The second f() will override the first f() and you end up with only one f(). The namespace is a dictionary and you cannot have duplicated keys.

查看更多
登录 后发表回答