Getting not derived members of a class

  • Thread starter Franz Steinhaeusler
  • Start date
F

Franz Steinhaeusler

Hello NG,

I want to retrieve the members of a class
with a baseclass.
But the problem is, how to get the non derived
members.

class a:
def who(self):
print "who"
def __init__(self):
self._a = 3

class b(a):
def who1(self):
print "who1"
def __init__(self):
a.__init__(self)
self._b = 4

y=b()

dir (y)
['__doc__', '__init__', '__module__', '_a', '_b', 'who', 'who1']


I need a function which lists only the members of
the "not derived" class (here class B).

_b
_who1
__init__

How can I achieve this?
With the introspect module or so?

many thanks in advance!
 
G

George Sakkis

Franz said:
Hello NG,

I want to retrieve the members of a class
with a baseclass.
But the problem is, how to get the non derived
members.

class a:
def who(self):
print "who"
def __init__(self):
self._a = 3

class b(a):
def who1(self):
print "who1"
def __init__(self):
a.__init__(self)
self._b = 4

y=b()

dir (y)
['__doc__', '__init__', '__module__', '_a', '_b', 'who', 'who1']


I need a function which lists only the members of
the "not derived" class (here class B).

_b
_who1
__init__

How can I achieve this?
With the introspect module or so?

I believe you can't: Both _a and _b end up in y.__dict__ and there's no
way to differentiate between the two depending on the time of their
creation. By the way, these are instance attributes, not class
attributes, so strictly _b is not a member of B, it's just an instance
of y. To see why this is the case, check the following valid (though
highly discouraged) example:

class X:
def __init__(self, x):
if isinstance(x,str):
self._s = x
else:
self._n = x

x1 = X("1")
x2 = X(1)

dir(x1)
['__doc__', '__init__', '__module__', '_s']

dir(x2)
['__doc__', '__init__', '__module__', '_n']


George
 
F

Franz Steinhaeusler

Franz said:
Hello NG,

I want to retrieve the members of a class
with a baseclass.
But the problem is, how to get the non derived
members.

class a:
def who(self):
print "who"
def __init__(self):
self._a = 3

class b(a):
def who1(self):
print "who1"
def __init__(self):
a.__init__(self)
self._b = 4

y=b()

dir (y)
['__doc__', '__init__', '__module__', '_a', '_b', 'who', 'who1']


I need a function which lists only the members of
the "not derived" class (here class B).

_b
_who1
__init__

How can I achieve this?
With the introspect module or so?

I believe you can't: Both _a and _b end up in y.__dict__ and there's no
way to differentiate between the two depending on the time of their
creation. By the way, these are instance attributes, not class
attributes, so strictly _b is not a member of B, it's just an instance
of y. To see why this is the case, check the following valid (though
highly discouraged) example:

class X:
def __init__(self, x):
if isinstance(x,str):
self._s = x
else:
self._n = x

x1 = X("1")
x2 = X(1)

dir(x1)
['__doc__', '__init__', '__module__', '_s']

dir(x2)
['__doc__', '__init__', '__module__', '_n']


George

Hello George,

thank you for this information.

This is a pity.

The background:
I want to create a code completition for an editor component.
It should distinguish between inherited and non inherited members.
Reason is, that on wxPython, most classes are derived from wxWindow.
For example if I want Code completition for wx.Frame,
I always get the 200 or so suggestions,
whereby most times, I'm only interested in the possible completions of
wx.Frame and maybe wx.TopLevelWindow.
 
J

Jeff Epler

On 'y', Python has no way of recording where '_a' and '_b' were set, so
you can't tell whether it comes from class 'a' or 'b'.

You can find the attributes that are defined on 'b' only, though, by
using 'b.__dict__.keys()', or 'y.__class__.__dict__.__keys__()'. This
gives
['__module__', 'who1', '__init__', '__doc__']

If you want to limit yourself to current versions of cpython (because the
bytecode used in cpython is only an implementation detail) and define a 'member
of class a' as one where a.__init__ has a statement like 'self.z = ...', you
can peer into the bytecodes. Something like this:
from dis import HAVE_ARGUMENT, opname
LOAD_FAST = chr(opname.index('LOAD_FAST'))
STORE_ATTR = chr(opname.index('STORE_ATTR'))
HAVE_ARGUMENT = chr(HAVE_ARGUMENT)

def find(cls):
ns = cls.__dict__
result = ns.keys()
init = ns.get('__init__', None)
if not init: return ns
f = ns['__init__'].func_code.co_code
n = ns['__init__'].func_code.co_names
i = 0
while i < len(f) - 6:
if (f == LOAD_FAST and f[i+1] == f[i+2] == '\0'
and f[i+3] == STORE_ATTR):
j = ord(f[i+4]) + 256 * ord(f[i+5])
result.append(n[j])
i += 6
elif f > HAVE_ARGUMENT:
i += 3
else:
i += 1
return result
['__module__', 'who1', '__init__', '__doc__', '_b']

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD4DBQFC7j7AJd01MZaTXX0RAtwGAJixxnxi/IwFamOKOu0UiytCSuFwAKCNPRvg
At7d3NWBO90k7s1QTCu+MA==
=OssF
-----END PGP SIGNATURE-----
 
F

Franz Steinhaeusler

On 'y', Python has no way of recording where '_a' and '_b' were set, so
you can't tell whether it comes from class 'a' or 'b'.

You can find the attributes that are defined on 'b' only, though, by
using 'b.__dict__.keys()', or 'y.__class__.__dict__.__keys__()'. This
gives
['__module__', 'who1', '__init__', '__doc__']

If you want to limit yourself to current versions of cpython (because the
bytecode used in cpython is only an implementation detail) and define a 'member
of class a' as one where a.__init__ has a statement like 'self.z = ...', you
can peer into the bytecodes. Something like this:
from dis import HAVE_ARGUMENT, opname
LOAD_FAST = chr(opname.index('LOAD_FAST'))
STORE_ATTR = chr(opname.index('STORE_ATTR'))
HAVE_ARGUMENT = chr(HAVE_ARGUMENT)

def find(cls):
ns = cls.__dict__
result = ns.keys()
init = ns.get('__init__', None)
if not init: return ns
f = ns['__init__'].func_code.co_code
n = ns['__init__'].func_code.co_names
i = 0
while i < len(f) - 6:
if (f == LOAD_FAST and f[i+1] == f[i+2] == '\0'
and f[i+3] == STORE_ATTR):
j = ord(f[i+4]) + 256 * ord(f[i+5])
result.append(n[j])
i += 6
elif f > HAVE_ARGUMENT:
i += 3
else:
i += 1
return result
['__module__', 'who1', '__init__', '__doc__', '_b']

Jeff


Hello Jeff,

thank you for this desciption.

Well, a little complicated, I must read/try this later,
but it looks promising to get the "last derived class" members ;)


Is there any possibility to simply get out
the classes and baseclasses of a class?

somfunc (y) => class A, B (where B is last).

Ok you can prepare a class, but I need to use
the existing wxPython classes.
 
R

Reinhold Birkenfeld

Franz said:
The background:
I want to create a code completition for an editor component.
It should distinguish between inherited and non inherited members.
Reason is, that on wxPython, most classes are derived from wxWindow.
For example if I want Code completition for wx.Frame,
I always get the 200 or so suggestions,
whereby most times, I'm only interested in the possible completions of
wx.Frame and maybe wx.TopLevelWindow.

You can, of course, always search the base classes and subtract the two sets
(all members)-(members of baseclasses). For example:

cls = wx.Frame

set(dir(cls)) - reduce(set.union, [set(dir(base)) for base in cls.__bases__])

Reinhold
 
F

Franz Steinhaeusler

Franz said:
The background:
I want to create a code completition for an editor component.
It should distinguish between inherited and non inherited members.
Reason is, that on wxPython, most classes are derived from wxWindow.
For example if I want Code completition for wx.Frame,
I always get the 200 or so suggestions,
whereby most times, I'm only interested in the possible completions of
wx.Frame and maybe wx.TopLevelWindow.

You can, of course, always search the base classes and subtract the two sets
(all members)-(members of baseclasses). For example:

cls = wx.Frame

set(dir(cls)) - reduce(set.union, [set(dir(base)) for base in cls.__bases__])

Reinhold

Hello Reinhold,

yes, cool, thank you very much!

The optimum would be getting also the other base classes, with the
members, but I think, it is asked to much.

'wx.Frame' ... => CreateStatusBar, ...
'wx.TopLevelWindow' ... => GetIcon, ...
'wx.Window' ... => ...
'wx.EvtHandler' => ...
 
G

George Sakkis

Franz said:
Is there any possibility to simply get out
the classes and baseclasses of a class?

somfunc (y) => class A, B (where B is last).

If you use "new-style" classes, i.e. classes inheriting from object, it
is trivial:

class X(object):
pass

class Y1(X):
pass

class Y2(X):
pass

class Z(Y1,Y2):
pass
(<class '__main__.Z'>, <class '__main__.Y1'>, <class '__main__.Y2'>,
<class '__main__.X'>, <type 'object'>)

Old style classes don't have __mro__, so you have to write it yourself;
in any case, writing old style classes in new code is discouraged.

George
 
B

Brian Beck

George said:
(<class '__main__.Z'>, <class '__main__.Y1'>, <class '__main__.Y2'>,
<class '__main__.X'>, <type 'object'>)

Old style classes don't have __mro__, so you have to write it yourself;
in any case, writing old style classes in new code is discouraged.

Notice also that George's __mro__ solution returns the bases in reverse
order than what you requested (in your example, you said B should come
last). So use list(reversed(z.__class__.__mro__)) or
z.__class__.__mro__[::-1]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,311
Members
47,981
Latest member
satome

Latest Threads

Top