I am relatively new to Python, and I'm wondering how I can call a variable in the name of a new variable.
For example, when I have the 2 following variables and their values:
number1 = 100
string1 = 'abc'
and I want to write a line of code such that I can create new variables who's name contains the values of variables number1 and string1 (e.g new_var_100 and new_var_abc)
For example:
new_var_(value_of_number1) = 200 ##What to write on LHS?
new_var_(value_of_string1) = 'def' ##What to write on LHS?
such that when I call new_var_100, it returns 200; and when I call new_var_abc, it returns 'def'.
Thanks very much.
not realy sure if you shuld do this but here goes:
string1 = 'abc'
globals()[f"string1{number1}]=200```
You can't - at least not without involving some very hacky solutions.
If you want to treat variable names as strings, modifying or concatenating them, you actually want a dictionary:
my_dict = {'number1' = 100, 'string1' = 'abc'}
You then access those values by passing the key values inside brackets - which fundamentally work like arbitrary variable names:
my_dict['number1'] # returns 100
my_dict['string1'] # returns 'abc'
you can then use a simple for loop to create new values based on some logic:
for value in my_dict.values():
my_dict['new_var_' + str(value)] = 200
Note that my code simply sets the values associated with the keys 'new_var_100' and 'new_var_abc' to 200. You'll need extra logic if you want to update strings and ints differently.
Related
First I tried directly storing values from a list having the name 'data' in an array variable 'c' using loop but 'none' got printed
for i in data:
print(i['name'])
c=i['name']
Here print(i['name']) perfectly worked and output appeared
This is the working ouput
Then I printed c in order to print the values generated using loop. The ouput came as none.
print(c)
Then I tried another way by storing the values and making the array iterable at the same time using for loop. An error occurred which I was unable to resolve.
for i in data:
b[c]=i['name']
c=c+1
The error apeared is as follow-
I have tried two ways, if there is any other way please help me out as I am new to python.
It looks like the variable 'data' is a dictionary.
If you want to add each name from that dictionary to a list:
# create a new list variable
names = []
for i in data:
name = i['name']
print(name)
# add the name to the list
names.append(name)
# output the new list
print(names)
Assuming your data object here is a list like [{"name": "Mr. Green", ...}, {"name": "Mr. Blue", ...}].
If your goal is to end up with c == ["Mr. Green", "Mr. Blue"], then you're looking for something like:
c = []
for i in data:
c.append(i['name'])
print(c)
or you can accomplish tasks like these using list comprehensions like:
c = [i['name'] for i in data]
print(c)
The first code example you posted is iterating through the items in data and reassigning the value of c to each item's name key - not adding them to a list("array"). Without knowing more about the code you ran to produce the screenshot and/or the contents of data, it's hard to say why you're seeing print(c) produce None. I'd guess the last item in data is something like {"name": None, ...} which if it's coming from JSON is possible if the value is null. Small note: I'd generally use .get("name") here instead so that your program doesn't blow up if an item is missing a "name" key entirely.
For your second code example, the error is different but I think falls along a similar logical fallacy which is that lists in python function differently from primitives(things like numbers and strings). For the interpreter to know that b or c are supposed to be lists("arrays"), they need to be instantiated differently and they have their own set of syntax/methods for mutation. For example, like arrays in other languages, lists are indexed by position so doing b[c] = <something> will only work if c is an integer. So something similar to your second example that would also produce a list of names like my above would be:
b = [None] * len(data)
c = 0
for i in data:
b[c]=i['name']
c=c+1
Note that if you only initialize b = [], you get an IndexError: list assignment index out of range on the initial assignment of b[0] = "some name" because the list is of size 0.
Add
b = []
above your first line of code. As the error is saying that you have not (and correctly so) defined the list to append.
I personally would use list comprehension here
b = [obj['name'] for obj in data]
where obj is i as you have defined it.
I have a simple pandas dataframe with a column 'mycol' and has 5 rows in it and I'm trying to create 5 new variables for every row value, something like below:
newcol_1=df['mycol'][0]
newcol_2=df['mycol'][1]
newcol_3=df['mycol'][2]
newcol_4=df['mycol'][3]
newcol_5=df['mycol'][4]
I don't want to hard code as above and I'm using the below "for loop" but it keeps throwing 'can't assign to operator'. I know that assignment values should be on the right and variable on the left but not sure how do I use for loop to dynamically create these 5 variables.
for i in 0, df.shape[0]-1:
#"newcol_"+str(i+1) =df['mycol'][i] # this isn't working
newcol_+str(i+1) =df['mycol'][i] # this also isn't working
Appreciate if anyone can help with this...Thanks!
Preferred option: modify globals()
# Create variables dynamically
for i, value in enumerate(df["VALUE"].values):
globals()[f"newcol_{i+1}"] = value
# Test that newcol_3 exists, for instance
print(newcol_3) # Works fine
print(newcol_3 == df['mycol'][2]) # True
Alternate option: use exec()
Though one should do so with caution
# Create a new dict with desired key/value pairs
newcols = {f"newcol_{i+1}": value for i, value in enumerate(df["VALUE"].values)}
# Create new variables dynamically from dict
for name, value in newcols.items():
exec(f"{name}= {value}")
# Previous tests work just as fine
I'd like to call a variable with a number in the name. I think the closest I've come is concatenating an iterator onto the name, and casting that as a dictionary but it doesn't work.
This is what I have tried:
dict0 = {"pet1":"dog", "pet2":"cat", "pet0":"bird"}
dict1 = {"first":"a", "second":"b", "third":"c"}
dict2 = {"num1":1,"num2":2,"num3":3}
for i in range(3):
tempDict = "dict"+str(i) # type is string
print(dict(tempDict))
output: ValueError: dictionary update sequence element #0 has length 1; 2 is required
These dictionaries are being populated with a database call, and the tables are numbered 0,1,2...n. Some days I have one dictionary, and some days multiple. It would be really convenient to be able to call them and act on the contents iteratively if possible. I'm not sure what to google for an answer, thank you in advance.
Assuming you have created the variables with the correct names (in this case dict0, dict1, dict2) you can get the values via their name using the vars() method
dict0 = {"pet1":"dog", "pet2":"cat", "pet0":"bird"}
dict1 = {"first":"a", "second":"b", "third":"c"}
dict2 = {"num1":1,"num2":2,"num3":3}
for i in range(3):
print(vars()[f"dict{i}"])
This prints each dict as expected
if you want to access dictionaries by their variable name try this:
dict0 = {"pet1":"dog", "pet2":"cat", "pet0":"bird"}
dict1 = {"first":"a", "second":"b", "third":"c"}
dict2 = {"num1":1,"num2":2,"num3":3}
for i in range(3):
dict_var_name = "dict"+str(i) # type is string
print(globals()[dict_var_name])
globals() return a dictionary which caontain all defined variables in global scope. for more information on this look at this question
Summary of issue: I'm trying to create a nested Python dictionary, with keys defined by pre-defined variables and strings. And I'm populating the dictionary from regular expressions outputs. This mostly works. But I'm getting an error because the nested dictionary - not the main one - doesn't like having the key set to a string, it wants an integer. This is confusing me. So I'd like to ask you guys how I can get a nested python dictionary with string keys.
Below I'll walk you through the steps of what I've done. What is working, and what isn't. Starting from the top:
# Regular expressions module
import re
# Read text data from a file
file = open("dt.cc", "r")
dtcc = file.read()
# Create a list of stations from regular expression matches
stations = sorted(set(re.findall(r"\n(\w+)\s", dtcc)))
The result is good, and is as something like this:
stations = ['AAAA','BBBB','CCCC','DDDD']
# Initialize a new dictionary
rows = {}
# Loop over each station in the station list, and start populating
for station in stations:
rows[station] = re.findall("%s\s(.+)" %station, dtcc)
The result is good, and is something like this:
rows['AAAA'] = ['AAAA 0.1132 0.32 P',...]
However, when I try to create a sub-dictionary with a string key:
for station in stations:
rows[station] = re.findall("%s\s(.+)" %station, dtcc)
rows[station]["dt"] = re.findall("%s\s(\S+)" %station, dtcc)
I get the following error.
"TypeError: list indices must be integers, not str"
It doesn't seem to like that I'm specifying the second dictionary key as "dt". If I give it a number instead, it works just fine. But then my dictionary key name is a number, which isn't very descriptive.
Any thoughts on how to get this working?
The issue is that by doing
rows[station] = re.findall(...)
You are creating a dictionary with the station names as keys and the return value of re.findall method as values, which happen to be lists. So by calling them again by
rows[station]["dt"] = re.findall(...)
on the LHS row[station] is a list that is indexed by integers, which is what the TypeError is complaining about. You could do rows[station][0] for example, you would get the first match from the regex. You said you want a nested dictionary. You could do
rows[station] = dict()
rows[station]["dt"] = re.findall(...)
To make it a bit nicer, a data structure that you could use instead is a defaultdict from the collections module.
The defaultdict is a dictionary that accepts a default type as a type for its values. You enter the type constructor as its argument. For example dictlist = defaultdict(list) defines a dictionary that has as values lists! Then immediately doing dictlist[key].append(item1) is legal as the list is automatically created when setting the key.
In your case you could do
from collections import defaultdict
rows = defaultdict(dict)
for station in stations:
rows[station]["bulk"] = re.findall("%s\s(.+)" %station, dtcc)
rows[station]["dt"] = re.findall("%s\s(\S+)" %station, dtcc)
Where you have to assign the first regex result to a new key, "bulk" here but you can call it whatever you like. Hope this helps.
I have a set of data that looks like so:
OutletCntrTemp|25degreesC|ok
InletTemp|17degreesC|ok
PCHTemp|46degreesC|ok
P0ThermMargin|-57degreesC|ok
P1ThermMargin|-59degreesC|ok
P0DIMMTemp|27degreesC|ok
P1DIMMTemp|27degreesC|ok
HSC0InputPower|60Watts|ok
HSC0InputVolt|12.46Volts|ok
CPU0Tjmax|90degreesC|ok
......
Now I want to loop through this data and create a list or a tuple in a function and return each row but name that tuple using the first part of the string:
CPUTjmax = ('90degreesC','ok')
now i did some spliting up of the string via | but hit a wall when i tried to use string[0] = (string[1],string[2]) to define the tuple.
Could anyone give me a pointer here please.
Ric
What you can do is, create a dict, and add them as key:value pair in it:
>>> d = dict()
>>>
>>> s = 'CPU0Tjmax|90degreesC|ok'
>>> li = s.split("|")
>>>
>>> d[li[0]] = (li[1], li[2])
>>> d
{'CPU0Tjmax': ('90degreesC', 'ok')}
You almost certainly don't want to create variables, use a dict instead:
data = [
'CPU0Tjmax|90degreesC|ok',
'InletTemp|17degreesC|ok'
]
d = {el[0]: tuple(el[1:]) for el in (item.split('|') for item in data)}
# {'InletTemp': ('17degreesC', 'ok'), 'CPU0Tjmax': ('90degreesC', 'ok')}
The other answers are good. Here is one more way, similar to the answer using locals(). You just create an empty object, and fill its __dict__:
class X(object):
pass
Var = X()
for ...:
Var.__dict__[string[0]] = (string[1], string[2])
#now you can refer to your vars as Var.whatever
if Var.InletTemp[1] != 'ok':
...
Use should definitely use a dictionary variable.
For completeness here a non-standard solution for creating new local variables:
for line in open("data.dat"):
e=line.split("|")
locals()[e[0]] = ( e[1], e[2] )
Internally, the local variables are also a dictionary which you can access with locals().
However, as the documentation says:
The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.