selective (inheriting?) dir()?

Skip Montanaro skip at pobox.com
Mon Apr 21 11:52:49 EDT 2014


Thanks for the responses. I'm not really interested in perfection
here. I do most of my programming in a mature internally developed
platform written in Python. As the platform has grown and approaches
to different problems have changed  12-15 year period, some of the
classes which are instantiated have grown quite a few attributes which
are not interesting on a day-to-day basis. As I often query my objects
at runtime and use dir() to jog my memory about what's changing, it
would be nice to eliminate most attributes defined by and only used by
base classes.

Thanks for the suggestion of writing a custom __dir__ method. I hadn't
considered that. It was fairly straightforward to build its attribute
list on-the-fly, taking a snapshot of attributes just after
the base class __init__ method was call, and again after
initialization was complete. The only trick was to leave __dir__
undefined until after that little dance was complete.

Skip


On Mon, Apr 21, 2014 at 10:28 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> 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/
> --
> https://mail.python.org/mailman/listinfo/python-list



More information about the Python-list mailing list