Why do some object methods/attributes not show up when I call dir on the object?
Example:
from scipy import sparse
e = sparse.eye(2)
'H' in dir(e)
returns False. But calling e.H works just fine (returning another sparse matrix object). Why is this so, and how can I see these hidden attributes?
I'm using Python 3.5.1.
解决方案
e.H, e.A, e.T are pseudo-properties of the sparse matrix object.
shape is a property. In sparse.base.py I find
shape = property(fget=get_shape, fset=set_shape)
while the dict only contains:
In [121]: e.__dict__
Out[121]:
{'_shape': (2, 2),
'data': array([[ 1., 1.]]),
'format': 'dia',
'maxprint': 50,
'offsets': array([0])}
get_shape probably accesses _shape. set_shape probably limits our ability to change _shape.
I don't know of a neat way of finding all the defined properties for an object like this. Ideally they should be listed in the documentation, but sparse documentation is not ideal.
There is an e.getH method, which returns the same thing as e.H, so I suspect there's a piece of code, probably in some superclass
H = property(fget=getH)
Nope - in sparse.base.py I find a redefinition of __getattr__, so it's an entirely different mechanism (not property and not __dict__):
def __getattr__(self, attr):
if attr == 'A':
return self.toarray()
elif attr == 'T':
return self.transpose()
elif attr == 'H':
return self.getH()
elif attr == 'real':
return self._real()
elif attr == 'imag':
return self._imag()
elif attr == 'size':
return self.getnnz()
else:
raise AttributeError(attr + " not found")
In ipython I can fetch this with In [152]: e.__getattr__?? or sparse.base??.
getattr can be used to fetch all these attributes and properties (and methods)
In [161]: getattr(e,'shape')
Out[161]: (2, 2)
In [162]: getattr(e,'_shape')
Out[162]: (2, 2)
In [163]: getattr(e,'H')
Out[163]:
<2x2 sparse matrix of type ''
with 2 stored elements in Compressed Sparse Column format>
In [164]: getattr(e,'transpose')
Out[164]:
'
with 2 stored elements (1 diagonals) in DIAgonal format>>
With the inspect module I can get a list of members, e.g.
[i[0] for i in inspect.getmembers(e)]
but that still doesn't list these special ones defined in the __getattr__ method.