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
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
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
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
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
Well, why not let Python do the searching for you?
>>> method = getattr(instance, methodname)
>>> method(arguments)