selective (inheriting?) dir()?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon Apr 21 11:28:52 EDT 2014


On Mon, 21 Apr 2014 09:06:14 -0500, Skip Montanaro wrote:

[...]
> Now, dir(inst_b) will list both 'x' and 'y' as attributes (along with
> the various under under attributes). Without examining the source, is it
> possible to define some kind of "selective" dir, with a API like
> 
>     def selective_dir(inst, class_): pass
> 
> which will list only those attributes of inst which were first defined
> in (some method defined by) class_? The output of calls with different
> class_ args would yield different lists:
> 
>     selective_dir(inst_b, B) -> ['y']
> 
>     selective_dir(inst_b, A) -> ['x']

In general, no. There's no way of telling what method added an attribute 
after the event has taken place: given that instance.__dict__ has a key 
"x", how do you know how it got there?

You may be able to do this cooperatively: have both A and B define a 
__dir__ method which lists only the attributes they contribute, then call 
dir(A) or dir(B) as necessary.

Or, if you find yourself in the position of having an instance of both A 
and B, say, a and b, you can compare dir(a) and dir(b). Anything in the 
later but not in the former probably was added by B not A.

I say "probably" because one might have things like this:

class A:
    def __init__(self):
        if type(self) is not A:
            self.y = "Surprise!"
         self.x = "something"

and of course don't forget that attributes can be added by external 
entities too:

instance = A()
instance.z = "bet you forgot about this"

 
> I'm thinking some sort of gymnastics with inspect might do the trick,
> but after a quick skim of that module's functions nothing leapt out at
> me. OTOH, working through the code objects for the methods looks
> potentially promising:
> 
>>>> B.__init__.im_func.func_code.co_names
> ('A', '__init__', 'y')
>>>> A.__init__.im_func.func_code.co_names
> ('x',)


You may have a bit of difficulty with classes that write directly to the 
__dict__, or use setattr, or eval.



-- 
Steven D'Aprano
http://import-that.dreamwidth.org/



More information about the Python-list mailing list