Enhanced dir() function

Discussion in 'Python' started by Steven D'Aprano, Jul 1, 2011.

  1. 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:

    >>> dir(str)

    ['__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:

    >>> dir(str, '*split*')

    ['rsplit', 'split', 'splitlines']


    Comments and improvements welcome.



    --
    Steven
    Steven D'Aprano, Jul 1, 2011
    #1
    1. Advertising

  2. Steven D'Aprano

    Tim Chase Guest

    On 06/30/2011 11:29 PM, Steven D'Aprano wrote:
    > 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
    Tim Chase, Jul 1, 2011
    #2
    1. Advertising

  3. Tim Chase wrote:

    > On 06/30/2011 11:29 PM, Steven D'Aprano wrote:
    >> 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.


    --
    Steven
    Steven D'Aprano, Jul 1, 2011
    #3
  4. Steven D'Aprano

    Ethan Furman Guest

    Tim Chase wrote:
    > 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~
    Ethan Furman, Jul 1, 2011
    #4
  5. Steven D'Aprano

    Ethan Furman Guest

    Ethan Furman wrote:
    > Tim Chase wrote:
    >> 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~
    Ethan Furman, Jul 12, 2011
    #5
  6. Steven D'Aprano

    rantingrick Guest

    On Jun 30, 11:29 pm, Steven D'Aprano <steve
    > wrote:
    > 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.
    rantingrick, Jul 12, 2011
    #6
  7. Steven D'Aprano

    rantingrick Guest

    On Jul 1, 12:20 pm, Tim Chase <> wrote:

    > 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
    ---------------------------
    >>> dir([])

    ['__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...

    >>> dir(verbose=False)

    ['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
    'reverse', 'sort']

    Ahhh, i love it when a plan comes together!
    rantingrick, Jul 12, 2011
    #7
  8. On Wed, Jul 13, 2011 at 7:46 AM, rantingrick <> wrote:
    >>>> [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...
    >
    >>>> dir(verbose=False)

    > ['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.)
    Chris Angelico, Jul 13, 2011
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?UnVkeQ==?=

    Sub Dir, Virtual dir, what do I use?

    =?Utf-8?B?UnVkeQ==?=, Jun 12, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    405
    =?Utf-8?B?UnVkeQ==?=
    Jun 12, 2005
  2. Matthew Denner
    Replies:
    1
    Views:
    154
  3. Kga Agk
    Replies:
    2
    Views:
    137
    Kga Agk
    Jun 29, 2009
  4. Nick Gnedin
    Replies:
    2
    Views:
    144
  5. MRAB
    Replies:
    0
    Views:
    110
Loading...

Share This Page