Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

inheritance and __dict__

14 views
Skip to first unread message

Ka-Ping Yee

unread,
Jun 30, 1996, 3:00:00 AM6/30/96
to

I'm trying to understand what the convention for
maintaining __dict__ is.

I was getting a little confused because after
creating a derived class, it didn't look like
the methods from the base class were remembered:

>>> class Base:
... def a(self): return 4
...
>>> class Derived(Base):
... def b(self): return 5
...
>>> Base.__dict__
{'a': <function a at 8053660>, '__doc__': None}
>>> Derived.__dict__
{'b': <function b at 8053140>, '__doc__': None}

But i can still access the methods:

>>> Derived.a
<unbound method Base.a>
>>> Derived.b
<unbound method Derived.b>

I was even more surprised when i instantiated Derived:

>>> thing = Derived()
>>> thing.__dict__
{}

So how can i see what methods are available?
I can execute them with thing.a() and thing.b(),
but what if i want to get a list and check it?

I tried thing.__class__.__dict__, but that only
gives me the attributes of Derived, not Base, and
i couldn't discover any mechanism for finding out
the base classes of a given class.

I must be totally missing something important here...

Thanks in advance for any help!


Ping

Daniel Larsson

unread,
Jun 30, 1996, 3:00:00 AM6/30/96
to Ka-Ping Yee

Ka-Ping Yee wrote:
>
> I'm trying to understand what the convention for
> maintaining __dict__ is.
>
> I was getting a little confused because after
> creating a derived class, it didn't look like
> the methods from the base class were remembered:
>
> >>> class Base:
> ... def a(self): return 4
> ...
> >>> class Derived(Base):
> ... def b(self): return 5
> ...
> >>> Base.__dict__
> {'a': <function a at 8053660>, '__doc__': None}
> >>> Derived.__dict__
> {'b': <function b at 8053140>, '__doc__': None}
>
> ... (elided)

>
> I must be totally missing something important here...
>
> Thanks in advance for any help!
>
> Ping

What you are missing is a class's __bases__ attribute, a tuple of
all it's base classes. You have to recursively traverse that structure
to figure out the complete interface.
--
Daniel Larsson, ABB Industrial Systems AB

Ka-Ping Yee

unread,
Jul 1, 1996, 3:00:00 AM7/1/96
to

Daniel Larsson wrote:
>
> What you are missing is a class's __bases__ attribute, a tuple of
> all it's base classes. You have to recursively traverse that structure
> to figure out the complete interface.

Thank you. That helps. -- So is there really no easier way
to see the available methods than traversing the whole class
ancestry myself? All i want is a list of attribute names.

Perhaps this would be a commonly-needed-enough operation to add
a routine to generate the list to one of the standard modules?

Has anyone else ever wanted to do this?


Ping

Eric Daniel

unread,
Jul 1, 1996, 3:00:00 AM7/1/96
to

>>>>> "KY" == Ka-Ping Yee <s-p...@orange.cv.tottori-u.ac.jp> writes:

KY> Thank you. That helps. -- So is there really no easier way to see the
KY> available methods than traversing the whole class ancestry myself? All
KY> i want is a list of attribute names.

Unless I'm mistaken, newdir.dir() will do what you want.

>>> class C:
... a=1
...
>>> class D(C):
... b = 1
...
>>> d=D()
>>> import newdir
>>> newdir.dir(d)
['__doc__', 'a', 'b']


To have all class attributes, not only the methods, you need to apply the
following patch to newdir.py

*** Lib/newdir.py Mon Aug 1 06:28:43 1994
--- /usr/local/lib/python/newdir.py Mon Oct 23 18:38:08 1995
***************
*** 4,9 ****
--- 4,12 ----
# This should be the new dir(), except that it should still list
# the current local name space by default

+ # Updated Oct. 1995 by Eric Daniel.
+ # Now all the attributes of a class instance are listed, not only the methods.
+
def listattrs(x):
try:
dictkeys = x.__dict__.keys()
***************
*** 33,45 ****
total = dictkeys + methods + members
if the_class:
# It's a class instace; add the class's attributes
- # that are functions (methods)...
class_attrs = listattrs(the_class)
! class_methods = []
! for name in class_attrs:
! if is_function(getattr(the_class, name)):
! class_methods.append(name)
! total = total + class_methods
elif bases:
# It's a derived class; add the base class attributes
for base in bases:
--- 36,44 ----
total = dictkeys + methods + members
if the_class:
# It's a class instace; add the class's attributes
class_attrs = listattrs(the_class)
! total = total + class_attrs
!
elif bases:
# It's a derived class; add the base class attributes
for base in bases:
***************
*** 46,52 ****
base_attrs = listattrs(base)
total = total + base_attrs
total.sort()
- return total
i = 0
while i+1 < len(total):
if total[i] == total[i+1]:
--- 45,50 ----
***************
*** 56,67 ****
return total


- # Helper to recognize functions
-
- def is_function(x):
- return type(x) == type(is_function)
-
-
# Approximation of builtin dir(); but note that this lists the user's
# variables by default, not the current local name space.

--- 54,59 ----


--
Eric Daniel

Ka-Ping Yee

unread,
Jul 1, 1996, 3:00:00 AM7/1/96
to

Ka-Ping Yee wrote:
>
> Thank you. That helps. -- So is there really no easier way
> to see the available methods than traversing the whole class
> ancestry myself? All i want is a list of attribute names.

I'm sorry, i lied. I just realized that what i really need is
the ability to call a method with a constructed name.

Without inheritance, this is not hard (but a little long-winded):

methodname = a + b + c
instance.__class__.__dict__[methodname](instance, arguments)

Is this impossible to accomplish with a derived class?

(That is, without initiating a complete search of the
class ancestry for each attempt at a method call?)


Ping

Daniel Larsson

unread,
Jul 1, 1996, 3:00:00 AM7/1/96
to

Well, why not let Python do the searching for you?

>>> method = getattr(instance, methodname)
>>> method(arguments)

0 new messages