I have managed to make my first class, containing two methods where on holds data and the other does a set of derivations on the input data, given fairly simple python code utilizing Pandas functionality. I call the class, and its adherent methods, with 4 parameters.
What I would like is for the output from the class, a Pandas data frame, to be named according to one of the input parameters - being an string object. This since the derivation is made on a single data column in the input data and it would be practical to name the output data frame to the same as the input parameter (i.e., data frame variable) for later use.
An crude example of the structure of the class (and of the code) is give below:
class tool_swoe_iv:
"docstring"
def __init__(self,data_in):
self.data_in = data_in
def swoe_iv(self, param1, param2):
"code that executes calculations"
# output table which I would like to be re-named to param1 so it can be called later on.
woe_holder
When I call the class I would like the "woe_holder" data frame to have the same name as param1. Does my questions make sense? I come from a SAS background where the re-naming of the output data could easily have been done by a macro variable holding the name suffix.
Please note that im very new to the more formal parts of python coding involving classes and their development, honestly also to more standard python coding too.
Best,
I think that you're misunderstanding how python class methods work. Here's what I think you believe your code will do:
#Create an instance of tool_swoe_iv
my_tool = tool_swoe_iv(5)
#Execute calculations
my_tool.swoe_iv(param1, param2)
#Now there exists a new dataframe called param1
What you're missing here is that python functions return values. For example:
def addition(x, y):
return x + y
Now, if you want to have a variable that holds the result of an addition, you should assign it yourself, e.g.:
my_var = addition(1, 2)
Instead of doing it the way you're suggesting, with some function that looks like:
addition("myvar", 1, 2)
So using your original example, your code should look something like
class tool_swoe_iv:
"docstring"
def __init__(self,data_in):
self.data_in = data_in
def swoe_iv(self, param2):
"code that executes calculations"
# output table which I would like to be re-named to param1 so it can be called later on.
return dataframe
my_tool = tool_swoe_iv(5)
param1 = my_tool.swoe_iv(param2)
You can directly modify dictionary of variables by calling locals() and globals() function. For example, a = 1 is equal to locals()['a'] = 1.
So, you can use those functions to accomplish your idea:
globals()[param1] = woe_holder
However, this is not suggested, because you will assign it to a global name instead of local name. (If you use locals(), it will disappear when your function returns, because it will be a local variable of your function.) You'd better just return woe_holder to the caller and let the caller decide what name to assign to. For example, call my_tool.swoe_iv like that:
param1 = my_tool.swoe_iv(param2)
(In this case param1 can't be a object. Don't enclose it with quotation marks.)
This is more readable.
Related
New to python programming here. I need some help understand why this does not work:
import x.y # x is a package with __init__.py
def func1(x.y.z): # I get a syntax error here
It works when I do this:
import x.y
a = x.y.z
def func1(a):
I've search the web and can't find anything that would answer this somewhat directly.
Thanks.
With def you define new functions which accept some possibly unknown(!) arguments.
So, def sin(x): means "define a function called sin that accepts one argument". Note that this code means that x can be absolutely anything, the function definition doesn't (and cannot) apply any restrictions on its type, value, size, etc.
When you do
a = "hello"
def test(a):
pass
The a in the function definition is merely an argument that doesn't have any relation to any other a you use in your code! You could've called it x, pi, z or whatever as the name doesn't really matter (code readability aside).
When you try to write
def test(x.y.z):
pass
You get a syntax error as there exist restrictions on the variables' and arguments' names that don't allow you to call a variable any name you want. Why? Simply because otherwise you'll get a lot of uncertainty. For example, how to parse this:
# a poorly formatted number literal or a variable definition??
1234hello = "test"
# attempt to access a member of a class (or module) or a variable definition??
x.y.z = 5
# is "yay a variable's name or a poorly formatted string literal??
x = "yay - 5
# the same question as above
f' = df/dx
A function argument is a variable, so the very same restrictions are imposed on it as well.
BTW, take a look at the SO code highlighter going nuts trying to highlight the code above.
I am making a program to do some calculations for my Microeconomics class. Since there are some ways of working depending on the problem I am given, I have created a class. The class parses an Utility function and a 'mode' from the command line and calls a function or another depending on the mode.
Since every function uses the same variables I initiate them in __init__():
self.x = x = Symbol('x') # Variables are initiated
self.y = y = Symbol('y')
self.Px, self.Py, self.m = Px, Py, m = Symbol('Px'), Symbol('Py'), Symbol('m')
I need a local definition to successfully process the function. Once the function is initiated through sympify() I save it as an instance variable:
self.function = sympify(args.U)
Now I need to pass the variables x,yPx,Py,m to the different functions. This is where I have the problem. As I want a local definition I could simply x=self.x with all the variables. I would need to repeat this in every piece of code which isn't really sustainable. Another option is to pass all the variables as arguments.
But since I'm using a dictionary to choose which function to call depending on the mode this would mean I have to pass the same arguments for every function, whether I use them or not.
So I have decided to create a dictionary such as:
variables = { #A dictionary of variables is initiated
'x':self.x,
'y':self.y,
'Px':self.Px,
'Py':self.Py,
'm':self.m
}
This dictionary is initiated after I declare the variables as sympy Symbols. What I would like is to pass this dictionary in an unpacked form to every function. This way i would only need **kwargs as an argument and I could use the variables I want.
What I want is something like this:
a = 3
arggs = {'a' = a}
def f(**kwargs):return a+1
f(**args)
This returns 4. However when I pass my dictionary as an argument I get a non-defined 'x' or 'y' variables error. It can't be an scope issue because all the variables have been initiated for all the instance.
Here is my code calling the function:
self.approaches[self.identification][0](**self.variables)
def default(self, **kwargs):
solutions = dict()
self.MRS = S(self.function.diff(x) / self.function.diff(y)) # This line provokes the exception
What's my error?
PS: Some information may be unclear. English is not my main language. Apologies in advance.
Unfortunately, Python doesn't quite work like that. When you use **kwargs, the only variable this assigns is the variable kwargs, which is a dictionary of the keyword arguments. In general, there's no easy way to inject names into a function's local namespace, because of the way locals namespaces work. There are ways to do it, but they are fairly hacky.
The easiest way to make the variables available without having to define them each time is to define them at the module level. Generally speaking, this is somewhat bad practice (it really does belong on the class), but since SymPy Symbols are immutable and defined entirely by their name (and assumptions if you set any), it's just fine to set
Px, Py, m = symbols("Px Py m")
at the module level (i.e., above your class definition), because even if some other function defines its own Symbol("Px"), SymPy will consider it equal to the Px you defined from before.
In general, you can play somewhat fast and loose with immutable objects in this way (and all SymPy objects are immutable) because it doesn't really matter if an immutable object gets replaced with a second, equal object. It would matter, if, say, you had a list (a mutable container) because it would make a big difference if it were defined on the module level vs. the class level vs. the instance level.
Let's say I have a code like this:
def read_from_file(filename):
list = []
for i in filename:
value = i[0]
list.append(value)
return list
def other_function(other_filename):
"""
That's where my question comes in. How can I get the list
from the other function if I do not know the value "filename" will get?
I would like to use the "list" in this function
"""
read_from_file("apples.txt")
other_function("pears.txt")
I'm aware that this code might not work or might not be perfect. But the only thing I need is the answer to my question in the code.
You have two general options. You can make your list a global variable that all functions can access (usually this is not the right way), or you can pass it to other_function (the right way). So
def other_function(other_filename, anylist):
pass # your code here
somelist = read_from_file("apples.txt")
other_function("pears.txt.", somelist)
You need to "catch" the value return from the first function, and then pass that to the second function.
file_name = read_from_file('apples.txt')
other_function(file_name)
You need to store the returned value in a variable before you can pass it onto another function.
a = read_from_file("apples.txt")
There are at least three reasonable ways to achieve this and two which a beginner will probably never need:
Store the returned value of read_from_file and give it as a parameter to other_function (so adjust the signature to other_function(other_filename, whatever_list))
Make whatever_list a global variable.
Use an object and store whatever_list as a property of that object
(Use nested functions)
(Search for the value via garbage collector gc ;-)
)
Nested functions
def foo():
bla = "OK..."
def bar():
print(bla)
bar()
foo()
Global variables
What are the rules for local and global variables in Python? (official docs)
Global and Local Variables
Very short example
Misc
You should not use list as a variable name as you're overriding a built-in function.
You should use a descriptive name for your variables. What is the content of the list?
Using global variables can sometimes be avoided in a good way by creating objects. While I'm not always a fan of OOP, it sometimes is just what you need. Just have a look of one of the plenty tutorials (e.g. here), get familiar with it, figure out if it fits for your task. (And don't use it all the time just because you can. Python is not Java.)
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.
I have a Python script which creates a dictionary of its own functions and I'd like it to execute them by reading in a function name and arguments using YARP (knowledge of YARP is irrelevant to this question though).
I create a list of strings called "inc" which is populated by values coming into the program. The first item is a function name, and any other strings in the list are arguments. I create a dictionary called "methods" where the key is the function name and the value is a reference to the function object (using the inspect module). I store the return value of the function in a variable "result".
The snippet below shows a simplified version of what I'm using so far, which works fine, but can't handle functions with more than one argument. To circumvent this I use a list if a function needs more parameters:
if len(inc) == 1:
result = methods[inc[0]]() # call method with 0 arguments
elif len(inc) == 2:
result = methods[inc[0]](inc[1]) # call method passing a string
else:
args = []
result = methods(inc[0])(inc[1:]) # call method passing a list
Ideally, I'd like to change this so that my functions can have any number of arguments, but I can't figure out how I can do this. I'm new to Python and I have looked at the documentation and various websites - I just can't find a solution. I've tried things like creating a tuple of the arguments, but that doesn't work either as it ends up passing the whole tuple in as one parameter.
Is there a better solution to this problem, like creating some kind of object which represents a set of parameters and passing that into the function? Any suggestions would be greatly appreciated!
You should check out https://stackoverflow.com/a/3394898/1395668.
The magic you are looking for is the *. Apply this to your list and it unpacks the items into the argument fields of your function:
a = [ 1, 2, 3]
def myfunc(a, b, c):
return a + b + c
print myfunc(*a)
Check out ** for the same approach for dict
It's a bit strange to have this kind of mixed structure:
inc = [func_name, arg1, arg2, ...]
Wouldn't it be much more natural to have two separate bits of information?
func_name = ...
args = [arg1, arg2, ...]
The you could do
methods[func_name](*args)
(Usually, I wouldn't bind the functions name to a variable, but preferably the function itself.)