[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