Execute a function randomly - python

Consider the following functions:
def a():
print "a"
def b():
print "b"
Is there a way to pick a function to run randomly? I tried using:
random.choice([a(),b()])
but it returns both functions, I just want it to return one function.

Only call the selected function, not both of them:
random.choice([a,b])()
Below is a demonstration:
>>> import random
>>> def a():
... print "a"
...
>>> def b():
... print "b"
...
>>> random.choice([a,b])()
a
>>> random.choice([a,b])()
b
>>>
Your old code called both functions when the list [a(),b()] was created, causing Python to print both a and b. Afterwards, it told random.choice to choose from the list [None, None]1, which does nothing. You can see this from the demonstration below:
>>> [a(),b()]
a
b
[None, None]
>>>
The new code however uses random.choice to randomly select a function object from the list [a,b]:
>>> random.choice([a,b])
<function b at 0x01AFD970>
>>> random.choice([a,b])
<function a at 0x01AFD930>
>>>
It then calls only that function.
1Functions return None by default. Since a and b lack return-statements, they each return None.

Is it what you want?
random.choice([a,b])()

Related

Python lambda function in a list gives unexpected result

So I'm trying to make a list where a lambda functions are the elements of the list. The lambda function calls
another function which I pass an argument to. The problem is that lambda function only 'saves' the last value for all other items in the list. See below
The question is what should I do to get the desired result?
Edit: The stated problem is simplified. I have to use lambda for the solution
This is the code I'm trying to understand the problem:
def f(B):
print(B)
A = [lambda: f(a) for a in ["foo", "faz", "baz"]]
for a in A:
a()
Desired result:
foo
faz
baz
Real result:
baz
baz
baz
if you need to create an array of function calls you can achieve what you are trying to do with the following:
def f(x):
def g():
print(x)
return g
A = [f(a) for a in ["foo", "faz", "baz"]]
for a in A:
a()
output
foo
faz
baz
While lambda accesses the context it's defined in, a for loop doesn#t create a new context each time it runs. That would be too inefficient.
Thus, by the time your code actually calls the lambda functions that context has ended and a contains the last value the loop assigned to it.
Correct code:
def f(B):
print(B)
A = ["foo", "faz", "baz"]
for a in A:
f(a)
If this answer is not sufficient, please clarify why do you need that lambda in the first place.
For loop in lambda saves last item of list so its better to write it way out lambda
like this:
def b():
A = ["foo","faz","baz"]
For a in A:
Print(a)
and output is:
foo
faz
baz

How do I show that function is mutable in Python?

My understanding of mutability and immutability in Python is, say we have a variable foo, if there exists a way to change how foo looks like (by using print) without changing its id, then foo is mutable. Otherwise, it's immutable.
For example, you can do this for a list,
foo = [1, 2, 3]
print(foo, id(foo))
foo[0] = 100
print(foo, id(foo))
but no way for int.
But what about function? First of all, is my definitions of mutability and immutability given above correct? If yes, can you find a way to mutate function without changing its id in order to prove it's mutable?
You can explicitly change the code of a function without affecting its id (here is code using python 2.7):
>>> def f():
... print "f"
...
>>> def g():
... print "g"
...
>>> id(f)
140305904690672
>>> f()
f
>>> f.func_code = g.func_code
>>> id(f)
140305904690672
>>> f()
g

How to make a function that will return items in a list one at a time?

I am trying to make my function return items in a list one by one each time the function is called. I have this code:
def abc():
ls = ['a', 'b', 'c']
for i in ls:
ls.append(i)
yield i
I can type something like this on the terminal and keep pressing next() to get the next item in the list.
>>>ab = abc()
>>>next(ab)
'a'
>>>next(ab)
'b'
>>>next(ab)
'c'
>>>next(ab)
'a'
>>>next(ab)
'b'
And it should go on forever every time next is called. Instead of repeatedly typing next(ab) in the terminal, I want to make my function do all that (return the next item in the list) every time the function abc() is called.
Basically you're looking for a closure function:
def func():
seq = ['a', 'b', 'c']
ind = [-1]
def inner():
ind[0] += 1
return seq[ind[0]%len(seq)]
return inner
>>> f = func() # One call is still required after that the
# returned inner function can maintain the state.
>>> f()
'a'
>>> f()
'b'
>>> f()
'c'
>>> f()
'a'
In Python 3 instead of defining ind as a list we can use nonlocal keyword.
Or using itertools.cycle:
from itertools import cycle
def func(seq):
return cycle(seq).next
...
>>> f = func('abc')
>>> f()
'a'
>>> f()
'b'
>>> f()
'c'
>>> f()
'a'
>>> f()
'b'
You need a queue.
Every time a function call happens
x=[1,2,3]
k= x.pop(0)
x.append(k)
return k
This will get you the desired behavior.
EDIT:
ls = ['a', 'b', 'c']
def abc():
k= ls.pop(0)
ls.append(k)
return k
print abc()
print abc()
print abc()
print abc()
print abc()
The function you have uses increasing amounts of memory because it appends to the list for each iteration. An improvement is to maintain an index:
def abc():
ls = ['a', 'b', 'c']
i = 0;
while True:
yield ls[i]
i = (i+1) % len(ls)
What you have is exactly what you need. It is a generator. Normally you would not call next() directly. Normally you would use a loop to process the values produced by your generator:
for thing in abc():
print(thing)
Since your generator never throws a StopIteration exception, the for loop will never end.
This calls for creating a higher order function that will use closure to create a secondary function to do what you want.
def create_wrapper(func):
iter = func()
def wrapper():
return next(iter)
return wrapper
ab = create_wrapper(abc)
ab()
>>> 'a'
ab()
>>> 'b'
And so on.
Here is a quick intro to higher order functions and closures in the context of the above code -
In the above code, func is actually a function reference, note how we call create_wrapper(abc) without the parens after abc, so it is not actually executing abc(). Then we create an iter object and create a child function called wrapper. We refer to the iter object in the child function even though it is defined in the parent function. This usage is called closure. When we return the function reference to wrapper, create_wrapper goes out of scope and so should any variables used inside it - including iter. But because it is being referenced in the child function, which lives on beyond its parent, iter is preserved.
BTW - the way you create an infinite iterator by appending to the list is pretty clever :-) but it obviously runs the danger of a memory overflow. There are other ways to create infinite iterators. Check out https://docs.python.org/3/library/itertools.html.

python modify a dictionary inside a method

Is it possible to modify values for a dictionary inside a function without passing the dictionary as a parameter.
I would like not to return a dictionary, but only to modify its values.
That's possible, but not necessarily advisable, i can't imagine why you wouldn't like to pass or return the dictionary, if you merely don't want to return the dictionary, but could pass it, you can modify it to reflect in the original dictionary without having to return it, for example:
dict = {'1':'one','2':'two'}
def foo(d):
d['1'] = 'ONE'
print dict['1'] # prints 'one' original value
foo(dict)
print dict['1'] # prints 'ONE' ie, modification reflects in original value
# so no need to return it
However, if you absolutely cannot pass it for whatever reason, you can use a global dictionary as follows:
global dict # declare dictionary as global
dict = {'1':'one','2':'two'} # give initial value to dict
def foo():
global dict # bind dict to the one in global scope
dict['1'] = 'ONE'
print dict['1'] # prints 'one'
foo(dict)
print dict['1'] # prints 'ONE'
I'd recommend the first method demonstrated in the first code block, but feel free to use the second if absolutely necessary.
Enjoy :)
Yes you can, dictionary is an mutable object so they can be modified within functions, but it must be defined before you actually call the function.
To change the value of global variable pointing to an immutable object you must use the global statement.
>>> def func():
... dic['a']+=1
...
>>> dic = {'a':1} #dict defined before function call
>>> func()
>>> dic
{'a': 2}
For immutable objects:
>>> foo = 1
>>> def func():
... global foo
... foo += 3 #now the global variable foo actually points to a new value 4
...
>>> func()
>>> foo
4

python - how can I dynamically create a function with a name based on a string read in from a file?

Let's say I have a file containing the string "unpredictable_words". I would like to read in this string and then define a function as follows:
def test_unpredictable_words(self):
do_important_stuff()
I would then like to inject this function into a class definition so that this function can be called on any instances of this class.
How can I accomplish this?
I looked a bit at this answer - https://stackoverflow.com/a/8160676/1701170 - but I don't think it does what I want, exactly, or at least I can't understand what is going on.
Python 2.7.3 (default, Sep 26 2012, 21:51:14)
>>> def injected(self):
... print 'injected'
...
>>> class A(object):
... pass
...
>>> A.injected = injected
>>> a = A()
>>> a.injected()
injected
>>> def func2(self):
... print 'func2'
...
>>> setattr(A, 'injected2', func2)
>>> a.injected2()
func2
>>>
You don't need to define a function under one true name. Functions are first-class entitiens, you can pass them around and assign to variables. On top level, you use globals(), withing another function, locals() to bind a name:
>>> def foo(x):
... return x + 1
...
>>> name = 'unpredictable_words'
>>>
>>> globals()['test_' + name] = foo
>>>
>>> test_unpredictable_words(1)
2
>>>
>>> def some_function():
... locals()['test_' + name] = foo
... return test_unpredictable_words(1)
...
>>> some_function()
2
>>>
Sometimes you still want that the function knows its name, in order to appear nicely in a stacktrace. Now test_unpredictable_words appear as foo in error messages. This is not easy to fix, since that name is stored in foo.func_code.co_name and can't be changed.

Categories