I have some code that generates two strings - digit_ and 'x', where x is an integer. My gut feeling is that this is a stupid question, but I can't find an answer online. I have variables called digit_1, digit_2 ... etc up to digit_9. How can I call the correct one of these without using a really long if/elif function? Is there a way of calling a variable from a concatenation of it's name?
Sam
The cleanest way is to put the variables into a list or a dictionary, and then access them by index or by name.
No, there isn't a good way to "create" variable names and access them.
However, you can just use a list, and index into it instead.
Related
I didn't try anything because I don't even know where to start...
the program would associate every item of the list to the variables like (name)1, (name)2, (name)3, and so on to the number of items the list has.
prdt = ["WD40", "001", "oleo de carro, 1L", "liquidos", "seccao 1", 5, 30]
prdt1 ="WD40"
prdt2 ="001"
prdt3 ="oleo de carro, 1L"
prdt4 ="liquidos"
a program that creates a variable incremented by 1 in a for a loop.
Basically with python version above 3.8 you can use eval and walrus operator in order to achieve this behaviour. You will get variables with names corresponding to your list items
for idx, item in enumerate(prdt):
eval(f"({item}{idx}:={item})")
If you look at this weird syntax in eval it's walrus operator := combined with a parenthesis and all that in a f-string. Very unreadable and ugly solution imho, but eval only allows for expressions, NOT compound statements (so you cannot use the regular assignment with = ).
And you have int values in your list, which will cause the above code to fail, since var name in python cannot be an int... 5=5 is not a legal code, neither are values with spaces...Overall sorry to say, but this question does not make too much sense to be honest.
But in general it sounds like a terrible idea to be honest (whatever is your usecase). If you need to associate specific names with values you should use dict probably.
For debugging purposes I need to know the values of some variables in Python. But, I don't want create a dictionary with all variables and don’t want to add every new variable that I want to test at some point to a dictionary, especially when it comes to lists and their content, which is often procedurally generated.
So is there an alternative to just taking input as a string and then executing it by exec() or using print() and hardcoded variables?
Yes, there is a way. You can use the locals() function to get a dictionary of all variables. For example:
a=5
b=locals()["a"]
Now b will get the value of a, i.e. 5.
However, while you can do this doesn't mean you should do this. There may be something wrong in the structure of your program if you want to access variables by using their name stored in a string.
I have a list of objects. I want to call the variables or functions of the objects in that list. (With so many basic keywords in this problem, it's been quite difficult to find a solution or guide for this!)
E.g.:
for each in current_staff_list:
print(current_staff_list[each].variable_name)
What's the correct syntax to do this?
each is already the right element:
for each in current_staff_list:
print(each.variable_name)
Python for loops give you the element itself, not an index into the sequence.
I'm fairly new to python and have found that I need to query a list about whether it contains a certain item.
The majority of the postings I have seen on various websites (including this similar stackoverflow question) have all suggested something along the lines of
for i in list
if i == thingIAmLookingFor
return True
However, I have also found from one lone forum that
if thingIAmLookingFor in list
# do work
works.
I am wondering if the if thing in list method is shorthand for the for i in list method, or if it is implemented differently.
I would also like to which, if either, is more preferred.
In your simple example it is of course better to use in.
However... in the question you link to, in doesn't work (at least not directly) because the OP does not want to find an object that is equal to something, but an object whose attribute n is equal to something.
One answer does mention using in on a list comprehension, though I'm not sure why a generator expression wasn't used instead:
if 5 in (data.n for data in myList):
print "Found it"
But this is hardly much of an improvement over the other approaches, such as this one using any:
if any(data.n == 5 for data in myList):
print "Found it"
the "if x in thing:" format is strongly preferred, not just because it takes less code, but it also works on other data types and is (to me) easier to read.
I'm not sure how it's implemented, but I'd expect it to be quite a lot more efficient on datatypes that are stored in a more searchable form. eg. sets or dictionary keys.
The if thing in somelist is the preferred and fastest way.
Under-the-hood that use of the in-operator translates to somelist.__contains__(thing) whose implementation is equivalent to: any((x is thing or x == thing) for x in somelist).
Note the condition tests identity and then equality.
for i in list
if i == thingIAmLookingFor
return True
The above is a terrible way to test whether an item exists in a collection. It returns True from the function, so if you need the test as part of some code you'd need to move this into a separate utility function, or add thingWasFound = False before the loop and set it to True in the if statement (and then break), either of which is several lines of boilerplate for what could be a simple expression.
Plus, if you just use thingIAmLookingFor in list, this might execute more efficiently by doing fewer Python level operations (it'll need to do the same operations, but maybe in C, as list is a builtin type). But even more importantly, if list is actually bound to some other collection like a set or a dictionary thingIAmLookingFor in list will use the hash lookup mechanism such types support and be much more efficient, while using a for loop will force Python to go through every item in turn.
Obligatory post-script: list is a terrible name for a variable that contains a list as it shadows the list builtin, which can confuse you or anyone who reads your code. You're much better off naming it something that tells you something about what it means.
I would like to do the following (just an example, the real code has more menu's and more add_command's):
editmenu.add_command(label="Cut",state="disabled")
editmenu.add_command(label="Copy",state="disabled")
editmenu.add_command(label="Paste",state="disabled")
editmenu.add_command(label="Delete",state="disabled")
But on fewer lines, In fact, just one line if possible. I have menus that are taking up a considerable amount of space in my program and would like to reduce the clutter. Plus the programmer in me sees a bunch of similar lines and feels there must be a way to reduce them.
I tried the following code to no avail; I obviously got a nameerror because label and state aren't defined...
for labeldic in [{label:"Cut"},{label:"Copy"},{label:"Paste"},{label:"Delete"}]: editmenu.add_command(labeldic+{state:"disabled"})
Thanks in advance for any suggestions!
Here's a translation of what you wanted to do:
for labeldic in [{"label":"Cut"},{"label":"Copy"},{"label":"Paste"},{"label":"Delete"}]:
labeldic.update({"state": "disabled"})
editmenu.add_command(**labeldic)
There were three problems I fixed.
The first is that dictionary keys need to be quoted if they are strings. If you want a dict mapping the string 'label' to the the string 'cut', you can do it using the dict literal {'label': 'cut'}, or else possibly with the dict() constructor which expands keyword arguments that way: dict(label='cut'). As you discovered, {label: 'cut'} wouldn't work, because it tries to use a variable's value for the key, but there is no such variable.
The second is that you can't merge dictionaries using the + operator. It doesn't work, unfortunately. There is, however, an update method that mutates the dict it's called on. Since it doesn't return a merged dict, it can't be used inline the way you used +.
The third problem is that passing a dict is not the same as passing in keyword arguments. foo(bar='baz') is not the same as foo({'bar':'baz'}), but it is the same as foo(**{'bar':'baz'}). The ** syntax in function calling "unpacks" a dictionary into keyword arguments.
Regardless it's sort of weird style. Here's what I would do instead:
for label in ['Cut', 'Copy', 'Paste', 'Delete']:
editmenu.add_command(label=label, state='disabled')