Best way to dynamically get an attribute from a module from withinthe same module

Discussion in 'Python' started by Rafe, Nov 24, 2008.

  1. Rafe

    Rafe Guest

    What are the pros and cons of these two patterns (and are there any
    other)? Which is the best way to dynamically get an attribute from a
    module from within the same module?

    1) Using the name of the module
    this_module = sys.modules[__name__]
    attr = getattr(this_module, "whatever", None)

    2) using globals
    globals()["whatever"]


    I have been using #1 for two reasons. First, I will never run this
    module directly, so __name__ will always be the module name and not
    "__main__". Second, I can use this in a class to decide whether I want
    the module where the class came from or, if I make the class a base
    for a class in another module, the module where the sub-class is.

    I am not familiar with the scope, pros or cons of globals() so I would
    love to hear comments on this subject.


    Cheers,

    - Rafe
     
    Rafe, Nov 24, 2008
    #1
    1. Advertising

  2. Re: Best way to dynamically get an attribute from a module fromwithin the same module

    En Mon, 24 Nov 2008 02:11:49 -0200, Rafe <> escribió:

    > What are the pros and cons of these two patterns (and are there any
    > other)? Which is the best way to dynamically get an attribute from a
    > module from within the same module?
    >
    > 1) Using the name of the module
    > this_module = sys.modules[__name__]
    > attr = getattr(this_module, "whatever", None)
    >
    > 2) using globals
    > globals()["whatever"]


    3) using the bare name:
    whatever

    1) and 2) are useful when the desired name is variable, not a constant
    like "whatever".

    > I have been using #1 for two reasons. First, I will never run this
    > module directly, so __name__ will always be the module name and not
    > "__main__".


    (note that it works even with __main__)

    > Second, I can use this in a class to decide whether I want
    > the module where the class came from or, if I make the class a base
    > for a class in another module, the module where the sub-class is.


    I don't completely understand your use case. In the expression:
    getattr(some_module, attribute_name)
    you may use any module as the first argument (the current module, or any
    other).

    > I am not familiar with the scope, pros or cons of globals() so I would
    > love to hear comments on this subject.


    Perhaps if you explain in more detail your use case, somebody else may
    have further comments...
    I don't have the need to use globals()[name] very often.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Nov 29, 2008
    #2
    1. Advertising

  3. Rafe

    Rafe Guest

    Re: Best way to dynamically get an attribute from a module fromwithin the same module

    <snip>
    > 3) using the bare name:
    > whatever
    > 1) and 2) are useful when the desired name is variable, not a constant like "whatever".


    I thought that went without saying.


    > > I have been using #1 for two reasons. First, I will never run this
    > > module directly, so __name__ will always be the module name and not "__main__".

    >
    > (note that it works even with __main__)


    Nice. Thanks.

    > > Second, I can use this in a class to decide whether I want
    > > the module where the class came from or, if I make the class a base

    > I don't completely understand your use case. In the expression:
    >     getattr(some_module, attribute_name)
    > you may use any module as the first argument (the current module, or any other).


    Right, I was just confused about the effects of inheritance and scope.
    If I put a method in a baseclass, which is inherited in another
    module, and then run the method from an instance of the sub-class...

    - "sys.modules[__name__]" returns the baseclass module.

    - "sys.modules[self.__class__.__module__]" returns the subclass
    module.

    in the end I found it felt more logical to put the code in a module-
    level function and call it from the class. All of this was part of a
    fairly large factory method implementation.


    I now know that globals() refers to module-level names. The pros and
    cons were the main point of this thread and so far I have...

    1) getattr(module, "whatever") seems the most pythonic way to do it
    but it takes more than one line and requires a little more thought
    about scope and inheritance.

    2) globals()["whatever"] is concise, but it seems a little like a
    shortcut which requires special knowledge (though a very small
    amount).

    I did a quick benchmark test:
    < tmp2.py >
    import time
    import sys

    import tmp

    class A(tmp.A): pass
    class B(tmp.A): pass
    class C(tmp.A): pass
    class D(tmp.A): pass
    class E(tmp.A): pass
    class F(tmp.A): pass
    class G(tmp.A): pass
    class H(tmp.A): pass
    class I(tmp.A): pass
    class J(tmp.A): pass


    def test_globals_vs_gettattr():
    t1 = time.time()
    for i in range(0, 1000000):
    H = globals()["H"]
    t2 = time.time()
    print "globals() too %s seconds." % str(t2-t1)

    t1 = time.time()
    mod = sys.modules[__name__]
    for i in range(0, 1000000):
    H = getattr(mod, "H")
    t2 = time.time()
    print "getattr() too %s seconds." % str(t2-t1)
    < /tmp2.py >

    tmp.py just has a simple class in it. I just wanted to add some
    complexity, but I doubt this had any affect on the times.

    >>> import tmp2
    >>> tmp2.test_globals_vs_gettattr()

    globals() too .146900010109 seconds.
    getattr() too .434299993515 seconds.


    Just to see how much the call to sys.modules was affecting the test, I
    moved it outside the loop and reloaded the module for a second test.
    >>> reload(tmp2)

    <module 'tmp2' from '\\nas6tb\PROJECTS\tech\users\rafe.sacks\python
    \tmp2.py'>
    >>> tmp2.test_globals_vs_gettattr()

    globals() too .139100003242 seconds.
    getattr() too .254600000381 seconds.

    This second test is pointless in practice since I would be calling
    sys.modules each time anyway.

    Even though the getattr() way is around 3.5 times slower, I had to run
    the code 1,000,000 times before the difference became humanly
    recognizable. I also realize benchmarks should be taken with a grain
    of salt since my setup may differ greatly from others'.

    I guess, in the end, I'd use getattr() because it feels more pythonic,
    and more basic. I got pretty deep in to learning python before I had
    to learn what the globals() dict could do for me.


    Cheers,

    - Rafe
     
    Rafe, Dec 1, 2008
    #3
  4. Re: Best way to dynamically get an attribute from a module from within the same module

    Rafe wrote:

    > I guess, in the end, I'd use getattr() because it feels more pythonic,
    > and more basic. I got pretty deep in to learning python before I had
    > to learn what the globals() dict could do for me.


    Why not store your individual classes inside another class or keep them in a
    dict? That would be clearer, would not mess around with global namespace,
    and more pythonic IMHO.

    Jeremy

    --
    Jeremy Sanders
    http://www.jeremysanders.net/
     
    Jeremy Sanders, Dec 1, 2008
    #4
    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. Frank Millman
    Replies:
    7
    Views:
    314
    Frank Millman
    Feb 5, 2004
  2. JuHui
    Replies:
    0
    Views:
    246
    JuHui
    Mar 18, 2006
  3. johnny
    Replies:
    5
    Views:
    741
    johnny
    Dec 10, 2006
  4. Replies:
    3
    Views:
    1,571
    Brandon McCombs
    May 2, 2007
  5. Ken Kuhlman

    Best way to do attribute docstrings?

    Ken Kuhlman, Sep 7, 2007, in forum: Python
    Replies:
    5
    Views:
    264
    Ken Kuhlman
    Sep 27, 2007
Loading...

Share This Page