Getting not derived members of a class
Jeff Epler
jepler at unpythonic.net
Mon Aug 1 11:24:53 EDT 2005
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[i] == 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[i] > HAVE_ARGUMENT:
i += 3
else:
i += 1
return result
>>> import franz
>>> franz.find(y.__class__)
['__module__', 'who1', '__init__', '__doc__', '_b']
Jeff
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20050801/044efc77/attachment.sig>
More information about the Python-list
mailing list