Flip variable and it's value - python

I've done some looking on how I can flip a variable name and that variable's value, but I have come up empty-handed.
What I want
Let me clarify what I would like with an example.
Imagine I had a variable called my_variable and it's value would be a string 'my_new_variable'
my_variable = 'my_new_variable'
Is there any way that I can flip these so that it may look like this
my_new_variable = 'my_variable'

A dict is the appropriate way to do this. Driving internal symbol names with data is a strong sign of poor program design. Please use the dict, and refer to XY Problem. External data should drive data relations, but not the internal representation. By doing so, you make your algorithm's structure dependent on the data. Data manipulation should be independent of those specific values.
You can do it;; a little research on this site will give you the references. Don't.

Should you want to do that, how about
globals()[my_variable] = 'my_variable'

You can try doing this (after installing python-varname):
from varname import nameof
my_variable = 'my_new_variable'
exec("%s = '%s'" % (my_variable, nameof(my_variable))

One way this could be done and suggested by almost everyone who has commented is by using a dictionary then flipping the keys and values.
variables = {'my_variable':'my_new_variable'}
flipped = {v:k for k,v in variables.items()}
output
{'my_new_variable': 'my_variable'}

Related

when converting XML to SEVERAL dataframes, how to name these dfs in a dynamic way?

my code is on the bottom
"parse_xml" function can transfer a xml file to a df, for example, "df=parse_XML("example.xml", lst_level2_tags)" works
but as I want to save to several dfs so I want to have names like df_ first_level_tag, etc
when I run the bottom code, I get an error "f'df_{first_level_tag}'=parse_XML("example.xml", lst_level2_tags)
^
SyntaxError: can't assign to literal"
I also tried .format method instead of f-string but it also hasn't worked
there are at least 30 dfs to save and I don't want to do it one by one. always succeeded with f-string in Python outside pandas though
Is the problem here about f-string/format method or my code has other logic problem?
if necessary for you, the parse_xml function is directly from this link
the function definition
for first_level_tag in first_level_tags:
lst_level2_tags = []
for subchild in root[0]:
lst_level2_tags.append(subchild.tag)
f'df_{first_level_tag}'=parse_XML("example.xml", lst_level2_tags)
This seems like a situation where you'd be best served by putting them into a dictionary:
dfs = {}
for first_level_tag in first_level_tags:
lst_level2_tags = []
for subchild in root[0]:
lst_level2_tags.append(subchild.tag)
dfs[first_level_tag] = parse_XML("example.xml", lst_level2_tags)
There's nothing structurally wrong with your f-string, but you generally can't get dynamic variable names in Python without doing ugly things. In general, storing the values in a dictionary ends up being a much cleaner solution when you want something like that.
One advantage of working with them this way is that you can then just iterate over the dictionary later on if you want to do something to each of them. For example, if you wanted to write each of them to disk as a CSV with a name matching the tag, you could do something like:
for key, df in dfs.items():
df.to_csv(f'{key}.csv')
You can also just refer to them individually (so if there was a tag named a, you could refer to dfs['a'] to access it in your code later).

global variables and .format()

I wrote a python script that generates PDF reports. I had to do some data manipulation to change column names in each of the data sets I used.
My question is, Is there a way to set a global variable and then using .format() inside the Target_Hours_All.rename() ???
I have hardcoded each column name.
For example, Target_Hours_All.rename(columns = {'VP_x':'VP', '2018 Q1 Target Hours':'hourTarget18Q1'}, inplace = True)
However, I want to be able to run this each quarter without having to update every df.rename. Instead, I would like to have global variables at the top of the script and change those.
Any help would be greatly appreciated!!!
Easiest way? Move the strings you want to change out of the function call into variables and then use the variables within Target_Hours_All.rename()
This makes the code way lot easier to read.
I can only guess what Target_Hours_All.rename does. But my guess would be that it takes the hash in "columns" and replaces the key with the value. Correct?
So could write your columns line as:
columns = {}
vpl = 'VP_x'
vpr = 'VP'
columns[vpl] = vpr
target_hours_l = '20{year} {quarter} Target Hours'.format(year='18', quarter='Q1')
target_hours_r = 'hourTarget{year}{quarter}'.format(year='18',quarter='Q1')
columns[target_hours_l] = target_hours_r
Target_Hours_All.rename(columns = columns, ... )
Yes this is more code and I should not have named my has columns but something else instead. So there is way for improvement. But it shows how you can use .format() for your call.

Usng the value of a string as a variable name

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)

Python: Linking to a dictionary through a text string

I'm trying to create a program module that contains data structures (dictionaries) and text strings that describe those data structures. I want to import these (dictionaries and descriptions) into a module that is feeding a GUI interface. One of the displayed lines is the contents contained in the first dictionary with one field that contains all possible values contained in another dictionary. I'm trying to avoid 'hard-coding' this relationship and would like to pass a link to the second dictionary (containing all possible values) to the string describing the first dictionary. An abstracted example would be:
dict1 = {
"1":["dog","cat","fish"],
"2":["alpha","beta","gamma","epsilon"]
}
string="parameter1,parameter2,dict1"
# Silly example starts here
#
string=string.split(",")
print string[2]["2"]
(I'd like to get: ["alpha","beta","gamma","epsilon"]
But of course this doesn't work
Does anyone have a clever solution to this problem?
Generally, this kind of dynamic code execution is a bad idea. it leads to very difficult to read and maintain code. However, if you must, you can use globals for this:
globals()[string[2]]["2"]
A better solution would be to put dict1 into a dictionary in the first place:
dict1 = ...
namespace = {'dict1': dict1}
string = ...
namespace[string[2]]["2"]

Get global variables from file as dict?

I've got a file, constants.py, that contains a bunch of global constants. Is there a way I can grab all of them as dict, for just this file?
It should be simple:
import constants
print(constants.__dict__)
import constants
constants_dict = {}
for constant in dir(constants):
constants_dict[constant] = getattr(constants, constant)
I'm not sure I see the point of this though. How is writing constants_dict['MY_CONSTANT'] any better/easier/more readable than constants.MY_CONSTANT?
EDIT:
Based on the comments, I see some potential uses now.
Here's another way to write the above, depending on how compact you want it.
constants_dict = dict((c, getattr(constants, c)) for c in dir(constants))
EDIT2:
cji for the win! constants.__dict__

Categories