167

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.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526

4 Answers4

277
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).

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 9
    The docs give a warning about modifying vars(). http://docs.python.org/library/functions.html#vars . When is it okay to do this? – unutbu May 29 '10 at 02:44
  • 2
    @~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. – Mike Graham May 29 '10 at 03:06
  • 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? – unutbu May 29 '10 at 03:36
  • 4
    `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()`;-) – Alex Martelli May 29 '10 at 03:39
  • 1
    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? – unutbu May 29 '10 at 03:54
  • 15
    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. – Alex Martelli May 29 '10 at 05:07
  • 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 May 29 '10 at 05:18
  • @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. – Alex Martelli May 29 '10 at 05:55
  • @Alex Martelli: As there is no way for me to message you here, perhaps you might take a look at http://stackoverflow.com/questions/2447353/getattr-on-a-module, which is of great interest to me. – Matt Joiner May 29 '10 at 09:46
  • 1
    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. – msw May 29 '10 at 14:33
  • 3
    @msw, I think you forgot "practicality beats purity";-). – Alex Martelli May 29 '10 at 15:20
  • 1
    @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. – Alex Martelli May 29 '10 at 15:28
  • 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. – msw May 29 '10 at 15:32
  • @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;-). – Alex Martelli May 29 '10 at 15:58
  • 1
    @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. – msw May 30 '10 at 14:15
  • @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? – Matt Joiner May 31 '10 at 08:25
15

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}")
Trey Hunner
  • 10,975
  • 4
  • 55
  • 114
6

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']
msw
  • 42,753
  • 9
  • 87
  • 112
  • 1
    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. – msw May 29 '10 at 05:45
  • 1
    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. – Curt Feb 10 '16 at 05:22
-1
  1. You wouldn't. You would do globals()["SOME_CONSTANT"] = 42
  2. You wouldn't. You would store dynamically-generated content somewhere other than a module.
Mike Graham
  • 73,987
  • 14
  • 101
  • 130
  • 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. – msw May 29 '10 at 02:52
  • 4
    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. – Matt Joiner May 29 '10 at 05:20