[Python-ideas] Get the class that *defines* a method
Robert Kern
robert.kern at gmail.com
Sun Jun 23 22:54:37 CEST 2013
On 2013-06-23 20:42, anatoly techtonik wrote:
> Currently, the only way to get the name of the class that *defines* a method is
> to get chain of parent classes from inspect.getmro() and look into every class's
> dict until a given name is found. Knowing that dict contains not only methods,
> and knowing that it can be modified at run-time, this doesn't seem too reliable
> for me (unless Python itself does the same).
I think you can most robustly replicate what Python does by walking up the MRO
and checking for the method by calling each class's __getattribute__() until it
stops giving you the same method. The last class to give you the same method
that type(the_instance) gives you is the class that defines the method.
> At first I wanted to propose an enhancement to runtime skeleton of Python, which
> is 2D lookup tree for objects and containers that define them. But then I
> realized that it will may not reflect the model I need. For example, classes
> need to provide their parent classes, but in my model classes need to provide
> module name (or function name, or method name) in which they are defined.
>
> And while writing this I realized that *definition* scope may be different from
> *run-time* scope, and Python doesn't make it clear:
>
> >>> def lll():
> ... class A(object):
> ... pass
> ... a=A()
> ... return a
> ...
> >>> lll()
> <__main__.A object at 0x948252c>
> >>> __main__.A
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> NameError: name '__main__' is not defined
>
> The A object is said to be in __main__ namespace, but it seems to be a run-time
> namespace local to function and it seems like Python loses this information.
Classes defined in functions get assigned the name of the module that it is in,
in this case `__main__` which is a real module recorded under that name in
sys.modules. The example you have given doesn't show what you think it shows,
just that the __main__ module (which the interpreter executes its code in)
doesn't have a reference to itself. In general, modules don't include themselves
in their namespace.
You can get the class of an instance in the usual manner: type(). It is true
that you cannot access that class *by name alone*. This is not fixable, even in
principle.
> There is no information about the function that defined the class (owner, parent
> or .?.), and hence no info about container of the function, which makes it hard
> to assume the scope of variables for this class at run-time.
If you had actually defined a method and actually used a variable from the local
namespace (the only time where this information matters), the relevant
information will be recorded in the `func_closure` attribute of the function
object underneath the method.
[~]
|29> def foo(x):
...> class A(object):
...> def foo(self):
...> print x
...> return A()
...>
[~]
|30> a = foo(10)
[~]
|31> foo_method = type(a).foo
[~]
|32> foo_method
<unbound method A.foo>
[~]
|33> foo_method.im
foo_method.im_class foo_method.im_func foo_method.im_self
[~]
|33> foo_method.im_func
<function __main__.foo>
[~]
|34> foo_method.im_func.func_closure
(<cell at 0x109e16be8: int object at 0x1003100a0>,)
[~]
|35> foo_method.im_func.func_closure[0].cell_contents
10
You don't need to know about the function where the class definition is
contained in to get this information. The function objects carry it around with
them.
--
Robert Kern
"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
More information about the Python-ideas
mailing list