How should I call functions defined outside of the main function? - python

So I'm fairly new to python and I am working on an algorithm and I have let's say 2 functions
func1(x)
func2(x)
already defined outside the main function.
Now I want to call these functions inside the main functions one nested inside the other
Something like this
def funcmain(func1(func2(x)))
It obviously is not working I haven't been able to get it work anyway I want. Any tips on this?
Edit: What I meant to do is that I want to input a string, I want it to go through func2 first, then the return value from func2 to go through func1 and finally the return value of func1 to go through func main. I have tested each function separately and they are working as intended but I can't seem to get them interlinked together

I hope this code snippet will help to clarify things for you.
#!/usr/bin/python
def func1(x):
return x + 1
def func2(x):
return x + 2
def main(x):
print func1(func2(x))
if __name__ == '__main__':
main(0)
The output is 3.

Is this what you mean? Your question is not too clear. I assume x is also defined globally somewhere.
def funcmain():
return func1(func2(x))

take the following functions:
def func1(x):
return x+1
def func2(x):
return x*2
by itself you COULD do this: func1(func2(3)) which would return 3 times 2 plus 1. This works because by itself func1(func2(3)) actually returns a value, not a function.
BUT since you are trying to put it as the basic argument for the main function like this:
def main(func1(func2(x))): #dont do this, this is what you did, it is bad
return x*3
its not going to know what to do with that because there is no default for x...
you CAN DO THIS THOUGH:
def main(x=func1(func2(1)):
return x*3
this would do the appropriate math to 1 and then assign it as x (Because as we saw earlier, func1(func2(3))` would return THE RESULT OF FUNCTIONS not a function itself, then multiply it by 3. since you are defaulting x to equal a value ( which is func1(func2(1))
This is bad practice still, because you are defaulting to whatever func1(func2(1) comes out to.
what you probably want in the end is something simpler:
def main(x):
y = func1(func2(x))
return y*3
or maybe even simpler than that
def main(x):
return x*3
#and then just call it like this
main(func1(func2(1))

Related

Why is the function printing the first two lines before calling it?

Very new to python and I'm learning about defining and calling functions.
When def function4(x): and then define its output as a variable m, it prints the first two lines of the function before I even call it. Then when I call the function it only displays the return value. I was under the impression that anything indented under def function4(x): would not be executed unless function4(x) was specifically called?
Example:
def function4(x):
print(x)
print("still in this function")
return 3*x
m = function4(5)
print("BREAK")
print(m)
Output:
5
still in this function
BREAK
15
Process finished with exit code 0
Thanks for your time!
You're right, the function will not execute until you call it. You are calling it, though, right here:
m = function4(5)
So your print statements are executing in exactly the right place. You are setting m to the value returned by function4(5).
print does not call anything. It simply prints the string representation of whatever you give it to the console:
# a simple function to demonstrate
def f(x):
print("I am ", x)
return x
# I have not called f yet
print('Hello! ')
# I have printed the *function* f, but I still have not called it
# note the lack of parentheses
print('Here is a function: ', f)
print('We will call it now!')
# *Now* I am calling the function, as noted by the parentheses
x = f(1)
print('I have returned a value to x: ', x)
Which will do the following:
Hello!
Here is a function: <function f at 0x7fa958141840>
We will call it now!
I am 1
I have returned a value to x: 1
First of all I strongly recommend you that you use http://pythontutor.com/javascript.html#mode=edit if you want to know how your code is working, is very useful if you are new on Python.
Then, as for your code, you are calling the function when you declare the m variable, so that's the reason why the two print statements appear first.
The return value will only appear if you print the function, that's why the number 15 appears after all because you've printed it when you wrote print(m).
Hope this can help you, Goobye then and goodluck!.

How to check if the return value of a function is assigned to anything in Python

I have a function that has a return value. I'd like the function to behave differently when the return value of the function is assigned to something.
So something like this:
def func():
if return_value_assigned():
print("yes")
else:
print("no")
return 0
# this should print "no"
func()
# this should print "yes"
a = func()
I've tried to use this method:
frame_stack = inspect.getouterframes(inspect.currentframe())
code_context = frame_stack[2].code_context[0]
is_return_value_assigned = re.match(r"[\w+ ,]*=", code_context) is not None
However, apparently, code_context only stores the last line of the function call. So for example, this wouldn't work:
a = func(*args,
**kwargs)
Is there a better way of doing this? Is it possible to get the code context of the entire function call instead of just the last line?
The only option that makes any sense, with regards to every programming standard on caller vs. callee responsibilities I've ever seen, is something like this:
def foo(return_value=True):
if return_value:
print("yes")
else:
print("no")
return 0
Otherwise you're asking the called function to extact information from the caller, which seems like a really bad idea for many reasons.

pass return of a function into another

I have a question / problem and I don't know how to solve it. Suppose you have three functions, function 1, function 2 and function 3. In function 1 you do some operations and you give a specific return which will be used as input for the second function. In the second function you do some specific calculation and also finish with return, which you pass in a third function
My problem is that as soon as I pass the return of function 1 into function 2 all the calculation in function 1 is repeated (calculation is here in this case, several plots) The same goes for function two into three, now I get results from function 1 and function 2. I hope you do understand what I mean.
What I want is just the return value of func 1 for func 2 and return value of func 2 for three and not the entire function body.
Here is what my code looks like:
class test:
def __(self)__:
self.attribute1=pd.read_csv(...)
self.attribite2=pd.read_csv(...)
def func1(self):
plt.plot(a,b)
plt.plot(c,d)
return x
def func2(self):
self.data_2=self.func1()
plt.plot(e,f)
plt.plot(g,h)
return y
def func3(self):
self.data_3=self.func2()
plt.plot(i,j)
data_test=test()
print(data_test.func2())
My problem is that (let's focus on func2). If I use the input from func1 and execute my code for func2 I get also the two plots. I dont want to have that. I just want to see the plots(e,f) and plots(g,h) instead of plots(a,b), plots(c,d), plots(e,f) and plots(g,h)
Your class definition do not follow the OOP clean design, for which every method should performa the most atomic task possible.
Your methods func1, func2 and func3, they all do at least 2 tasks: plot something and return something else.
Consider changing your class so every method do one and only one thing, defining public APIS and private methods, for instance:
class test:
def __(self)__:
self.attribute1 = []
self.attribite2 = []
def _func1(self):
return x
def _func2(self):
self.data_2 = self._func1()
return y
def _func3(self):
self.data_3 = self._func2()
def func2(self):
self._func2()
plt.plot(e,f)
plt.plot(g,h)
def func3(self):
self._func3()
plt.plot(e,f)
plt.plot(g,h)
data_test=test()
data_test.func2()
This way func2 and func3 are public apis (aka: intended to be called from outside the class) that will "do the work" (setting stuff in self.data_2 and self.data_3) AND plot; while _func2 and _func3 are private methods (aka, methods that only the class itself is supposed to use) will only do the work.
Now, calling func2 will use methods _func1 and _func2, but only plot what's defined in func2.
You say that you "pass the return of function 1 into function 2", but you never do that.
You're not passing any results anywhere, and none of your functions take any input (except self) - you're calling the functions directly in each one.
In other words, every time you call function2, it calls function1, and every time you call function3, it calls function2, which in turn calls function1.
Code that matches your description would look like this:
class test:
def __(self)__:
self.attribute1=pd.read_csv(...)
self.attribite2=pd.read_csv(...)
def func1(self):
plt.plot(a,b)
plt.plot(c,d)
return x
def func2(self, a):
self.data_2 = a
plt.plot(e,f)
plt.plot(g,h)
return y
def func3(self, x):
self.data_3 = x
plt.plot(i,j)
return z
data_test = test()
print(data_test.func3(data_test.func2(data_test.func1())))

Method Overriding?

I saw this particular piece of code:
def g(x,y):
return x+y
def g(x,y):
return x*y
x,y=6,7
print (g(x,y))
The output is obviously(but not to me) is 42. Can somebody please explain this behavior? This is method overriding I suppose, but I'm still not getting the flow here.
When you define a function, and you redefine it, it will use the last one you defined, even the parameter is different:
def g(x,y):
return x+y
def g(x,y):
return x*y
x,y=6,7
print (g(x,y))
def hello():
return 'hello'
def hello():
return 'bye'
print hello()
def withone(word):
return word
def withone():
return 1==1
print withone('ok')
Output:
42
bye
TypeError: withone() takes no arguments (1 given)
And function name in Python is more like simple variable:
def hello():
return 'hello'
iamhello = hello # bind to the old one
def hello():
return 'bye'
print hello() # here is the new guy
print iamhello()
OutPut:
bye
hello
The devil is in the order of function definitions.
This is not technically method overriding as that requires class inheritance, instead it's a result of how python declares and references functions.
When declaring a function, python stores a reference to that function in a variable named after the function definition. (e.g. variable would be "foo" for "def foo():")
By declaring the function twice, the value of that variable gets overwritten by the second definition.
A Python script is parsed from top till bottom.
So anytime the same name of a variable or function or class occurs, it overwrites any definitions that where associated with this name before.
def g(x,z):
print('first')
def g():
print('second')
g = 3
print g
print g()
So look at this example which will result in the printout of '3' and then in an Exception: 'TypeError: 'int' object is not callable'
The name g is at first a function with two parameters, then it gets redefined to be a function with no parameters, then it gets redefined to be an int.
Which cannot be called obviously :)
Everything in python is treated as object, whether it be a function name or class name. So, when we define a function using 'def', the memory allocation is done for that method. Then python points the name that we assign to the function, to this allocated memory location. So if we define a method :-
def demo():
print 'hi'
the memory is allocated for the method, and the name 'demo' is pointed to its memory location as follows :-
Now as described by zoosuck in his second example, when you assign the function name to another variable :-
demo2 = demo # bind to the old one
then in that case, the assigned memory location to demo, is assigned to demo2 as well. So both demo and demo2 points to same location 12506.
print id(demo) # will print 12506
print id(demo2) # will print 12506
Now if we modify the above piece of code and in the next line, define a new method with same name demo:-
def demo():
print 'hi'
demo2 = demo # bind to the old one
demo() # Will print hi
def demo():
print "hello"
demo() # Will print hello
demo2() # Will print hi
then a completely new memory location 12534 is allocated for this new method, and now demo will point to this new location 12534 instead of pointing to the old one i.e. to 12506. But demo2 is still pointing to the location 12506.
I hope this will give you a clear idea of what is going on and how the method name is over-written.
Order matters, if names are same,last function you defined is processing. In your case it's;
def g(x,y):
return x*y
g is just a variable. The fact that the object it refers to is a function doesn't make it special in Python, so you can assign and reassign it as you want. In this case, the second assignment (which is what a function definition is) simply replaces the object stored there with a different one.
Functions and methods are normal objects like any others. So in
def g(x, y):
return x + y
def g(x, y):
return x * y
the second object g will override(replace) the first one, just like object a does below:
a = 1
a = 2
The number, type or order of parameters does not make any difference, because Python does not support function/method override and does not allow two functions/methods to have the same name.
If you are familiar with lambda function, also often called anonymous\inline functions, this might clear things up a bit
These two code blocks are essentially equal
def g(x,y):
return x+y
def g(x,y):
return x*y
g = lambda x,y: x+y
g = lambda x,y: x*y

Python Newbie: Returning Multiple Int/String Results in Python

I have a function that has several outputs, all of which "native", i.e. integers and strings. For example, let's say I have a function that analyzes a string, and finds both the number of words and the average length of a word.
In C/C++ I would use # to pass 2 parameters to the function. In Python I'm not sure what's the right solution, because integers and strings are not passed by reference but by value (at least this is what I understand from trial-and-error), so the following code won't work:
def analyze(string, number_of_words, average_length):
... do some analysis ...
number_of_words = ...
average_length = ...
If i do the above, the values outside the scope of the function don't change. What I currently do is use a dictionary like so:
def analyze(string, result):
... do some analysis ...
result['number_of_words'] = ...
result['average_length'] = ...
And I use the function like this:
s = "hello goodbye"
result = {}
analyze(s, result)
However, that does not feel right. What's the correct Pythonian way to achieve this? Please note I'm referring only to cases where the function returns 2-3 results, not tens of results. Also, I'm a complete newbie to Python, so I know I may be missing something trivial here...
Thanks
python has a return statement, which allows you to do the follwing:
def func(input):
# do calculation on input
return result
s = "hello goodbye"
res = func(s) # res now a result dictionary
but you don't need to have result at all, you can return a few values like so:
def func(input):
# do work
return length, something_else # one might be an integer another string, etc.
s = "hello goodbye"
length, something = func(s)
If you return the variables in your function like this:
def analyze(s, num_words, avg_length):
# do something
return s, num_words, avg_length
Then you can call it like this to update the parameters that were passed:
s, num_words, avg_length = analyze(s, num_words, avg_length)
But, for your example function, this would be better:
def analyze(s):
# do something
return num_words, avg_length
In python you don't modify parameters in the C/C++ way (passing them by reference or through a pointer and doing modifications in situ).There are some reasons such as that the string objects are inmutable in python. The right thing to do is to return the modified parameters in a tuple (as SilentGhost suggested) and rebind the variables to the new values.
If you need to use method arguments in both directions, you can encapsulate the arguments to the class and pass object to the method and let the method use its properties.

Categories

Resources