Enhanced dir() function

  • Thread starter Steven D'Aprano
  • Start date
S

Steven D'Aprano

The dir() function is designed for interactive use, inspecting objects for
the names of attributes and methods.

Here is an enhanced version that allows you to pass a glob to filter the
names you see:

http://code.activestate.com/recipes/577774-enhancing-dir-with-globs/

E.g. instead of this:
['__add__', '__class__',
... snip 60+ other names ...
'upper', 'zfill']

you can easily filter the results to show only names that interest you, by
passing a glob:
['rsplit', 'split', 'splitlines']


Comments and improvements welcome.
 
T

Tim Chase

The dir() function is designed for interactive use, inspecting objects for
the names of attributes and methods.

Here is an enhanced version that allows you to pass a glob to filter the
names you see:

Comments and improvements welcome.

Having not seen any other comments on it fly by, I thought I'd
respond. While in general I like the idea, I'm not sure when I'd
go to the effort of bringing the function into my namespace when
I could just do something like
[s for s in dir(...) if test_of_interest(s)]

If it came in as an effortless (i.e. O(1) where I do it once and
never again; not an O(n) where n=the number of times I invoke
Python) default replacement for dir(), I'd reach for it a lot
more readily. I seem to recall there's some environment-var or
magic file-name that gets sourced on every startup.

I use the list-comp version on a regular basis:

# implementation of which magic methods?
[s for s in dir(foo) if s.startswith('__') and s.endswith('__')]

# ignore magic methods
[s for s in dir(foo) if not (s.startswith('__') and
s.endswith('__'))]

# constants
[s for s in dir(foo) if s.isupper()]

# keywording
[s for s in dir(foo) if 'bar' in s.lower()]

Anyways, even if it just includes a brief blurb about "and this
is how you get it automatically in every Python session" (or a
link to the docs on how to do that), it would raise it from "meh"
to "nifty".

-tim
 
S

Steven D'Aprano

Tim said:
The dir() function is designed for interactive use, inspecting objects
for the names of attributes and methods.

Here is an enhanced version that allows you to pass a glob to filter the
names you see:

Comments and improvements welcome.

Having not seen any other comments on it fly by, I thought I'd
respond. While in general I like the idea, I'm not sure when I'd
go to the effort of bringing the function into my namespace when
I could just do something like
[s for s in dir(...) if test_of_interest(s)]

If test_of_interest is complex, then the list comp is the better solution.
Globbing dir is intended for simple globs (naturally!), not complex filter
functions of arbitrary complexity. The equivalent is globbing in the shell:

[steve@sylar python]$ dir p*.py
parallel_map.py partition.py perms.py proc.py pyprimes.py
paragraphs.py peekable.py pi.py progress.py

If it came in as an effortless (i.e. O(1) where I do it once and
never again; not an O(n) where n=the number of times I invoke
Python) default replacement for dir(), I'd reach for it a lot
more readily. I seem to recall there's some environment-var or
magic file-name that gets sourced on every startup.

There is some talk on the python-ideas mailing list about enhancing the
built-in dir().

But in the meantime, you can add it to your site.py module, or better still,
use your own personal startup file rather than the system site.py. I have
an environment variable set in my .bashrc file:

export PYTHONSTARTUP=/home/steve/python/startup.py

and then put code I want to run at startup in startup.py. For Windows users,
I don't know how to set environment variables, but I dare say it would be
something similar: set the environment variable PYTHONSTARTUP to a file
name, and put the code in that file.

I use the list-comp version on a regular basis:

# implementation of which magic methods?
[s for s in dir(foo) if s.startswith('__') and s.endswith('__')]

This would become:

dir(foo, "__*__")

# ignore magic methods
[s for s in dir(foo) if not (s.startswith('__') and
s.endswith('__'))]

dir(foo, "[!_]*[!_]")

although strictly speaking, my version only tests for one leading and
trailing underscore, not two.
# constants
[s for s in dir(foo) if s.isupper()]

That's beyond the capabilities of simple globbing.

# keywording
[s for s in dir(foo) if 'bar' in s.lower()]

I'm of two minds about case-insensitive globbing. It could be done with a
slight change to the function, but I'm not sure if I want to.

Anyways, even if it just includes a brief blurb about "and this
is how you get it automatically in every Python session" (or a
link to the docs on how to do that), it would raise it from "meh"
to "nifty".

Thanks for the feedback.
 
E

Ethan Furman

Tim said:
If it came in as an effortless (i.e. O(1) where I do it once and never
again; not an O(n) where n=the number of times I invoke Python) default
replacement for dir(), I'd reach for it a lot more readily. I seem to
recall there's some environment-var or magic file-name that gets sourced
on every startup.

interact.py
8<-----------------------------------------------
import os, sys
sys.ps1 = '--> '

from cookbook.utils import dir # or whereever you keep your copy
sys.modules['__builtin__'].dir = dir
8<-----------------------------------------------


~Ethan~
 
E

Ethan Furman

Ethan said:
Tim said:
If it came in as an effortless (i.e. O(1) where I do it once and never
again; not an O(n) where n=the number of times I invoke Python)
default replacement for dir(), I'd reach for it a lot more readily. I
seem to recall there's some environment-var or magic file-name that
gets sourced on every startup.

interact.py
8<-----------------------------------------------
import os, sys
sys.ps1 = '--> '

from cookbook.utils import dir # or whereever you keep your copy
sys.modules['__builtin__'].dir = dir
8<-----------------------------------------------


Imagine my amusement when I went to change an environment variable today
and found:

PYTHONSTARTUP=c:\python25\interact.py

~Ethan~
 
R

rantingrick

The dir() function is designed for interactive use, inspecting objects for
the names of attributes and methods.

Here is an enhanced version that allows you to pass a glob to filter the
names you see:

meh,

I have always believed in keeping my namespace squeaky clean so i
never have this problem. Modules like Tkinter (where you yourself have
supported the global import!) i always import as "tk". I think this IS
more a housekeeping issue than a "nail on patch" issue.

PS: However pay attention because i have some interesting ideas about
"dir culling" in my next post to this thread.
 
R

rantingrick

If it came in as an effortless (i.e. O(1) where I do it once and
never again; not an O(n) where n=the number of times I invoke
Python) default replacement for dir(), I'd reach for it a lot
more readily.  I seem to recall there's some environment-var or
magic file-name that gets sourced on every startup.

I use the list-comp version on a regular basis:

I strongly agree with this statement because i prefer the LC myself.
HOWEVER i've always lamented the verbosity of dir().
---------------------------
Case in Point
---------------------------
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__delslice__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__getitem__', '__getslice__', '__gt__',
'__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__',
'__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__reversed__', '__rmul__',
'__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__',
'__subclasshook__', 'append', 'count', 'extend', 'index', 'insert',
'pop', 'remove', 'reverse', 'sort']
---------------------------

Do we really need to see all the built in methods EVERY time? I don't,
i've had them memorized for years. HOWEVER i do understand the fact
that n00bs need to see them every time. So why should old hats need to
type this every time...
[x for x in dir([]) if not x.startswith('_')]
['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
'reverse', 'sort']

Because we have plenty of room for args in this function...
['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
'reverse', 'sort']

Ahhh, i love it when a plan comes together!
 
C

Chris Angelico

[x for x in dir([]) if not x.startswith('_')]
['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
'reverse', 'sort']

Because we have plenty of room for args in this function...
['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
'reverse', 'sort']

#define my_dir(o,verbose) verbose?dir(o):[x for x in dir(o) if not
x.startswith('_')]

And there you are, out of your difficulty at once. Granted, you now
have to run your code through cpp, but is that so big a problem?

ChrisA
(For the sarcasm-impaired: I am NOT advocating this.)
 

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,159
Messages
2,570,881
Members
47,418
Latest member
NoellaXku

Latest Threads

Top