How do I call setattr() on the current module?

64,072

Solution 1

import sys

thismodule = sys.modules[__name__]

setattr(thismodule, name, value)

or, without using setattr (which breaks the letter of the question but satisfies the same practical purposes;-):

globals()[name] = value

Note: at module scope, the latter is equivalent to:

vars()[name] = value

which is a bit more concise, but doesn't work from within a function (vars() gives the variables of the scope it's called at: the module's variables when called at global scope, and then it's OK to use it R/W, but the function's variables when called in a function, and then it must be treated as R/O -- the Python online docs can be a bit confusing about this specific distinction).

Solution 2

In Python 3.7, you will be able to use __getattr__ at the module level (related answer).

Per PEP 562:

def __getattr__(name):
    if name == "SOME_CONSTANT":
        return 42
    raise AttributeError(f"module {__name__} has no attribute {name}")

Solution 3

If you must set module scoped variables from within the module, what's wrong with global?

# my_module.py

def define_module_scoped_variables():
    global a, b, c
    a, b, c = 'a', ['b'], 3

thus:

>>> import my_module
>>> my_module.define_module_scoped_variables()
>>> a
NameError: name 'a' is not defined
>>> my_module.a
'a'
>>> my_module.b
['b']
Share:
64,072

Related videos on Youtube

Matt Joiner
Author by

Matt Joiner

About Me I like parsimonious code, with simple interfaces and excellent documentation. I'm not interested in enterprise, boiler-plate, or cookie-cutter nonsense. I oppose cruft and obfuscation. My favourite languages are Go, Python and C. I wish I was better at Haskell. Google+ GitHub Bitbucket Google code My favourite posts http://stackoverflow.com/questions/3609469/what-are-the-thread-limitations-when-working-on-linux-compared-to-processes-for/3705919#3705919 http://stackoverflow.com/questions/4352425/what-should-i-learn-first-before-heading-to-c/4352469#4352469 http://stackoverflow.com/questions/6167809/how-much-bad-can-be-done-using-register-variables-in-c/6168852#6168852 http://stackoverflow.com/questions/4141307/c-and-c-source-code-profiling-tools/4141345#4141345 http://stackoverflow.com/questions/3463207/how-big-can-a-malloc-be-in-c/3486163#3486163 http://stackoverflow.com/questions/4095637/memory-use-of-stl-data-structures-windows-vs-linux/4183178#4183178

Updated on March 18, 2020

Comments

  • Matt Joiner
    Matt Joiner over 4 years

    What do I pass as the first parameter "object" to the function setattr(object, name, value), to set variables on the current module?

    For example:

    setattr(object, "SOME_CONSTANT", 42);
    

    giving the same effect as:

    SOME_CONSTANT = 42
    

    within the module containing these lines (with the correct object).

    I'm generate several values at the module level dynamically, and as I can't define __getattr__ at the module level, this is my fallback.

  • unutbu
    unutbu about 14 years
    The docs give a warning about modifying vars(). docs.python.org/library/functions.html#vars . When is it okay to do this?
  • msw
    msw about 14 years
    Yep, SOME_CONSTANT computed at run-time isn't exactly constant. And if globals() isn't available to you then you must be reaching into another module to modify its attributes; that's bound to get people wondering.
  • Mike Graham
    Mike Graham about 14 years
    @~unutbu, I wouldn't really say that it's quite "okay", but it will work when you call vars() at module-level scope rather than inside of a function.
  • unutbu
    unutbu about 14 years
    Thanks for the information, @Mike. Is there an easy way to understand why vars() behaves this way (okay at module-level but not in functions)? Was it a restriction by design, or something else?
  • Alex Martelli
    Alex Martelli about 14 years
    vars() is equivalent to globals() at module scope (and so returns a true, modifiable dict) but to locals() at function scope (and so returns a never-to-be-modified pseudodict). I use vars() at module scope as it saves 3 characters, one syllable, vs its synonym-in-that-scope globals();-)
  • unutbu
    unutbu about 14 years
    Okay, that's helpful, @Alex; thanks. But why should locals() at function scope return a never-to-be-modified pseudodict? Would there have been something wrong with exposing a modifiable dict here?
  • Alex Martelli
    Alex Martelli about 14 years
    Yes, it would have destroyed the single most important optimization the Python compiler does: a function's local variables are not kept in a dict, they're in a tight vector of values, and each local variable access uses the index in that vector, not a name lookup. To defeat the optimization, forcing the dict you desire to exist, start the function with exec '': time a function with a couple substantial loops each way, and you'll see the importance of this core optimization to Python's performance.
  • Matt Joiner
    Matt Joiner about 14 years
    Hm is there any reason I can't just do globals()[name] = value, keeping in mind that "This is always the dictionary of the current module", and that vars() is equivalent to globals() in your answer? Is it safe to do this?
  • Matt Joiner
    Matt Joiner about 14 years
    Constant and mutable are mutually exclusive. Constant and dynamically generated are not. The values I'm generating are always the same, and determined based on further "constants", to save on arithmetic and typing on my part.
  • msw
    msw about 14 years
    Yeah, I've always (where "always" is defined as the "last few months I've been learning Python") found that global but not really declaration puzzling. I suppose it may be a historical relic that predates module namespaces.
  • Alex Martelli
    Alex Martelli about 14 years
    @Matt, sure, it's safe (vars and globals are equivalent at module top level, and if you're in a function it's globals you want to use to set a module-level variable anyway). Though you can use setattr, as you chose to ask in this question, you can also get the same effect with the indexed assignment in question. And, by the way, you can also have a __getattr__ on what behaves just about like a module (can be imported etc), but, I guess that's yet another issue.
  • Matt Joiner
    Matt Joiner about 14 years
    @Alex Martelli: As there is no way for me to message you here, perhaps you might take a look at stackoverflow.com/questions/2447353/getattr-on-a-module, which is of great interest to me.
  • msw
    msw about 14 years
    Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Readability counts. Special cases aren't special enough to break the rules. There should be one-- and preferably only one --obvious way to do it. If the implementation is hard to explain, it's a bad idea.
  • Alex Martelli
    Alex Martelli about 14 years
    @msw, I think you forgot "practicality beats purity";-).
  • Alex Martelli
    Alex Martelli about 14 years
    @Matt, ah yes, @Håvard S's solution in that Q is what I had in mind (having originally published it myself in the Cookbook, I upvoted when I saw it given on SO;-) -- that it doesn't work after import * I see as one of the zillion problems with import *, not with the solution in question; that it doesn't work on barenames ("within the current module" as you say) is true, but then barenames are so entirely different from qualified names that it shouldn't be expected to.
  • msw
    msw about 14 years
    Fair nuff, so what's practical about vars()[name] = value other than "it saves 3 characters, one syllable" that makes it special enough to break the rules, be implicit, be unreadable, be hard to explain, and depends heavily on the knowledge of the particular implementation. Yeah, it's clever, so is the C construct i++-++j and if it happens to work the way you want on your platform, does anything else really matter? Do note how much explanation this so-called practical example made to an intelligent, interested reader.
  • Alex Martelli
    Alex Martelli about 14 years
    @msw, oh, I thought you were commenting on my several few comments (about how locals() can't practically be a dict), not one from 12 hours ago - hard to keep track when you give no reference. There's nothing implicit or unreadable about vars, it's not especially clever, it works uniformly across platforms, and the only thing that makes it confusing is that it's documented wrong in the online docs. Guess I'll edit the answer to point this out since this appears to really make you go off the deep end;-).
  • msw
    msw about 14 years
    @matt: assuming that your question is an honest one - I'm new to Python and was attracted to PEP 20 "Zen of Python" principles that make well written Python code almost self-evidently trivial. I find that overuse of __setattr__ is apparently very seductive yet has the net effect of making code mysterious. Overuse of meta-syntactic constructs tends to make code reading difficult for exactly the reasons the C preprocessor is presently shunned for past abuses.
  • Matt Joiner
    Matt Joiner about 14 years
    @msw: Okay now your comments make sense. I'm just happy that it works, and that Alex's description has removed confusion on my part. I can see however, that having both vars() and globals(), and even the fact that globals() is a misleading name... not ideal, but who's counting?
  • Curt
    Curt over 8 years
    The original question is asking how to set an attribute whose name is given by a string (the same thing I was presently searching for), so this would not help.