Given x = C.f
after:
class C:
def f(self):
pass
What do I call on x
that will return C
?
The best I could do is exec
ing a parsed portion of x.__qualname__
, which is ugly:
exec('d = ' + ".".join(x.__qualname__.split('.')[:-1]))
For a use case, imagine that I want a decorator that adds a super
call to any method it's applied to. How can that decorator, which is only given the function object, get the class to super
(the ???
below)?
def ensure_finished(iterator):
try:
next(iterator)
except StopIteration:
return
else:
raise RuntimeError
def derived_generator(method):
def new_method(self, *args, **kwargs):
x = method(self, *args, **kwargs)
y = getattr(super(???, self), method.__name__)\
(*args, **kwargs)
for a, b in zip(x, y):
assert a is None and b is None
yield
ensure_finished(x)
ensure_finished(y)
return new_method
x.im_class
? – Haifax
is just a regular function that isn't directly tied toC
at all. – Haifax.im_class
that isn't available in Python 3.x – Conquerim_class
orself.__class__
as an argument tosuper
(which is the OP's intention according to his other question), because if you ever subclassC
you'll get infinite loops whenf
is called. – Haifax.__globals__['.'.join(x.__qualname__.split('.')[:-1])]
? Still ugly, but at least without anexec
... – Verminationx.__self__
for the object instance? orx.__self__.__class__
for the class – PerukeAttributeError: 'function' object has no attribute '__self__'
– Tragediennex = C.f
you may have issues. Since you are operating on the class itself (and not an instance of the class) the function x becomes detached. Only way I see would be to get the function onf
through an instance likex = C().f
– Uncladx = C.f
you could usedx = C().f
. However if that doesn't suit your needs then I do not know of another solution at this time. – UncladC.f
is a method: it is a function that belongs to the classC
that takes a reference toself
. It's true that Python 3 stopped using theMethodType
for unbound methods, but semantically it is a method. – Tragedienne__qualname__
isn't necessarily related to the class. Also, parsing__qualname__
like this is beyond its intended usage. I found one issue with respect to closure<locals>
; I'm not sure what other corner cases exist now or may come up in future releases. – Esemplastic__parent__
member for modules, classes, and class members so that the declaration structure can be walked. – Tragediennefunc._derived = True
). Then definederived_generator
in a class decorator that creates a closure over the class, so you can callsuper(cls, self)
. Loop over the class dict to apply this to all of the_derived
functions. – Esemplastic