0

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

1 Answer 1

1

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))
Sign up to request clarification or add additional context in comments.

3 Comments

awesome thank you. since you've already taken a look, can i ask if you have any advice or thoughts that popped up for me to improve on or any red flags
That would belong on the Code Review SO (if you post over there, you can link the question here).
@rndom See my edit, btw. ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.