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?
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:
namespace
is a dict-like object, just likelocals()
. You can now store something in that namespace (like__function_definitions__
or similar) to add extra references to the functions.You should use a namespace to distinguish the different
f
s.Heed the advice of the "Zen of Python":
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.