i want use loop correctly inside function
This is my code :
def test():
for i in range(1,10):
return i
def check():
print(test())
check()
output is 1
i want to full iteration
output : 1 ,2,4....10
When you return inside a function, it immediately terminates the function and returns the specified value. This means that it goes into the for loop and returns 1, then stops running. One way to get around this is to use the yield keyword instead of return.
def test():
for i in range(1, 10):
yield i
This will make test() a generator, which can then be printed in check by unpacking its values.
def check():
print(*test())
Alternative ways of doing this would be to return a list in test() or to simply print the values within test() itself.
In Python (as with almost all programming languages), functions can only return once (ish). As soon as Python encounters return, it'll exit the function.
Python does have a feature called "generators", though: with the yield keyword, you can (sort of) return more than once:
def test():
for i in range(1,10):
yield i
To expand those values to the print function's arguments, use * like so:
def check():
print(*test())
>>> check()
1 2 3 4 5 6 7 8 9
>>> sum(test())
45
wim points out that you can sometimes return more than once from a function – but later return statements will "replace" the return value from earlier ones.
>>> def f():
... try:
... return 1
... finally:
... return 2
...
>>> f()
2
Unfortunately, CPython's optimising this too much for me to make sense of the dis bytecode decompilation; I have no idea how this works under the hood.
If you want to return all the values in the range you can do something like this:
def test():
return [i for i in range(1,10)]
def check():
print(test())
check()
Related
I want to achieve this
for i in range(1,10):
print(i)
but using different functions, by putting values of for-loop to variable named valuee and then as an argument to clamp function then printing it. Why am I getting just 1? and not from 1->9?
def clamp(valuee):
print(valuee)
def value():
for i in range(1,10):
return i
valuee=value()
clamp(valuee)
If you use return you will end the function. You are looking for a generator; just change the return for yield.
def clamp(valuee):
print(valuee)
def value():
for i in range(1,10):
yield i
You can use your generator in 2 ways: inside a loop
for valuee in value():
clamp(valuee)
Or as you originally wanted, but you have to add the keyword next:
def clamp(valuee):
print(valuee)
def value():
for i in range(1,10):
yield i
valuee = value()
clamp(next(valuee))
clamp(next(valuee))
clamp(next(valuee))
...
It is not printing all the values because in value() method you are using return and when i=1 in loop, value() returns 1 and exits from the function and loop too.
you can use ...
def clamp(valuee):
print(valuee)
def value():
for i in range(1,10):
clamp(i)
value()
A python wrapper specifically for for-loops and its actions
I write a lot FOR loops that are, well, pretty generic.
For eg:
for x in y:
do something
... and error-prone. eg forgetting the ":", or indentation probs.
Could we put the FOR loop in a def, and call it, supplying it with the something?
An interesting exercise if nothing else.
A basic wrapper...
def wrapper(func,*args):
def wrapped():
return func(*args)
return wrapped
wrapper(print,"bob")
wrapper()
...which works. ie prints bob out
but I don't know how to make the below work - returning a FOR function made lots of syntax errors.
eg something like:
def for_1(y, do_something):
def wrapped():
return for x in y:
do_something
return wrapped
for_1(range(3),print("bob\n"))
for_1()
...and didn't see bob on the screen 3 times.
Could someone point me in the right direction, please? A wrapper is not doing the returned function.
Perhaps use a class for the wrapper? Then have my own methods(??)
...or maybe point me to someone's page who has done this before. I have explored wrappers and decorators but not seen something for passing parameters to a FOR loop function
You can simply restructure your code to not return too early and not call to early.
For this split up the function and parameters as two parameters to your for_1 wrapper.
If you want return value, gather them in your for loop and return them as a list.
def for_1(y, do_something, with_param):
for x in y:
do_something(with_param)
for_1(range(3), print, "bob")
Why make it complicated?
def for_1(y, to_print):
for x in range(y):
print(to_print)
for_1(3, "bob")
OUTPUT:
bob
bob
bob
EDIT:
def square(x):
print(x*x)
def for_1(y, command, param):
for x in range(y):
command(param)
for_1(1, square, 3)
OUTPUT:
9
the print is evaluated immediately and its return value passed in. what you want here is to pass in a callable, and append () to the do_something inside the loop. than you can use lambda for the passed in function.
def for_1(y, do_something):
def wrapped():
return for x in y:
do_something() # so we call whatever is passed in to be executed at this point
return wrapped
f = for_1(range(3),lambda: print("bob\n"))
f()
# or equivalent:
def print_bob():
print("bob\n")
for_1(range(3),print_bob)
This is an overly simplified version of the problem that I'm working on. It's crude and basic but I just started out with python and wanna make sure that I have my basics straightened out.
I can't seem to get the desired output with this. For ex: When the list generated by a() contains '2', when I call out b() it does not give me the required value of y, which in this case should be 2.
from random import choice, sample
def a():
a = sample(range(0,5),2)
a.append(1)
return a
def b():
if 3 in a():
y = 1
elif 2 in a():
y = 2
else:
pass
return y
print a()
print b()
There are a few problems with your program, most notably, you are calling a within b, which I don't think you want to do. Within b, you are regenerating a list of new random values and then checking the contents of this list.
Also, you should not use pass in your else statement because you could imagine the possibility where y is never defined, and therefore you will fail to return something. I would suggest the following:
from random import choice, sample
def a():
a = sample(range(0,5),2)
a.append(1)
return a
def b(a):
if 3 in a:
return 1
elif 2 in a:
return 2
else:
return
a_output = a()
print a_output
print b(a_output)
However, this is an odd way to check the contents of a list. Without knowing the purpose of your program, it is difficult to make a recommendation for an alternative way to write a more pythonic function.
I have a function
def f():
while True:
blah
I want to alter f in such a way that the caller could control the number of times the while loop in f runs, without altering much of the code in f (specially not adding a counter in f). Something like
def f(num_executions = True):
while num_executions:
blah()
f() will run an infinite loop
but f(an_expression_that_evaluates_to_true_n_times) will run the while loop n times.
What could such an expression be?
UPDATE:
I know, there are plenty of way to control how many times a loop will run, but the real question here is -
Can an expression in python evaluate to True for configurable number of times?
Some ideas I am toying with
-making an expression out of list = list[:-1]
-modifying default parameters of a function within a function
No need for a while-loop. Use a for-loop:
>>> def f(n):
... for _ in range(n):
... dostuff()
_ is used as a variable name in a for loop normally to be a placeholder. This loop loops through n amount of times. So f(5) would loop five times.
While I agree with the others that this is a bad idea, it is entirely (and easily) possible:
class BoolChange:
def __init__(self):
self.count = 0
def __bool__(self):
self.count += 1
return self.count <= 5
x = BoolChange()
while x:
print("Running")
This outputs Running five times, then exits.
The main reason this is a bad idea is that it means checking the state of the object modifies it, which is weird behaviour people won't expect. I can't imagine a good use case for this.
You can't do exactly what you describe. What is passed in python is not an expression, but a value. An object. An Immutable object in general evaluate to either True or to False. It will not change during the loop. Mutable object can change its truth value, but you can't make arbitrary object change during a general loop (which does not touch it in any way). In general, as have been said here, you really need to use for statement, or pass in a callable object (say, a function):
def f(is_true = lambda x : True):
while is_true():
blah()
Note that the reason that the callable solution is acceptable, while the "hiding in boolean" #Lattyware demonstrated is not, is that the additional coputation here is explicit - the () tells the reader that almost anything can happen here, depending on the object passed, and you don't need to know that the __bool__ method in this object is silently called and is expected to have side effect.
def f(c=-1):
while c:
print 'blah'
if c > 0: c -= 1
How about using a generator as a coroutine?
def blah():
print 'hi'
def f():
while True:
blah()
yield
x = f()
next(x) # "hi"
The generator here isn't be used for what it yields, but you get to control how many times it blahs externally, because it yields control ever time it blahs.
for i in range(3):
next(x) # blah blah blah
This will also work -
def foo(n=[1,2,3]):
foo.func_defaults = tuple([foo.func_defaults[0][:-1]],)
return n
while foo():
blah()
I was wondering if it is possible in python to do the following:
def func1(a,b):
return func2(c,d)
What I mean is that suppose I do something with a,b which leads to some coefficients that can define a new function, I want to create this function if the operations with a,b is indeed possible and be able to access this outside of func1.
An example would be a simple fourier series, F(x), of a given function f:
def fourier_series(f,N):
...... math here......
return F(x)
What I mean by this is I want to creat and store this new function for later use, maybe I want to derivate it, or integrate or plot or whatever I want to do, I do not want to send the point(s) x for evaluation in fourier_series (or func1(..)), I simply say that fourier_series creates a new function that takes a variable x, this function can be called later outside like y = F(3)... if I made myself clear enough?
You should be able to do this by defining a new function inline:
def fourier_series(f, N):
def F(x):
...
return F
You are not limited to the arguments you pass in to fourier_series:
def f(a):
def F(b):
return b + 5
return F
>>> fun = f(10)
>>> fun(3)
8
You could use a lambda (although I like the other solutions a bit more, I think :) ):
>>> def func2(c, d):
... return c, d
...
>>> def func1(a, b):
... c = a + 1
... d = b + 2
... return lambda: func2(c,d)
...
>>> result = func1(1, 2)
>>> print result
<function <lambda> at 0x7f3b80a3d848>
>>> print result()
(2, 4)
>>>
While I cannot give you an answer specific to what you plan to do. (Looks like math out of my league.)
I can tell you that Python does support first-class functions.
Python may return functions from functions, store functions in collections such as lists and generally treat them as you would any variable.
Cool things such as defining functions in other functions and returning functions are all possible.
>>> def func():
... def func2(x,y):
... return x*y
... return func2
>>> x = func()
>>> x(1,2)
2
Functions can be assigned to variables and stored in lists, they can be used as arguments for other functions and are as flexible as any other object.
If you define a function inside your outer function, you can use the parameters passed to the outer function in the definition of the inner function and return that inner function as the result of the outer function.
def outer_function(*args, **kwargs):
def some_function_based_on_args_and_kwargs(new_func_param, new_func_other_param):
# do stuff here
pass
return some_function_based_on_args_and_kwargs
I think what you want to do is:
def fourier_series(f,N):
#...... math here......
def F(x):
#... more math here ...
import math #blahblah, pseudo code
return math.pi #whatever you want to return from F
if f+N == 2: #pseudo, replace with condition where f,N turn out to be useful
return F
else:
return None
Outside, you can call this like:
F = fourier_series(a,b)
if F:
ans = F(x)
else:
print 'Fourier is not possible :('
The important thing from Python's point of view are:
Yes, you can write a function inside a function
Yes, you can return a function from a function. Just make sure to return it using return F (which returns the function object) as compared to return F(x) which calls the function and returns the value
I was scraping through some documentation and found this.
This is a Snippet Like your code:
def constant(a,b):
def pair(f):
return f(a,b)
return pair
a = constant(1,2) #If You Print variable-> a then it will display "<function constant.
#<locals>.pair at 0x02EC94B0>"
pair(lambda a, b: a) #This will return variable a.
Now, constant() function takes in both a and b and return a function called "Anonymous Function" which itself takes in f, and calls f with a and b.
This is called "closures". Closures is basically an Instance of a Function.
You can define functions inside functions and return these (I think these are technically closures):
def make_f(a, b):
def x(a, b):
return a+b
return x(a, b)