I assume do_this and do_that are actually dependent on some argument of foo, since otherwise you could just move them out of foo and call them directly.
I suggest reworking the whole thing as a class. Something like this:
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
def do_this(self):
pass
def do_that(self):
pass
def __call__(self):
self.do_this()
self.do_that()
foo = Foo(x, y)
foo()
foo.do_this()
Answer from Lauritz V. Thaulow on Stack OverflowI assume do_this and do_that are actually dependent on some argument of foo, since otherwise you could just move them out of foo and call them directly.
I suggest reworking the whole thing as a class. Something like this:
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
def do_this(self):
pass
def do_that(self):
pass
def __call__(self):
self.do_this()
self.do_that()
foo = Foo(x, y)
foo()
foo.do_this()
These previous answers, telling you that you can not do this, are of course wrong. This is python, you can do almost anything you want using some magic code magic.
We can take the first constant out of foo's function code, this will be the do_this function. We can then use this code to create a new function with it.
see https://docs.python.org/2/library/new.html for more info on new and https://docs.python.org/2/library/inspect.html for more info on how to get to internal code.
Warning: it's not because you CAN do this that you SHOULD do this, rethinking the way you have your functions structured is the way to go, but if you want a quick and dirty hack that will probably break in the future, here you go:
import new
myfoo = new.function(foo.func_code.co_consts[1],{})
myfoo(x,y) # hooray we have a new function that does what I want
UPDATE: in python3 you can use the types module with foo.__code__:
import types
myfoo = types.FunctionType(foo.__code__.co_consts[1], {})
myfoo() # behaves like it is do_this()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: do_this() missing 2 required positional arguments: 'x' and 'y'
This is the code I am trying to run:
x = 1
def f1():
x = 2
def f2():
global x
x = 3
print(x)
f1()
print(x)
f2()
print(x)Output:
1
1
Traceback (most recent call last):
f2()
NameError: name 'f2' is not defined
What I meant to do was call the f2() function but then it showed an error.
My question is how do I call the f2() function outside the nested block?
Python - Proper way to call nested functions? - Stack Overflow
Call a nested function in Python - Stack Overflow
How to call a function that is nested in python - Stack Overflow
How to call nested function independently in Python script - Stack Overflow
If you want, you can return several functions that way:
class Box(object):
def __init__(self,**kw): vars(self).update(kw)
def first(x):
def second():
print(x)
def third(y): return x+y
return Box(second=second,third=third)
first(10).second() # prints 10
x=first(15)
x.second() # prints 15
print(x.third(10)) # prints 25
Any resemblance to reputation scores for answers is coincidental.
Why not use a class?
class First:
def __init__(self, x):
self.x = x
def second(self):
print(x)
First(3).second()
The fact that all Python functions are closures is a great feature, but it's fairly advanced. Classes are the usual place to store state.
You would have to return the function object; function2 is just another local variable inside function1 otherwise:
def function1():
#code here
def function2():
return foo
return function2
def function3():
x = function1()() # calls function2, returned by function1()
Calling function1() returns the function2 object, which is then called immediately.
Demo:
>>> def foo(bar):
... def spam():
... return bar + 42
... return spam
...
>>> foo(0)
<function spam at 0x10f371c08>
>>> foo(0)()
42
>>> def ham(eggs):
... result = foo(eggs + 3)()
... return result
...
>>> ham(38)
83
Note how calling foo() returns a function object.
To make that happen, you have to return function2 from function1 and then call function2 from function3 like this
def function1():
#code here
def function2():
return #variable
return function2
def function3():
x = function1()
print x()
Or, instead of storing function2 in x, you can simply do
def function3():
print function1()()
func1 does return nothing (implicitly None), that is why you get the exception, if you want to call func3 from main block, just return func2, call func2 to get func3 and then call it.
# File: nesteFunc.py
def func1():
x1 = 1
def func2():
x2 = 2
def func3():
x3 = 3
print(x1, x2, x3)
return func3
return func2
if __name__ == "__main__":
f2 = func1()
f3 = f2()
f3()
About your second question, yes, func3 will hace access to variables x1 and x2 because they exist in the parent scope.
You don't need to return func2 or func3 in func1(), if it's just to print (x1, x2, x3). You could do:
# File: nesteFunc.py
def func1():
x1 = 1
def func2():
x2 = 2
def func3():
x3 = 3
print(x1, x2, x3)
func3()
func2()
if __name__ == "__main__":
func1()
When you do this, function b is defined locally within a. This means that it cannot be accessed by default outside of a. There are two main ways to solve this, but both involve modifying a:
The
globalkeyword (not recommended)def a(): global b def b(): print("hi")Here the
globalkeyword setsbup as a global variable, so that you can then access it by calling it normally from withinc. This is generally frowned upon.Returning the function from
aand passing it tocdef a(): def b(): print("hi") return b def c(b): #your codeThen, when you call
c, you should passbto it, whichawill have returned. You can either do so thus:b = a() c(b)Or you can simply call
aevery time you callc, thus:c(a())If you choose to do this, you can then define
cthus:def c(): b = a() #your code herewhich would allow you to simply call
cnormally, thus:`c()`
This is not possible due to the way that Python scope works. b() is local to a(), and so does not exist within c().
EDIT: commenter is correct, the suggestion I initially gave doesn't work -- so this definitely just isn't possible.
To answer your first question: to call all of the functions you need to put the names of your functions into the main() function. But, you had several other errors so I have decided to walk you through the program, step-by-step.
First, we set the prices:
secA = 20
secB = 15
secC = 10
Here is the first function, getTickets()
def getTickets():
global A
A = int(input("Please enter the number of tickets sold in section A: "))
global B
B =int(input("Please enter the number of tickets sold in section B: "))
global C
C =int(input("Please enter the number of tickets sold in section C: "))
Notice the word global before I use the variable. This tells the computer that this variable can be used everywhere. Next, notice the double parentheses - since both int() and input() are functions, so we need to show that by doing that.
I fixed your code for the ticketsValid() function. Usually, it isn't a good idea to nest functions, so this is at the same indentation level as the above code.
def ticketsValid(A,B,C):
while A > 300 or A < 0:
print("ERROR: Section A has a limit of 300 seats\n")
A = int(input("Please enter the number of tickets sold in section A: "))
while B > 500 or B < 0:
print("ERROR: Section B has a limit of 500 seats")
B =int(input("Please enter the number of tickets sold in section B: "))
while C > 200 or C < 0:
print("ERROR: Section C has a limit of 200 seats")
C =int(input("Please enter the number of tickets sold in section C: "))
This gets the variables from above, and checks to see if they are valid. Notice that I added a check for negative numbers - you can't sell negative tickets.
Then we come to calcIncome(A,B,C):
def calcIncome(A, B, C):
total = A * secA + B * secB + C * secC
print ("The income generated is $%d" % (total))
First, we multiply the sections by the set prices to calculate the total. Then, we print it.
Lastly, we need to call the functions. I used your idea for a main() function, which uses the other functions. It looks like this.
def main():
getTickets()
ticketsValid(A,B,C)
calcIncome(A, B, C)
It simply calls the other functions, in the correct order, when run.
Lastly, we call the main() function by typing:
main()
I hope that this answered your question. If not, feel free to comment. If so, please check the green check mark next to my answer.
If you only want to know how to use a nested function:
def f():
def g(): #this defines a function but does not call it
print "run g"
g() # this calls g.
Typically, nested functions should not be available outside its parent function. Since the point of using a nested function is that the function only helps its parent function to do things. If you want it outside, consider define it as a new function.
In your case, you need to consider how to break up your code into parts.
If I were you, I would use getTickets() to get tickets.
The ticketsValid is fine, though I would let it return a boolean.
calcIncome would return the total income.
So the general design is like:
def main():
(A, B, C) = getTickets()
if(ticketsValid(A, B, C)):
income = calcIncome(A, B, C)
print("The income generated from all sections is: ", income)
def getTickets():......
def ticketsValid(A, B, C):......
def calcIncome(A, B, C):......
I think this would be a better design.