How to test if python class parent has method defined?
Question:
I have a subclass that may have a method ‘method_x’ defined. I want to know if ‘method_x’ was defined somewhere else up the class hierarchy.
If I do:
hasattr(self, 'method_x')
I’ll get a truth value that also looks at any methods defined for the subclass. How do I limit this to just inquire as to whether or not that method was defined higher up the class chain?
Answers:
If you’re using Python 3, you can supply super()
to the object parameter of hasattr
.
For example:
class TestBase:
def __init__(self):
self.foo = 1
def foo_printer(self):
print(self.foo)
class TestChild(TestBase):
def __init__(self):
super().__init__()
print(hasattr(super(), 'foo_printer'))
test = TestChild()
With Python 2, it’s similar, you just have to be more explicit in your super()
call.
class TestBase(object):
def __init__(self):
self.foo = 1
def foo_printer(self):
print(self.foo)
class TestChild(TestBase):
def __init__(self):
super(TestChild, self).__init__()
print(hasattr(super(TestChild, self), 'foo_printer'))
test = TestChild()
Both 2 and 3 will work with multiple levels of inheritance and mixins.
Python 3.3 introduced a __qualname__
attribute on functions, which you can check on your subclass’ methods to learn which class they were defined on:
class Foo:
def a(self): ...
def b(self): ...
class Bar(Foo):
def a(self): ...
>>> Bar.a.__qualname__
'Bar.a'
>>> Bar.b.__qualname__
'Foo.b'
With that in mind, you can write something like this:
def inherited(instance, method_name) -> bool:
cls_name = instance.__class__.__name__
qual_name = getattr(instance, method_name).__qualname__
return not qual_name.startswith(f"{cls_name}.")
>>> inherited(Foo(), "a")
False
>>> inherited(Foo(), "b")
True
This will only work for methods, and not attributes in general.
I have a subclass that may have a method ‘method_x’ defined. I want to know if ‘method_x’ was defined somewhere else up the class hierarchy.
If I do:
hasattr(self, 'method_x')
I’ll get a truth value that also looks at any methods defined for the subclass. How do I limit this to just inquire as to whether or not that method was defined higher up the class chain?
If you’re using Python 3, you can supply super()
to the object parameter of hasattr
.
For example:
class TestBase:
def __init__(self):
self.foo = 1
def foo_printer(self):
print(self.foo)
class TestChild(TestBase):
def __init__(self):
super().__init__()
print(hasattr(super(), 'foo_printer'))
test = TestChild()
With Python 2, it’s similar, you just have to be more explicit in your super()
call.
class TestBase(object):
def __init__(self):
self.foo = 1
def foo_printer(self):
print(self.foo)
class TestChild(TestBase):
def __init__(self):
super(TestChild, self).__init__()
print(hasattr(super(TestChild, self), 'foo_printer'))
test = TestChild()
Both 2 and 3 will work with multiple levels of inheritance and mixins.
Python 3.3 introduced a __qualname__
attribute on functions, which you can check on your subclass’ methods to learn which class they were defined on:
class Foo:
def a(self): ...
def b(self): ...
class Bar(Foo):
def a(self): ...
>>> Bar.a.__qualname__
'Bar.a'
>>> Bar.b.__qualname__
'Foo.b'
With that in mind, you can write something like this:
def inherited(instance, method_name) -> bool:
cls_name = instance.__class__.__name__
qual_name = getattr(instance, method_name).__qualname__
return not qual_name.startswith(f"{cls_name}.")
>>> inherited(Foo(), "a")
False
>>> inherited(Foo(), "b")
True
This will only work for methods, and not attributes in general.