List all attributes which are inherited by a class
Asked Answered
H

4

12

Hi I have the below from which I am trying to pull data from Outlook using code obtained on StackOverflow.

Using the first loop, I am trying to gather all attributes available to the object.

Whilst running it I notice the absence of Name which is later called in the 2nd loop, I assume this is due to inheritance. Please can you assist me in finding all attributes available to a class?

import win32com.client,sys

o = win32com.client.gencache.EnsureDispatch("Outlook.Application")
ns = o.GetNamespace("MAPI")

adrLi = ns.AddressLists.Item("Global Address List")
contacts = adrLi.AddressEntries
numEntries = adrLi.AddressEntries.Count
print(type(contacts))
nameAliasDict = {}
attrs_ = dir(contacts)
for i in range(len(attrs_)):
    print((attrs_[i]))

for j in contacts:
    print(j.Name)

    sys.exit()
Helmick answered 17/5, 2017 at 15:23 Comment(2)
#4241671 note object attributes might be differentMikamikado
Not necessarily inheritance; the set of names for which attribute lookup succeeds is not necessarily explicitly defined. The only thing you can say for certain is that an attribute x is available for foo if foo.x does not raise an AttributeError.Mackenie
R
7

Python provides a handy little builtin called dir. I can use that on a class instance to get a list of all the attributes and methods of that class along with some inherited magic methods, such as __delattr__, __dict__, __doc__, __format__, etc. You can try this yourself by doing the following:

x = dir(myClassInstance)

but what you want is:

child.__class__.__bases__[0]().getAttributes()

__bases__ is a class attribute containing tuple of base classes for this class. so if your class has only one base class, this is the answer, but if class has more than one base class, just do same for all elements from that tuple.

Rebuild answered 25/5, 2017 at 18:57 Comment(1)
Where does the method getAttributes() come from?Cogwheel
C
4

Use the super and dir built-in functions.

super refers to the instance of the mother class.

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.

dir returns a list of the argument's attributes.

With an argument, attempt to return a list of valid attributes for that object.

class Foo:
    def __init__(self):
        self.v = 10

class Bar(Foo):
    def __init__(self):
        super().__init__()
        print(dir(super()))

b = Bar()

Output:

[(...), 'v']

The output list contains all the attributes that are defined in the mother class. It mostly contains attributes inherited from object (the attributes between double underscores).


If you do not extend the class whose you want to know the attributes, just use dir on an instance:

>>> dir(Foo())
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'v']
Curia answered 17/5, 2017 at 15:30 Comment(1)
dir(super()) doesn't do what you think it does. For example, if v was defined in Bar instead of Foo, it would still show up in the output. Also, dir(super()) won't show inherited methods, or any of the object's methods; the methods shown by dir(super()) are a completely unrelated list, coming from the class hierarchy of super itself.Blossomblot
C
4

dir(contacts) will show you all the attribute names of contacts.

I notice the absence of Name which is later called in the 2nd loop

You use j.Name not contacts.Name so there is no reason for Name to show up from the first loop. If you want to know all the available attributes on j then do dir(j).

Cogwheel answered 19/5, 2017 at 22:32 Comment(0)
A
4

Given two classes, Parent and Child, if you want only the inherited attributes you could use the inspect module coupled with dir:

import inspect

class Parent():
    a = 1

    def myfunc(self):
        return 2

class Child(Parent):

    c = 4


mros = inspect.getmro(Child) #returns a tuple with the class in parameter at the first position, the rest should be the parent class(es)
child_attrs = dir(mros[0])
parent_attrs = dir(mros[1])

inherited_attr = [item for item in child_attrs if item in parent_attrs]

print(parent_attrs)
print(child_attrs)
print(inherited_attr)

And you can go like this up into the hierarchy however you wish

Allnight answered 24/5, 2017 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.