Get parent class name? [duplicate] - python

This question already has answers here:
Get class that defined method
(8 answers)
Closed 6 years ago.
The community reviewed whether to reopen this question 6 months ago and left it closed:
Original close reason(s) were not resolved
class A(object):
def get_class(self):
return self.__class__
class B(A):
def __init__(self):
A.__init__(self)
b = B()
print b.get_class()
This code will print <class '__main__.B'>.
How can I get the class name where the method has been defined (namely A)?

From the documentation: https://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy
Class objects have a __name__ attribute. It might cleaner to introspect the base class(es) through the __bases__ attr of the derived class (if the code is to live in the derived class for example).
>>> class Base(object):
... pass
...
>>> class Derived(Base):
... def print_base(self):
... for base in self.__class__.__bases__:
... print base.__name__
...
>>> foo = Derived()
>>> foo.print_base()
Base

inspect.getmro(cls)
Return a tuple of class cls’s base classes,
including cls, in method resolution order. No class appears more than
once in this tuple. Note that the method resolution order depends on
cls’s type. Unless a very peculiar user-defined metatype is in use,
cls will be the first element of the tuple.
import inspect
inspect.getmro(B)
result will be:
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
First element is the class itself, second element is always first of the parents. After that things can get bit more complicated.

You could change
return self.__class__
return A().__class__
Since there is no other instance of A() available...

Related

how to get the class name of a statics method belongs to it [duplicate]

How can I get the class that defined a method in Python?
I'd want the following example to print "__main__.FooClass":
class FooClass:
def foo_method(self):
print "foo"
class BarClass(FooClass):
pass
bar = BarClass()
print get_class_that_defined_method(bar.foo_method)
import inspect
def get_class_that_defined_method(meth):
for cls in inspect.getmro(meth.im_class):
if meth.__name__ in cls.__dict__:
return cls
return None
I don't know why no one has ever brought this up or why the top answer has 50 upvotes when it is slow as hell, but you can also do the following:
def get_class_that_defined_method(meth):
return meth.im_class.__name__
For python 3 I believe this changed and you'll need to look into .__qualname__.
In Python 3, if you need the actual class object you can do:
import sys
f = Foo.my_function
vars(sys.modules[f.__module__])[f.__qualname__.split('.')[0]] # Gets Foo object
If the function could belong to a nested class you would need to iterate as follows:
f = Foo.Bar.my_function
vals = vars(sys.modules[f.__module__])
for attr in f.__qualname__.split('.')[:-1]:
vals = vals[attr]
# vals is now the class Foo.Bar
Thanks Sr2222 for pointing out I was missing the point...
Here's the corrected approach which is just like Alex's but does not require to import anything. I don't think it's an improvement though, unless there's a huge hierarchy of inherited classes as this approach stops as soon as the defining class is found, instead of returning the whole inheritance as getmro does. As said, this is a very unlikely scenario.
def get_class_that_defined_method(method):
method_name = method.__name__
if method.__self__:
classes = [method.__self__.__class__]
else:
#unbound method
classes = [method.im_class]
while classes:
c = classes.pop()
if method_name in c.__dict__:
return c
else:
classes = list(c.__bases__) + classes
return None
And the Example:
>>> class A(object):
... def test(self): pass
>>> class B(A): pass
>>> class C(B): pass
>>> class D(A):
... def test(self): print 1
>>> class E(D,C): pass
>>> get_class_that_defined_method(A().test)
<class '__main__.A'>
>>> get_class_that_defined_method(A.test)
<class '__main__.A'>
>>> get_class_that_defined_method(B.test)
<class '__main__.A'>
>>> get_class_that_defined_method(C.test)
<class '__main__.A'>
>>> get_class_that_defined_method(D.test)
<class '__main__.D'>
>>> get_class_that_defined_method(E().test)
<class '__main__.D'>
>>> get_class_that_defined_method(E.test)
<class '__main__.D'>
>>> E().test()
1
Alex solution returns the same results. As long as Alex approach can be used, I would use it instead of this one.
Python 3
Solved it in a very simple way:
str(bar.foo_method).split(" ", 3)[-2]
This gives
'FooClass.foo_method'
Split on the dot to get the class and the function name separately
I found __qualname__ is useful in Python3.
I test it like that:
class Cls(object):
def func(self):
print('1')
c = Cls()
print(c.func.__qualname__)
# output is: 'Cls.func'
def single_func():
print(2)
print(single_func.__module__)
# output: '__main__'
print(single_func.__qualname__)
# output: 'single_func'
After my test, I found another answer here.
I started doing something somewhat similar, basically the idea was checking whenever a method in a base class had been implemented or not in a sub class. Turned out the way I originally did it I could not detect when an intermediate class was actually implementing the method.
My workaround for it was quite simple actually; setting a method attribute and testing its presence later. Here's an simplification of the whole thing:
class A():
def method(self):
pass
method._orig = None # This attribute will be gone once the method is implemented
def run_method(self, *args, **kwargs):
if hasattr(self.method, '_orig'):
raise Exception('method not implemented')
self.method(*args, **kwargs)
class B(A):
pass
class C(B):
def method(self):
pass
class D(C):
pass
B().run_method() # ==> Raises Exception: method not implemented
C().run_method() # OK
D().run_method() # OK
UPDATE: Actually call method() from run_method() (isn't that the spirit?) and have it pass all arguments unmodified to the method.
P.S.: This answer does not directly answer the question. IMHO there are two reasons one would want to know which class defined a method; first is to point fingers at a class in debug code (such as in exception handling), and the second is to determine if the method has been re-implemented (where method is a stub meant to be implemented by the programmer). This answer solves that second case in a different way.
if you get this error:
'function' object has no attribute 'im_class'
try this:
import inspect
def get_class_that_defined_method(meth):
class_func_defided = meth.__globals__[meth.__qualname__.split('.')[0]]
#full_func_name = "%s.%s.%s"%(class_func_defided.__module__,class_func_defided.__name__,meth.__name__)
if inspect.isfunction(class_func_defided):
print("%s is not part of a class."%meth.__name__)
return None
return class_func_defided
sample test:
class ExampleClass:
#staticmethod
def ex_static_method():
print("hello from static method")
def ex_instance_method(self):
print("hello from instance method")
def ex_funct(self):
print("hello from simple function")
if __name__ == "__main__":
static_method_class = get_class_that_defined_method(ExampleClass.ex_static_method)
static_method_class.ex_static_method()
instance_method_class = get_class_that_defined_method(ExampleClass.ex_instance_method)
instance_method_class().ex_instance_method()
function_class = get_class_that_defined_method(ex_funct)

Can we overload behavior of class object [duplicate]

This question already has answers here:
What are metaclasses in Python?
(25 answers)
Closed 7 years ago.
I know we can overload behavior of instances of a class, e.g. -
class Sample(object): pass
s = Sample()
print s
<__main__.Sample object at 0x026277D0>
print Sample
<class '__main__.Sample'>
We can change the result of print s:
class Sample(object):
def __str__(self):
return "Instance of Sample"
s = Sample()
print s
Instance of Sample
Can we change the result of print Sample?
You can use a metaclass:
class SampleMeta(type):
def __str__(cls):
return ' I am a Sample class.'
Python 3:
class Sample(metaclass=SampleMeta):
pass
Python 2:
class Sample(object):
__metaclass__ = SampleMeta
Output:
I am a Sample class.
A metaclass is the class of class. Its relationship to a class is analogous to that of a class to an instance. The same classstatement is used. Inheriting form type instead from object makes it a metaclass. By convention self is replaced by cls.

How would I find where a function originates in source code?

I'm having trouble actually following the source code, mostly because simply using grep on it isn't working.
Is there any way to find out from which class a certain method was inherited? For example, if there is class A, which has method foo() and bar(), and there is class B which has biz(), and class C which inherits all of it's attributes and methods from both A and B, how would I be able to determine which class foo() came from (without strictly looking at the source manually)?
You can always access the super-classes of a class by looking in the __bases__ attribute for that class. Given three simple classes A, B, C (which for Py2.7 must inherit from object) :
class A:
def foo():
pass
def bar():
pass
class B:
def biz(): pass
class C(A, B):
pass
You can then iterate through the __bases__ for C and check whether an attribute, function foo (for example), exists in one of these classes.
To do this you can check for membership of foo in the __dict__ that holds the names for each class object in __bases__:
for base in C.__bases__:
if 'foo' in base.__dict__:
print("Attribute: '{}' defined in {}".format("foo", base))
Which prints:
Attribute: 'foo' defined in <class '__main__.A'>
For a more complete and general view:
# get all attributes of class C
vars = [classVar for classVar in dir(C) if not classVar.startswith('__')]
# iterate through all bases:
for base in C.__bases__:
for attr in vars:
if attr in base.__dict__:
print("Attribute: '{}' defined in {}".format(attr, base))
Which returns:
Attribute: 'bar' defined in <class '__main__.A'>
Attribute: 'foo' defined in <class '__main__.A'>
Attribute: 'biz' defined in <class '__main__.B'>
For all classes in the chain of inheritance you can switch __bases__ to __mro__ which indicates the method resolution order; a tuple of objects python searches when trying to resolve attribute references.
If we add a function to class C and make another class D that inherits from C:
class C(A, B):
def another(): pass
class D(C): pass
To get a view of where each function is defined, just switch __bases__ with __mro__ in the loop:
# hold D's attributes (functions names, variables.)
attrs = [var for var in dir(D) if not var.startswith('__')]
# vars contents: ['another', 'bar', 'biz', 'foo']
for base in D.__mro__:
for attr in attrs:
if attr in base.__dict__:
print("Attribute: '{}' defined in {}".format(attr, base))
Now, this follows the mro tuple (equal to (__main__.D, __main__.C, __main__.A, __main__.B, object) in this specific case) and yields a similar output:
Attribute: 'another' defined in <class '__main__.C'>
Attribute: 'bar' defined in <class '__main__.A'>
Attribute: 'foo' defined in <class '__main__.A'>
Attribute: 'biz' defined in <class '__main__.B'>
You can do checking through the parent classes as determined by the method resolution order and checking the members of each parent class:
for i in C.__mro__:
if 'bar' in i.__dict__:
print 'bar is in class ' + i.__name__
So, given the following classes definitions:
class A(object):
def foo(self): pass
def bar(self): pass
class B(object):
def biz(self): pass
class C(A,B): pass
Running the above code will give
bar is in class A

Python - which is the better way of calling superclass' method?

All the while I have been using:
SuperClass.__init__(self, *args, **kwargs)
My reason is that this shows explicitly which superclass is used, especially in the case of multiple inheritance.
However, other codes I came across use
super(MyClass, self).__init__(*args, **kwargs)
instead.
This could become ambigious when it's used in:
class MyClass(SuperClass1, SuperClass2):
def __init__(self, *args, **kwargs):
super(MyClass, self).__init__(*args, **kwargs) #which SuperClass is being used?
I would like to know why this form of calling is widely adopted? Any advantage at all?
The reason that super is prefereable for modern (new style) classes is that it allows cooperative multiple inheritance. Here's an example.
>>> class Foo(object):
... def display(self):
... print "In Foo"
...
>>> class Foo2(Foo):
... def display(self):
... print "In Foo2"
... super(Foo2, self).display()
... print "Back in Foo2"
...
>>> class Bar(Foo):
... def display(self):
... print "In Bar"
... super(Bar, self).display()
... print "Back in Bar"
...
>>> class FooBar(Foo2, Bar):
... pass
...
>>> FooBar().display()
In Foo2
In Bar
In Foo
Back in Bar
Back in Foo2
>>> class BarFoo(Bar, Foo2):
... pass
...
>>> BarFoo().display()
In Bar
In Foo2
In Foo
Back in Foo2
Back in Bar
Note that I didn't do anything to change the display method on the superclasses but I got different display methods on the subclasses by changing the order in which I arranged the superclasses. BarFoo and FooBar have different methods. This is because they have different Method Resolution Orders
>>> BarFoo.__mro__
(<class '__main__.BarFoo'>, <class '__main__.Bar'>, <class '__main__.Foo2'>, <class '__main__.Foo'>, <type 'object'>)
>>> FooBar.__mro__
(<class '__main__.FooBar'>, <class '__main__.Foo2'>, <class '__main__.Bar'>, <class '__main__.Foo'>, <type 'object'>)
This means that super resolves to a different class for each subclass that it's called in. This allows for each overriding method to change a small part of what's going on and still let every other superclass contribute to the method call as long as they're willing to play nicely.
For new style classes which inherit from object, super is used.
The __mro__ (method resolution order) attribute of the type lists the method resolution search order used by super.
>>> class X(object):
pass
>>> class Y(object):
pass
>>> class Z(X, Y):
pass
>>> Z.__mro__
(<class '__main__.Z'>, <class '__main__.X'>, <class '__main__.Y'>, <type 'object'>)
This specifies the ordering for Z. Since it is Z(X, Y), X is first in the hierarchy. Had it been Z(Y, X), Y would have preceded over X.
For old style classes, SuperClass.__init__(self, *args, **kwargs) is used.
UPDATE:
For your question as to which SuperClass is being used.
>>> class First(object):
pass
>>> class Second(object):
def __init__(self, *args, **kwargs):
print 'Second __init__ called'
>>> class MInherit(First, Second):
def __init__(self):
super(MInherit, self).__init__()
>>> i = MInherit()
Second __init__ called
First, First will be checked to see if it has an __init__, since First comes first in the MRO. Since in this case 'First' doesn't have an __init__, so Second is called. Had there been an __init__ in First, only that would have been called.
In addition to the good answers already posted, here is some additional info:
Old-style classes (those that don't derive from object) have a depth-first method resolution order. Old-style classes call their super classes in the way that you are used to.
New-style classes (those that do derive from object) have a more complicated method resolution order. At the highest level it is akin to breadth first, but is more complex than that. See this page for an excellent explanation. Using "super()" allows new style classes to follow this method resolution order.
If you are using new-style classes, you can still use the old-style of calling super classes and your code will still work. The differences only become apparent for more complicated multiple-inheritance patterns.

Python Reflection and callable objects

I have a two part question.
>>> class One(object):
... pass
...
>>> class Two(object):
... pass
...
>>> def digest(constr):
... c = apply(constr)
... print c.__class__.__name__
... print constr.__class__.__name__
...
>>> digest(Two)
Two
type
How would one create object 'Two'? Neither constr() or c() work; and it seems that apply turns it into a type.
What happens when you pass a class rather and an instance into a method?
Classes are high level objects, so you can simply pass them like this:
def createMyClass ( myClass ):
obj = myClass()
return obj
class A ( object ):
pass
>>> x = createMyClass( A )
>>> type( x )
<class '__main__.A'>
How would one create object 'Two'?
Neither constr() or c() work; and it
seems that apply turns it into a
type.
The above comment was made in regards to this code:
>>> def digest(constr):
... c = apply(constr)
... print c.__class__.__name__
... print constr.__class__.__name__
apply (deprecated: see #pyfunc's answer) certainly does not turn the class Two into a type: It already is one.
>>> class Two(object): pass
...
>>> type(Two)
<type 'type'>
Classes are first class objects: they're instances of type. This makes sense if you look at the next example.
>>> two = Two()
>>> type(two)
<class '__main__.Two'>
You can see that a class very clearly functions as a type because it can be returned from type. Here's another example.
>>> Three = type('Three', (Two, ), {'foo': 'bar'})
>>> type(Three)
<type 'type'>
>>> three = Three()
>>> type(three)
<class '__main__.Three'>
You can see that type is a class that can be instantiated. Its constructor takes three arguments: the name of the class, a tuple of base classes and a dictionary containing the class attributes. It returns a new type aka class.
As to your final question,
What happens when you pass a class
rather and an instance into a method?
You're going to have to be more specific. Classes are just instances of type and so are first class objects. Asking what happens if I pass a class into a method is like asking what happens if I pass an integer into a method: It depends entirely on what the method is expecting.
Just another one example:
def InstanceFactory(classname):
cls = globals()[classname]
return cls()
class A(object):
def start(self):
print "a.start"
class B(object):
def start(self):
print "b.start"
InstanceFactory("A").start()
InstanceFactory("B").start()
If the class belongs to another module:
def InstanceFactory(modulename, classname):
if '.' in modulename:
raise ValueError, "can't handle dotted modules yet"
mod = __import__(modulename)
cls = getattr(mod, classname]
return cls()
I am confused though. Wasn't apply() deprecated since 2.3
http://www.python.org/dev/peps/pep-0290/
We don't need this any more.
apply(f, args, kwds) --> f(*args, **kwds)
Others have been moved / considered deprecated in modern usage:
buffer()
coerce()
and intern()
Simply use : Classname() to create an object.

Categories

Resources