First of all, i am somewhat new to python coding, so this might seem like a stupid question.
Problem: I am trying to create a script that allows me to import a number into (variable?operator?) names, in order to run my python script from a bash script.
Ideally i wanted to do the following (i know the syntax is wrong, but it is from my first try and captures what i would want it to do):
replica_number = 2 #2 is only for testing. It will later be exchanged with an imported number from a bash script over many different data sheets.
t_r+replica number = md.load(data_path+'potein_+replica_number+_centered.xtc', top = data_path+'potein_+replica_number+_first.gro')[1:]
What i want this to do is to automatically create the variables named t_r2 and import the files called protein_2_centered.xtc and protein_2_first.gro. However when i do this i get: SyntaxError: can't assign to operator
Does anyone know how to get around this problem, or do i just have to make a separate script for every replica?
What you need is either a list or a dictionary.
you can keep all your results in a list (without keeping the replica_number):
t_r_list = []
t_r_list.append(md.load(...)[1:]) # Run this line for each t_r you want to load
or if you want to keep the replica_number, you can use a dict:
t_r_dict = {}
t_r_dict[replica_number] = md.load(...)[1:]
You might want to read a tutorial on these data structures and how to use them, it will greatly help you on your journey with python later on and is the basis of the basis when it comes to working with data in python.
when the name of the attributes or variables is dynamic, we can use, for example, the new way Python uses for fomat Strings (f'') and then the setattr method:
The settattr method is this, is part of the builtins library:
def setattr(x, y, v): # real signature unknown; restored from __doc__
""" Sets the named attribute on the given object to the specified value."""
Here what you can do with variables
replica_number = 2
variable_name = f't_r{replica_number }'
and then check and set the aatribute:
if not hasattr(YOUR_OBJECT, variable_name ):
raise ValueError
setattr(YOUR_OBJECT, variable_name , THE_VALUE)
Use a dictionary for such kind of operations:
replica_number = md.load(...)[1:]
your_dict = {t_r : replica_number}
And access it through
your_dict[t_r]
Related
I'm trying to convert a list into callable functions. I'm writing a top level program to interface with a program that reads different data types.
I previously loaded a module that has these functions defined as well as many others, but we only want to use these 4. We want to be able to adjust from a top level the dataList
dataList= ['sat1', 'sat2', 'sat3', 'sat4'] #(top line input by user)
readData = ['ob.rd_'+L for L in dataList]
for n in range(0,np.size(dataList)): readData[n]('file.'+dataList[n])
Loaded module has functions ob.rd_sat1, ob.rd_sat2, ob.rd_sat3, etc (over 50 different read functions) defined and ready to go. I generate a list with only the functions I want to call. list of function names but defined as string not variable/function names
Here is where I am pulling my hair out by the roots. I cannot get the program to recognize the list of names as functions.
I get
Error: 'str' object is not callable.
I've googled this but cannot find any answer that works. Seems simple but ....
If the functions are in a module, or are methods on an object, you can use getattr to convert a string to the function of the same name.
Example:
import random
names = ("randint", "uniform")
for name in names:
func = getattr(random, name)
result = func(0,100)
print("{}: {}".format(name, result))
In your case, if you want to convert "sat1" into the function ob.rd_sat1, you can do it like this:
import ob
...
dataList= ['sat1', 'sat2', 'sat3', 'sat4']
funcs = [getattr(ob, "rd_" + name) for name in dataList]
For the third statement use
for n in range(0,np.size(dataList)): globals()[readData[n]]('file.'+dataList[n])
In case the functions are not global, use locals instead of globals!
Update 1:
As #Bryan Oakley has pointed out,
you can also use
dataList= ['sat1', 'sat2', 'sat3', 'sat4']
readData = ['rd_'+L for L in dataList]
for n in range(0,np.size(dataList)): getattr(ob, readData[n])('file.'+dataList[n])
Question
We are getting a strange error** and we suspect it is because our script.py*** assigned a variable that already has some built-in meaning. E.g.
str = 2
Is there a way we can check if this has happened?
So far
We're thinking it would involve:
Assign a list at the beggining of the script, containing all built-in objects' names as strings:
builtin_names = get_builtin_var_names() # hypothetical function
Assign a list at the end of the script, containing all user-assigned objects' names as strings:
user_names = get_user_var_names() # hypothetical function
Find the intersection, and check if not empty:
overwritten_names = list(set(user_names) & set(builtin_names))
if overwritten_names:
print("Whoops")
Related
Is there a way to tell if a function in JavaScript is getting over
written?
Is there a common way to check in Python if an object
is any function type?
**Silent error, for those interested in it, it is silent, i.e. it finishes without an error code but the value it spits out differs between two implementations of the same code, call them A and B... both versions require the running of two modules (separate files) that we've made (changes.py and dnds.py), but whereas:
Version A: involves running changes.py -> pickle intermediate data (into a .p file) -> dnds.py,
Version B: involves running changes.py -> return the data (a dict) as arguments to dnds.py -> dnds.py.
And for some reason only version A is the one with the correct final value (benchmarked against MATLAB's dnds function).
***script.py, is actually dnds.py (who has imported changes.py). You can find all the code, but to test the two alternative versions I was talking about in ** you need to specifically look at dnds.py, the line with: CTRL+F: "##TODO:Urgent:debug:2016-11-28:". Once you find that line, you can read the rest of that comment line for instructions how to replicate version B, and its resulting silent error**. For some reason I HAVE to pickle the data to get it to work... when I just return the dicts directly I get the wrong dN/dS values.
You can get the names (and values) of builtins via the dict __builtins__. You can get the names (and values) of global variables with globals() and of locals with locals(). So you could do something like:
import __builtin__
name, val = None, None
for name, val in locals().iteritems():
if hasattr(__builtin__, name) and getattr(__builtin__, name) != val:
print("{} was overwritten!".format(name))
and then the same for globals(). This will check whether there is any object in the local namespace that has a different value in the builtins namespace. (Setting name and val to None is needed so that the variables exist before calling locals, or else you'll get a "dictionary changed sized during iteration" error because the names are added partway through the loop.)
You could also use a tool like pylint which checks for such errors among many others.
I have an application that reads multiple variable names from one block of an input file. Then it reads the associated values from another block of the same file.. e.g. variable names read in as ABC,DEF,GEF,etc and values read in as 1,2,3,etc. In Python, can I create those variables at run time, e.g. perform the following code.
ABC = 1
DEF = 2
GHI = 3
I am quite new to Python so forgive if this is a stupid question...
Sounds like you need a dictionary. A dictionary is a way of looking up values based on another value. In this case the values are the strings that you read from the file. For example:
myvars = {}
myvars['ABC'] = 1
myvars['DEF'] = 2
myvars['GHI'] = 3
Velox is right, you should use a dictionary to store this kind of data:
vars = {}
vars['ABC'] = 1
print vars['ABC'] # 1
But just to answer your question, you have different ways to create variables at runtime:
eval
You can use eval to evaluate strings as if they were written in the source:
eval('ABC = 1')
print ABC # 1
namespace access
You can use globals() and locals() to access the global and local namespace (they are a dictionary). Then you can add another name with a value:
globals()['ABC'] = 1
print ABC # 1
Both these ways are not safe, in fact with eval you are executing external code that can be malicious or also crash your program. globals is the namespace of your program and messing with it could make it misbehave. So consider sticking to dictionaries.
In Python you technically can create global variables dynamically using globals:
globals()["ABC"] = 1
but it's something that is done rarely because most often a separate dictionary is a better choice (see Velox response). The function globals() simply returns the dictionary that Python uses to store global (module) variables.
Unless you're a Python expert and you really know what you're doing most probably using globals is a bad idea (however a Python expert wouldn't ask about it here).
Unfortunately there is not enough information in your question for me to guess what you're trying to accomplish by creating variables dynamically, so it's hard to provide a correct solution.
I am attempting to use a module called interface.py which defines a list of conditions and a few functions to check arguments against those conditions. There are many thousands of conditions however, and so I want to use a dictionary instead of a list to prevent needing to look at all of them. To do this I'm using the following code:
def listToDictionary(list):
"""This function takes a list of conditions and converts it to a dictionary
that uses the name of the condition as a key."""
d = {}
for condition in list:
if condition.name.lower() not in d:
d[condition.name.lower()] = []
d[condition.name.lower()].append(condition)
return d
conditionList = listToDictionary(conditions.list) #the condition list comes from another module
Further into the file are the actual interface functions that take arguments to compare with the list of conditions - these functions are written assuming that conditionList will be a dictionary.
Unfortunately this isn't working. Giving error details is difficult because this code is being imported by a django page and I am trying to avoid talking about django so this question stays uncomplicated. Essentially the pages including this code will not load, and if I change it back to just using a list everything works fine.
My suspicion is that the problem has to do with how Python treats import statements. I need the listToDictionary conversion to run as soon as interface.py is imported, otherwise the interface functions will expect a dictionary and get a list instead. Is there any way to ensure that this is happening?
An educated guess: the list in conditions.list is not yet fully constructed when your module is being imported. As a result, you get a dictionary that is missing some entries or even empty, which is causing problems later. Try deferring the construction of the dict, like this:
conditionTable = None # shouldn't call it list if it's a dict
def get_cond_table():
global conditionTable
if conditionTable is None:
conditionTable = listToDictionary(conditions.list)
return conditionTable
Instead of referring to conditionList in your functions, refer to get_cond_table().
Alright, I found out that the problem was in another function that was still expecting the dictionary to be a list. The reason I couldn't see it right away is that Django left a very cryptic error message. I was able to get a better one using python manage.py shell and importing the module manually.
Thanks for your help everyone.
I've come across many articles which don't quite address what I'm attempting to do. I hope that this isn't a duplicate question.
I am writing a Python script which interfaces with several real-world objects outside of my PC. I have written classes which contain the functions necessary to interface with those objects. I have also successfully written a function, not very object oriented in style, which instantiates instances of those classes, gets data from them, and saves it all to a CSV file. That all works fine. Where I'm getting tripped up is in trying to make the function more adaptable so that I don't have to re-write it every time I want to add another class instance or get a different data point from a pre-existing instance.
The approach that I'm attempting is to create a list which contains names of class instances and specific function names to get data out of those instances. I then pass this list to another function. This other function would ideally create a header for my CSV file (so that the data can be more easily interpreted) and then proceed to gather the data.
Pseudocode:
inst1 = my_class_1()
inst2 = my_class_2()
filename = 'fubar.csv'
control_list = ['inst1', 'value1', 'inst2', 'value']
my_fucntion(filename, control_list):
# Code to create a header for CSV file in the form inst1-value1, inst2-value2
# Loop to control the number of times to grab data
# Code which iterates control_list and builds up things like inst1.value1(), inst2.value2(),
# etc. and then appends the results to a list
# write results list to filename
If I pass all elements of control_list into my function as strings I can easily generate my header for the results file but I can't figure out how to take those strings and generate something like inst1.value1() so that Python will access the functions within my classes. I think that if I create the list like [inst1.value1(), inst2.value2()] I can get data from my classes but I can't figure out how to create my header file this way.
I'm open to other approaches if the approach I outlined above won't work.
You can easily do this work without use of other python predefined function with help of oops concept.
class MyClass(object):
def init(self, value1):
self.value1 = value1
inst = MyClass("example")
get the value of attribute
inst.value1
set the value of attribute
inst.value1 = "hello"
I think you're looking for the getattr function:
class MyClass(object):
def __init__(self, value1):
self.value1 = value1
instance = MyClass("example")
fieldname = "value1"
fieldvalue = getattr(inst1, fieldname)
# fieldvalue == "example"
With getattr and setattr you can write code that manipulates fields whose name you pass in to your function as parameters.
I recently had a similar issue and used namedtuple to solve it.
value1 = 'value of 1'
value2 = 'value of 2'
ControlList = namedtuple("ControlList", "inst1, inst2"))
controllist = ControlList(value1, value2)
>>> print controllist.inst1
... 'value of 1'
>>> print controllist.inst2
... 'value of 2'
value1 and value2 need not be strings, they can even be instanciated or uninstaciated classes.
The benefits of writing ControlList this way, is that you can always expand your control list, and it doesn't break functions that rely on ControlList being a certain length, or having certain values in certain places. You always have access to the items in ControlList via .method binding, and can alias ControlList.method internally to your functions if you want to avoid messing with code.