This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 2 years ago.
In a different question I tried to use an enumerate and for element to create a pandas dataframe using the element as the name. It turns out the problem is more general. Is there anyway to set a variable value using something other than a plain string? In Bash this is done with the Read command, which takes the previous output into a subshell and assigns it to a variable name (I'll post my question on that below).
Any way to do this in Python? i.e., something simple like:
list1[0] = pd.dataframe(data), where list1[0] is a string. Or similarly using a dict key where the value is a dataframe:
for i in dict1: i = dict1[key] or for i in dict1: function(i) = dict1[key]?
The latter doesn't work using str() or any function because the error complains "SyntaxError: can't assign to function call", but maybe something similar?
Python: How can I use an enumerate element as a string?
https://unix.stackexchange.com/questions/338000/bash-assign-output-of-pipe-to-a-variable
https://unix.stackexchange.com/questions/574920/bash-how-to-get-stdout-to-console-and-also-pipe-to-next-command
EDIT:
Okay, well, after extended discussion with #juanpa.arrivillaga, he explained that strings are not plain strings as in Bash. Let's see if I have this right.. they are string objects stored in dict objects. (even integers are stored as objects unless using numpy or pandas which expand on Python arrays). Inside a for i in dict1: loop print(i) works because 'print will call str implicitly on any object you pass to it'. i = value does not because 'think of variables as nametags you throw on objects' and i is being resolved in its for loop scope as a dict object key. I'm not sure why, but variable 'nametags' cannot be string objects.
A workaround using globals() kind of mentioned in the Duplicate answers exists:
for key in dict1: globals()[key] = pd.DataFrame()
This is because in CPython, they used actual python objects to implement the global namespaces. It might be possible to 'maybe use ctypes to modify the namespace array in a local scope', as another workaround is to use SimpleNamespace to create a new object to store variables (presumably because they are stored as objects, the same as in globals(). And to wrap up, 'setattr(sys.modules[_name_], var_name, var_value) is equivalent to globals()[var_name] = var_value'.
Sorry it's quite hard to understand what exactly the question is.
for i in dict1: function(i) = dict[key]
A couple of problems with this: the thing on the left is what you're assigning, so the syntax should be dict[key] = function(i) (but don't call your dicts 'dict' because that's a reserved keyword). This is assuming key is defined somewhere. This is why you're getting the error you describe - you cant assign to a function call, you assign to variables.
As for storing things in list, you can put whatever you like in there, same with dictionaries. For example:
import pandas as pd
ls = [pd.DataFrame(), 'Hello']
d = {
'a': pd.DataFrame(),
1: pd.DataFrame()
}
print(ls)
print(d['a'])
print(d[1])
I think this issue can be solved with dictionaries:
var_names = ['your_string', 'your_second_string']
dict = {}
for i, var_name in enumerate(var_names):
var_name = f'var_name{i}'
dict[var_name] = pd.DateFrame([])
Related
This question already has answers here:
using locals() inside dictionary comprehension
(2 answers)
Closed last year.
Inside a script I have conditions to created variables with names of files. At the end of the script I want to know which variables were created. I use in locals() function to check it. If I do if with a simple list building it works fine, but with list comprehension I don't get the results. Why?
To be clear, I don't need suggestions to bypass the problem (I can just use the simple list building), just an explanation to the behaviour.
In my example file_08 and file_14 variables were created, but file_15 wasn't.
all_files = []
for file in ['file_08', 'file_14', 'file_15']:
if file in locals():
all_files.append(file)
print(all_files)
['file_08', 'file_14']
Works, but:
print([file for file in ['file_08', 'file_14', 'file_15'] if file in locals()])
[]
Doesn't work
The locals() function returns a dictionary containing the variables defined in the local namespace. Unless you have defined variables with the names 'file_88', 'file_14', and 'file_15' within the executable name space, you will get an empty list. You can verify this by printing the contents of locals() and see what you get back.
This question already has answers here:
How do I create variable variables?
(17 answers)
How can I create multiple variables from a list of strings? [duplicate]
(2 answers)
generating variable names on fly in python [duplicate]
(6 answers)
Closed 3 years ago.
I have a ticker and I want to check a specific list of tickers to see if the ticker is found. If it is found, it will replace it.
The new tickers come from another data source and therefore do not know which specific list of tickers to check. In order to find that list, I can pass the lists name as a string but upon iterating the code (naturally) recognizes this as string as opposed to a list to iterate.
Is there a way to have the code/function recognize that the string is actually a specific list to be checked? In reading other questions, I know this may not be possible...in that case what is an alternative?
list_1=['A','B']
list_2=['C','D']
old_ticker='A'
new_ticker='E'
assigned_list='list_1'
def replace_ticker(old_ticker,new_ticker,list):
for ticker in list:
if new_ticker in list:
return
else:
list.append(new_ticker)
list.remove(old_ticker)
replace_ticker(old_ticker,new_ticker,assigned_list)
You key the needed lists by name in a dictionary:
ticker_directory = {
"list_1": list_1,
"list_2": list_2
}
Now you can accept the name and get the desired list as ticker_directory[assigned_list].
list_1=['A','B']
list_2=['C','D']
lists = {
'list_1':list_1,
'list_2':list_2
}
old_ticker='A'
new_ticker='E'
assigned_list='list_1'
def replace_ticker(old_ticker,new_ticker,list_name):
if old_ticker not in lists[list_name]:
return
else:
lists[list_name].append(new_ticker)
lists[list_name].remove(old_ticker)
replace_ticker(old_ticker,new_ticker,assigned_list)
print(lists[assigned_list])
This is the complete program from what i perceived.
#prune already answered this, I have just given the whole solution
There are at least two possibilities:
1 As noted in comments kind of overkill but possible:
Use eval() to evaluate string as python expressions more in the link:
https://thepythonguru.com/python-builtin-functions/eval/
For example:
list_name = 'list_1'
eval('{}.append(new_ticker)'.format(list_name))
2 Second
Using locals() a dictionary of locally scoped variables similiar to the other answers but without the need of creating the dict by hand which also requires the knowledge of all variables names.
list_name = 'list_1'
locals()[list_name].append(new_ticker)
This question already has answers here:
Why doesn't assigning to the loop variable modify the original list? How can I assign back to the list in a loop? [duplicate]
(4 answers)
Closed 5 months ago.
I have a list and want to change its elements
list = ['apple','potato']
Now, while this works
for i in range(list):
list[i] = list[i].capitalize()
this one doesn't and I just don't get why
for i in list:
i = i.capitalize()
I'm new to Python, my only background is C++ so I'm still trying to adapt to Python's style. If this kind of question had already been asked, please, feel free to redirect me and close this topic. Thank you!
Assigning in the loop will create a new name i inside the for that loses its value after each iteration.
That isn't really the point here though. You can have the effect get noticed if you were dealing with mutable substructures that can be altered in-place, i.e:
l = [[1], [2]]
for i in l:
i.append(2)
changes will get reflected accordingly (sub-list will be get 2 appended to them).
in your case, though, you have strs which are immutable objects. i.capitalize(), acting on a str instance will create a new copy of the value which is assigned and then lost. It will not affect the objects inside the list.
The value i in for i in container: does refer to the objects contained in the sequence. When you assign i to the result of i.capitalize(), the name i will now refer to the new capitalized instance returned.
Don't try and draw parallels between C++ and Python, I know it sometimes makes learning easier but, other times, in can confuse the hell out of you.
Mandatory note: don't use list as a name, it masks the built-in name list.
Let's say I have a string like this.
string = "someString"
I now want to create a new instance of say, a dict() object using the variable stored in string. Can I do this?
string = dict()
Hoping it becomes "someString = dict()". Is this right? If not, how do i do it? Still learning python. Any help would be greatly appreciated.
Yes, it is possible to do this, though it is considered a bad thing to do:
string = 'someString'
globals()[string] = dict()
Instead you should do something like:
my_dynamic_vars = dict()
string = 'someString'
my_dynamic_vars.update({string: dict()})
then my_dynamic_vars[string] is a dict()
You really shouldn't do this, but if you really want to, you can use exec()
For your example, you would use this:
exec(string + " = dict()")
And this would assign a new dictionary to a variable by the name of whatever string is.
Using black magic, the kind that send you to python hell, it's possible.
The globals() and locals() functions, for example, will give you the dictionaries that contain variables currently in scope as (key, value) entries. While you can try to edit these dictionaries, the results are sometimes unpredictable, sometimes incorrect, and always undesirable.
So no. There is no way of creating a variable with a non-explicit name.
If the variable you want to set is inside an object, you can use setattr(instance,'variable_name',value)
I am writing a program in python and I am using a dictionary. I need to create an empty list for each key in the dictionary, and each list needs to have the same name as the key. The keys are user entered, which is why I can't just make a list in the conventional way.
This was the first thing I tried
a = {"x":1, "y":2, "z"3}
list(a.keys())
a.pop() = [] # This raises an error
I also tried to make the lists when the dictionary was being created, but this did not work either:
a = {}
b = input("INPUT1")
c = input("INPUT2")
a[b] = c
b = []
This created a list with the name "b" rather than whatever the user entered. Please help!!
This really doesn't make much sense. Why do your lists need 'names'? For that matter, what do you mean by 'names'?
Secondly, your code doesn't do anything. a.keys() is already a list. Calling list on it doesn't do anything else. But in any case, whatever the result of that line is, it is immediately thrown away, as you don't store the result anywhere.
pop doesn't work on dictionaries, it works on lists. And what does it mean to set the result of pop to a list? Are you trying to dynamically create a set of local variables with the names of each key in the dictionary? If so, why? Why not simply create another dictionary with the keys of the first, and each value as a new list? That can be done in one command:
b = dict((k, []) for k in b.keys())
(Note that dict.fromkeys() won't work here, as that would cause each element to share the same list.)
Use raw_input instead. input expects a valid Python expression and WILL evaluate whatever the user inputs. So if the user inputs a word, it'll evaluate that word and try to find an object with its name.
EDIT: for further clarification, input("INPUT1") is the equivalent of doing eval(raw_input("INPUT1")), for instance.