Reputation: 355
working through "Learning Python: Powerful Object-Oriented Programming'
chapter 28 has you create a class that will list all instance attributes of an object.
then the book offers some ideas, such as listing all attributes up the inheritance tree. when doing so, i used the @classmethod
decorator shown below - and was wondering if there's a way to filter those types of methods out of my listing:
"""Assorted class utilities and tools"""
class ShowAttrs(object):
"""
A class to show all available (including inherited, excluding special) attributes
"""
@classmethod
def getAttrs(cls, child_cls):
my_attrs = [_ for _ in child_cls.__dict__ if _.startswith('_') is False]
my_name = child_cls.__name__
listed_attrs = [my_name + ': ' + ', '.join(my_attrs)]
try:
bases = child_cls.__bases__
inherited_attrs = []
for base in bases[::-1]:
if base.__name__ != 'ShowAttrs' and base.__name__ != 'object':
inherited_lists = [ShowAttrs.getAttrs(base)]
for _ in inherited_lists:
inherited_attrs.extend(_)
except NameError:
return
inherited_attrs.extend(listed_attrs)
return inherited_attrs
def __repr__(self):
child_cls = self.__class__
all_attrs = ShowAttrs.getAttrs(child_cls)
len_attrs = reversed(list(range(len(all_attrs))))
all_attrs_unique = [ x for i,x in zip(len_attrs,all_attrs[::-1]) if i <= all_attrs.index(x) ]
return '\n'.join(reversed(all_attrs_unique))
if __name__ == '__main__':
class Parent(ShowAttrs):
var3 = 'Parent'
def parentMethod(self):
print('this is a Parent')
class Child(Parent):
var2 = 'Child'
def childMethod(self):
print('this is a Child')
class GrandChild(Child):
var1 = 'GrandChild'
@classmethod
def howCanIFilterThisOneOut(cls):
pass
def grandchildMethod(self):
print('this is a GrandChild')
def grandchildMethod2(self):
pass
def grandchildMethod3(self):
pass
class GrandChild2(Child):
var11 = 'GrandChild2'
class GreatGrandChild(GrandChild, GrandChild2):
var0 = 'GreatGrandChild'
x = GreatGrandChild()
print(x)
when i run this:
Python 3 x = GreatGrandChild() print(x)
Console
Parent: var3, parentMethod
Child: var2, childMethod
GrandChild2: var11
GrandChild: var1,howCanIFilterThisOneOut, grandchildMethod, grandchildMethod2, grandchildMethod3
GreatGrandChild: var0
but howCanIFilterThisOneOut
is a classmethod, not an instance method. so just wondering if it's possible to differentiate.
thanks
sandbox to try it: https://edube.org/sandbox/af4390bc-77aa-11ec-ab3f-0242157e55ca
Upvotes: 0
Views: 155
Reputation: 169184
isinstance(x, classmethod)
does the trick.
my_attrs = [
name for (name, value)
in child_cls.__dict__.items()
if not name.startswith('_') and not isinstance(value, classmethod)
]
As an aside, your code could simplify, with duplicate removal and all, into something like
import inspect
def get_fields(cls):
seen = set()
for cls in inspect.getmro(cls)[::-1]:
if cls is object:
continue
attr_names = {
name
for name in cls.__dict__
if name not in seen and not name.startswith("_")
}
seen.update(attr_names)
yield (cls.__name__, sorted(attr_names))
Upvotes: 1