2

I recently found out how to dynamically create variables in python through this method:

vars()['my_variable'] = 'Some Value'

Thus creating the variable my_variable.

My question is, is this a good idea? Or should I always declare the variables ahead of time?

martineau
  • 119,623
  • 25
  • 170
  • 301
Mark Skelton
  • 3,663
  • 4
  • 27
  • 47
  • 2
    No, no.​​​​​​​​ Why not just `my_variable = 'Some Value'` then? – vaultah Feb 17 '16 at 13:58
  • 3
    If you need any dynamic naming, use dicts. – bereal Feb 17 '16 at 14:02
  • Just because you can take advantage of the variable nanespace doesn't mean you should. You could override **anything** using those functions. – OneCricketeer Feb 17 '16 at 14:03
  • related: http://stackoverflow.com/questions/1373164/how-do-i-do-variable-variables-in-python – ivan_pozdeev Feb 17 '16 at 14:05
  • 2
    I was about to write a long answer about how this kind of dynamic naming makes it harder for machines and humans, even original authors to write correct code, but in essence, if OP were to just use dicts for everything, it would be the same problem. (Heck, we can infer from hints in the question that Python is already using dicts for everything.) So I won't blithely answer it that way. But I will say that human authors should strive for readability. – kojiro Feb 17 '16 at 14:07
  • 1
    In principle, there's nothing wrong with it. Though it'd make your code harder to read, which is against "best practice" conventions. Notwithstanding, if you can justify writing twice as much code, then I don't see why you shouldn't. Note that creating a variable by `my_var = my_value` is same, and calls the same functions, but it takes "longer" as it's implicit. Longer = nanoseconds longer! Though nanoseconds can turn into seconds if there's 1e9 of them. So again, is optimisation a factor? If so, you can also try `ctypes` or numpy `ctype` implementations, which are comparatively more elegant. – Pouria Feb 17 '16 at 14:17
  • @PouriaHadjibagheri I'm not sure what you are trying to say. `my_var = my_value` doesn't execute *any* functions if `my_var` is a simple name, and is probably the single fastest Python operation. That aside, modifying the return value of `vars()` is *documented* as being the wrong thing to do. – chepner Feb 17 '16 at 15:00
  • `my_var` does not magically become an allocated space with the value of `my_value` of size `double` in the memory. Python is a high level language, so it is done "implicitly", through a number of functions, each of which require initialisation and termination (through garbage collection in Python - which C lacks) which takes some time. So the less functions are called, the less time is wasted. I'm not saying this is necessarily the case here. I've never done it this way, and it needs to be tested. But in principle, if this is THE function called by the interpreter, then it should be faster! – Pouria Feb 17 '16 at 15:39
  • This post reminded me of a page I saw earlier this week, it shows you why it is a *bad* idea to declare variables dynamically. http://stupidpythonideas.blogspot.com/2013/05/why-you-dont-want-to-dynamically-create.html – Jerrybibo Feb 17 '16 at 14:03

5 Answers5

5

I think it's preferable to use a dictionnary if it's possible:

vars_dict = {}
vars_dict["my_variable"] = 'Some Value'
vars_dict["my_variable2"] = 'Some Value'

I think it's more pythonic.

Tiket_dev
  • 141
  • 1
  • 11
  • 1
    It's more pythonic to build dictionaries using dictionary literals. Especially, empty dictionaries. – vaultah Feb 17 '16 at 14:17
  • `vars_dict = { 'my_variable': 'Some Value', 'my_variable2': 'Some Value' }`? – kojiro Feb 17 '16 at 14:31
  • @kojiro The idea is to dynamically feed the dictionnary – Tiket_dev Feb 17 '16 at 14:34
  • Just a small, best practices, point. It is a better to define empty variables as literals. In other words, `vars_dict = dict()` is better that `vars_dict = {}`. I'm not saying the latter is wrong. I'm just saying the former is more explicit, and easier to go through. – Pouria Feb 17 '16 at 16:46
3

This is a bad idea, since it gets much harder to analyze the code, both for a human being looking at the source, and for tools like pylint or pychecker. You'll be a lot more likely to introduce bugs if you use tricks like that. If you think you need that feature at some time, think really hard if you can solve your problem in a simpler and more conventional way. I've used Python for almost 20 years, and never felt a need to do that.

If you have more dynamic needs, just use a normal dictionary, or possibly something like json.

One of the great things with Python, its dynamic nature and good standard collection types, is that you can avoid putting logic in text strings. Both the Python interpreter, syntax highlighting in your IDE, intellisense and code analysis tools look at your source code, provides helpful suggestions and finds bugs and weaknesses. This doesn't work if your data structure or logic has been hidden in text strings.

More stupid and rigid languages, such as C++ and Java, often makes developers resort to string based data structures such as XML or json, since they don't have convenient collections like Python lists or dicts. This means that you hide business logic from the compiler and other safety checks built into the language or tools, and have to do a lot of checks that your development tools would otherwise do for you. In Python you don't have to do that ... so don't!

Magnus Lyckå
  • 336
  • 2
  • 8
2

Pros:

  • adds another level of indirection, makes the environment more dynamic
    • in particular, allows to avoid more code duplication

Cons:

  • not applicable for function namespaces (due to optimization)
  • adds another level of indirection, makes the environment more dynamic
    • "lexical references" are much harder to track and maintain
      • if created names are arbitrary, conflicts are waiting to happen
      • it's hard to find the ins and outs in the code base and predict its behaviour
      • that's why these tricks may upset code checking tools like pylint
  • if variables are processed in a similar way, they probably belong together separately from others (in a dedicated dict) rather than reusing a namespace dict, making it a mess in the process

In brief, at the abstraction level Python's language and runtime features are designed for, it's only good in small, well-defined amounts.

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
2

There is no guarantee that vars()['myvariable'] = 'Some value' and my variable = 'Some value' have the same effect. From the documentation:

Without an argument, vars() acts like locals(). Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.

This code is simply wrong.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

I don't see what would be the advantage of it, also would make your code harder to understand. So no I don't think it is a good idea.

Marco Giordano
  • 600
  • 4
  • 14