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__
Related
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'}
I'm guessing this will be a really simple problem but I have no solution yet.
I have a long code that does modelling and updates values of variables for optimisation. The code is initially written like this:
init_old(x,y):
return {(k):olddict[k][x][0]*prod[y] for k in realnames}
Q_house=init_old(“Q_house”,"P_house")
Q_car=init_old(“Q_car”,"P_car")
Q_holiday=init_old(“Q_holiday”,"P_holiday")
I already can simplify it a bit with a comprehension:
ListOfExpenses=["house","car","holiday"]
Q_house, Q_car, Q_holiday=[init_old(“Q_”+i,"P0_"+i) for i in ListOfExpenses]
I am trying to find an equivalent but more flexible way of writing that final line, so that I change the list of Expenses and the "Q_..." variables together easily:
ListOfExpenses=["house","car","holiday"]
ListOfCost=["Q_house","Q_car","Q_holiday"]
Elements_Of_ListOfCost=[init_old(“Q_”+i,"P0_"+i) for i in ListOfExpenses]
So when I look for Q_house, Q_car or Q_holiday later, it returns the same Q_house=init_old(“Q_house”,"P_house") calculated in the original code.
I don't want to use dictionaries for now as they would require major change to the rest of the code and calling dictionaries causes problems in some of the other functions. Thanks in advance for the help.
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)
It's kind of hard to explain but I'm using a directory that has a number of different files but essentially I want to loop over files with irregular intervals
so in pseudocode I guess it would be written like:
A = 1E4, 1E5, 5E5, 7E5, 1E6, 1.05E6, 1.1E6, 1.2E6, 1.5E6, 2E6
For A in range(start(A),end(A)):
inputdir ="../../../COMBI_Output/Noise Studies/[A] Macro Particles/10KT_[A]MP_IP1hoN0.0025/"
Run rest of code
Because at the moment I'm doing it manually by changing the value in [A] and its a nightmare and time consuming. I'm using Python on a macbook so I wonder if writing a bash script that is called within Python would be the right idea?
Or replacing A with a text file, such that its:
import numpy as np
mpnum=np.loadtxt("mp.txt")
for A in range(0,len(A)):
for B in range(0,len(A)):
inputdir ="../../../COMBI_Output/Noise Studies/",[A] "Macro Particles/10KT_",[A]"MP_IP1hoN0.0025/"
But I tried this first and still had no luck.
You are almost there. You don't need a range, just iterate over the list. Then do a replacement in the string using format.
A = ['1E4', '1E5', '5E5', '7E5', '1E6', '1.05E6', '1.1E6', '1.2E6', '1.5E6', '2E6']
for a in A:
inputdir = "../../../COMBI_Output/Noise Studies/{} Macro Particles/10KT_{}MP_IP1hoN0.0025/".format(a)
The idea of putting the file names in a list and simply iterating over them using
for a in A:
seems to be the best idea. However, one small suggestion, if I may, instead of having a list, if you're going to have a large number of files inside this list, why not make it a dictionary? In this way, you can iterate through your files easily as well as keep a count on them.
I have to dump data from SAS datasets. I found a Python module called sas7bdat.py that says it can read SAS .sas7bdat datasets, and I think it would be simpler and more straightforward to do the project in Python rather than SAS due to the other functionality required. However, the help(sas7bdat) in interactive Python is not very useful and the only example I was able to find to dump a dataset is as follows:
import sas7bdat
from sas7bdat import *
# following line is sas dataset to convert
foo = SAS7BDAT('/support/sas/locked_data.sas7bdat')
#following line is txt file to create
foo.convertFile('/support/textfiles/locked_data.txt','\t')
This doesn't do what I want because a) it uses the SAS variable names as column headers and I need it to use the variable labels, and b) it uses "nan" to denote missing numeric values where I'd rather just leave the value blank.
Can anyone point me to some useful documentation on the methods included in sas7bdat.py? I've Googled every permutation of key words that I could think of, with no luck. If not, can someone give me an example or two of using readColumnAttributes(), readColumnLabels(), and/or readColumnNames()?
Thanks, all.
As time passes, solutions become easier. I think this one is easiest if you want to work with pandas:
import pandas as pd
df = pd.read_sas('/support/sas/locked_data.sas7bdat')
Note that it is easy to get a numpy array by using df.values
This is only a partial answer as I've found no [easy to read] concrete documentation.
You can view the source code here
This shows some basic info regarding what arguments the methods require, such as:
readColumnAttributes(self, colattr)
readColumnLabels(self, collabs, coltext, colcount)
readColumnNames(self, colname, coltext)
I think most of what you are after is stored in the "header" class returned when creating an object with SAS7BDAT. If you just print that class you'll get a lot of info, but you can also access class attributes as well. I think most of what you may be looking for would be under foo.header.cols. I suspect you use various header attributes as parameters for the methods you mention.
Maybe something like this will get you closer?
from sas7bdat import SAS7BDAT
foo = SAS7BDAT(inFile) #your file here...
for i in foo.header.cols:
print '"Atrributes"', i.attr
print '"Labels"', i.label
print '"Name"', i.name
edit: Unrelated to this specific question, but the type() and dir() commands come in handy when trying to figure out what is going on in an unfamiliar class/library
I know I'm late for the answer, but in case someone searches for similar question. The best option is:
import sas7bdat
from sas7bdat import *
foo = SAS7BDAT('/support/sas/locked_data.sas7bdat')
# This converts to dataframe:
ds = foo.to_data_frame()
Personally I think the better approach would be to export the data using SAS then process the external file as needed using Python.
In SAS, you can do this...
libname datalib "/support/sas";
filename sasdump "/support/textfiles/locked_data.txt";
proc export
data = datalib.locked_data
outfile = sasdump
dbms = tab
label
replace;
run;
The downside to this is that while the column labels are used rather than the variable names, the labels are enclosed in double quotes. When processing in Python, you may need to programmatically remove them if they cause a problem. I hope that helps even though it doesn't use Python like you wanted.