I'm trying to make a map that takes a function that calls other functions, and a list of functions - so here is what I've put in:
def function1():
return 3
def function2():
return 4
def List_Of_Functions(My_Function):
return My_Function
print(list(map(List_Of_Functions, [function1, function2])))
but this is what I get in the result:
[<function function1 at 0x7f5e6797a620>, <function function2 at 0x7f5e6797a730>]
I'm new to Python so any explanation would be much appreciated.
Nowhere in the code you are calling any of the functions function1 or function2.
I think what you are after is by amending the middle method to become:
def List_Of_Functions(My_Function):
return My_Function()
Without the parentheses after the My_Function, it's just passing a reference to the function and doing nothing with it.
Adding the parentheses - it's calling the function.
You missed function1() and function2() in the last statement
def function1():
return 3
def function2():
return 4
def List_Of_Functions(My_Function):
return My_Function
print(list(map(List_Of_Functions, [function1(), function2()])))
Related
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)
I'm refreshing my memory about some python features that I didn't get yet, I'm learning from this python tutorial and there's an example that I don't fully understand. It's about a decorator counting calls to a function, here's the code:
def call_counter(func):
def helper(x):
helper.calls += 1
return func(x)
helper.calls = 0
return helper
#call_counter
def succ(x):
return x + 1
if __name__ == '__main__':
print(succ.calls)
for i in range(10):
print(succ(i))
print(succ.calls)
What I don't get here is why do we increment the calls of the function wrapper (helper.calls += 1) instead of the function calls itself, and why does it actually working?
The important thing to remember about decorators is that a decorator is a function that takes a function as an argument, and returns yet another function. The returned value - yet another function - is what will be called when the name of the original function is invoked.
This model can be very simple:
def my_decorator(fn):
print("Decorator was called")
return fn
In this case, the returned function is the same as the passed-in function. But that's usually not what you do. Usually, you return either a completely different function, or you return a function that somehow chains or wraps the original function.
In your example, which is a very common model, you have an inner function that is returned:
def helper(x):
helper.calls += 1
return func(x)
This inner function calls the original function (return func(x)) but it also increments the calls counter.
This inner function is being inserted as a "replacement" for whatever function is being decorated. So when your module foo.succ() function is looked up, the result is a reference to the inner helper function returned by the decorator. That function increments the call counter and then calls the originally-defined succ function.
When you decorate a function you "substitute" you're function with the wrapper.
In this example, after the decoration, when you call succ you are actually calling helper. So if you are counting calls you have to increase the helper calls.
You can check that once you decorate a function the name is binded tho the wrapper by checking the attribute _name_ of the decorated function:
def call_counter(func):
def helper(*args, **kwargs):
helper.calls += 1
print(helper.calls)
return func(*args, **kwargs)
helper.calls = 0
return helper
#call_counter
def succ(x):
return x + 1
succ(0)
>>> 1
succ(1)
>>> 2
print(succ.__name__)
>>> 'helper'
print(succ.calls)
>>> 2
Example with Class Decorator
When you decorate a function with the Class Decorator, every function has its own call_count. This is simplicity of OOP. Every time CallCountDecorator object is called, it will increase its own call_count attribute and print it.
class CallCountDecorator:
"""
A decorator that will count and print how many times the decorated function was called
"""
def __init__(self, inline_func):
self.call_count = 0
self.inline_func = inline_func
def __call__(self, *args, **kwargs):
self.call_count += 1
self._print_call_count()
return self.inline_func(*args, **kwargs)
def _print_call_count(self):
print(f"The {self.inline_func.__name__} called {self.call_count} times")
#CallCountDecorator
def function():
pass
#CallCountDecorator
def function2(a, b):
pass
if __name__ == "__main__":
function()
function2(1, b=2)
function()
function2(a=2, b=3)
function2(0, 1)
# OUTPUT
# --------------
# The function called 1 times
# The function2 called 1 times
# The function called 2 times
# The function2 called 2 times
# The function2 called 3 times
What I don't get here is why do we increment the calls of the function wrapper (helper.calls += 1) instead of the function calls itself, and why does it actually working?
I think to make it a generically useful decorator. You could do this
def succ(x):
succ.calls += 1
return x + 1
if __name__ == '__main__':
succ.calls = 0
print(succ.calls)
for i in range(10):
print(succ(i))
print(succ.calls)
which works just fine, but you would need to put the .calls +=1 in every function you wanted to apply this too, and initialise to 0 before you ran any of them. If you had a whole bunch of functions you wanted to count this is definitely nicer. Plus it initialises them to 0 at definition, which is nice.
As i understand it it works because it replaces the function succ with the helper function from within the decorator (which is redefined every time it decorates a function) so succ = helper and succ.calls = helper.calls. (although of course the name helper is only definied within the namespace of the decorator)
Does that make sense?
As I understand this (correct me if I'm wrong) the order you program executes is:
Register call_function.
Register succ.
While registering succ function interpreter finds a decorator so it executes call_function.
Your function returns an object which is a function (helper). And adds to this object field calls.
Now your function succ has been assigned to helper. So when you call your function, you're actually calling helper function, wrapped within a decorator. So every field you add to your helper function is accessible outside by addressing succ because those 2 variables refer to same thing.
So when you call succ() it's basically the same if you would do helper(*args, **argv)
Check this out:
def helper(x):
helper.calls += 1
return 2
helper.calls = 0
def call_counter(func):
return helper
#call_counter
def succ(x):
return x + 1
if __name__ == '__main__':
print(succ == helper) # prints true.
I've written a simple decorator:
from functools import wraps
import random
def my_dec(f):
lst = list()
#wraps(f)
def wrapper(*args):
lst.append(random.randint(0, 9))
print(lst)
return f(*args)
return wrapper
#my_dec
def foo():
print("foo called")
Now, if I call foo multiple times lst is not being flushed. Instead, it builds up over time. Thus, multiple calls of foo return an output like this:
foo()
> [4]
> foo called
foo()
> [4, 9]
> foo called
foo()
> [4, 9, 1]
> foo called
...
Why is that? I thought a decorator is just syntactic sugar for my_dec(foo)?! I assumed that each call to my_dec flushes lst.
You're right... The decorator is just syntactic sugar. Specifically:
#decorator
def foo():
pass
is exactly the same thing as:
def foo():
pass
foo = decorator(foo)
Let's be a little more outlandish and rewrite this another way that is mostly equivalent1:
def bar():
pass
foo = decorator(bar)
del bar
Hopefully written out this way, you can see that if I call foo a bunch of times, I'm not calling decorator a bunch of times. decorator only got called once (to help create foo).
Now in your example, your decorator creates a list immediately when it gets called:
def my_dec(f):
lst = list() # list created here!
#wraps(f)
def wrapper(*args):
lst.append(random.randint(0, 9))
print(lst)
return f(*args)
return wrapper
The function returned wrapper gets assigned to your foo, so when you call foo, you're calling wrapper. Note that there is no code in wrapper that would reset lst -- only code that would add more elements to lst so there is nothing here to indicate the lst should get "flushed" between calls.
1(depending on what the decorator does, you might see some differences in the function's __name__ attribute, but otherwise it's the same thing...)
Also note that you'll have one lst for each time the decorator is called. We can go crazy with this one if we like and decorate foo twice:
#my_dec
#my_dec
def foo():
pass
Or we can decorate more than one function:
#my_dec
def foo():
pass
#my_dec
def bar():
pass
And then when we call foo and bar, we'll see that they each accumulate their own (distinct) lists of random numbers. In other words, each time your decorator is applied to something, a new list will be created and each time that "something" is called, the list will grow.
I have been hard pressed to answer a question we were recently asked as part of an exercise on higher-order functions in Python.
The question is to define two functions, one which takes no arguments, and passes three globally defined functions, c(), t() and f(), through if/else statements (if c() true, return t() else return f()). The other function is a higher-order function that we evaluate on c(), t() and f() that then passes them through the same if/else statements.
These functions are different and our task is to see how by defining three functions c(), t() and f() such that the first function returns 1 and the second returns something other than one.
So far I have come to the realization that the issue lies with the calling of the functions c(), t() and f() before passing them through the if/else statements. This however has not been enough to inspire a solution. Would anyone be able to steer me in the correct direction?
Here is the associated code:
def if_function(condition, true_result, false_result):
if condition:
return true_result
else:
return false_result
def with_if_statement():
if c():
return t()
else:
return f()
def with_if_function():
return if_function(c(), t(), f())
def c():
return []
def t():
return 1
def f():
return 1
You may easily pass callable as function arguments, without calling them.
def cond():
return True
def f():
return 2
def g():
time.sleep(60)
def if_function(condition_callable, call_if_true, call_if_false):
if condition_callable():
return call_if_true()
else:
return call_if_false()
if_function(cond, f, g) # evaluates immediately, does not sleep since g is never evaluated.
I have a question about decorators. I understand what are decorators and I know how to use it, I have read all this tutorial How to make a chain of function decorators?
I understand that :
>>> def my_decorator(fn):
>>> print 'Do something before'
>>> print fn()
>>> def foo():
>>> return 'Hello World!'
>>> foo = my_decorator(foo)
Is the same at that :
>>> def my_decorator(fn):
>>> print 'Do something before'
>>> print fn()
>>> #my_decorator
>>> def foo():
>>> return 'Hello World!'
I know what are closures and why we use closure in a decorator with parameters (to get the decorator parameters in nested function) but that I don't understand is why we use closure and nested functions to get arguments and the function.
How the closure (or something else) can access parameters and the function outside. I am unable to do the same without the #decorator.
Here for example I can access my foo() and the parameters of the function without passing this function in parameter :
def my_decorator(str):
def wrapper(fn):
def inner_function(*args):
print 'Do something before'
return fn(*args)
return inner_function
return wrapper
#my_decorator('test')
def foo(a, b):
return a + b
print foo(1, 1)
How this is possible ?
I found the solution :
In fact the decorator use the closure functionality :
So here is the solution to do the same thing without the decorator and with parameters (it's just to understand the operation, and to learn)
def wrapper(str):
def decorator_factory(fn):
def inner_function(*args):
print 'Do something before'
return fn(*args)
return inner_function
return decorator_factory
#my_decorator('test')
def foo(a, b):
return a + b
# with decorator
print foo(1, 1)
# without decorator
print wrapper('str')(foo)(1, 1)
Decorator is a function that takes one argument (this argument is function) - this is my definition of decorator. In your case wrapper is decorator. While my_decorator is used to collect arguments for inner_function. inner_function is used to replace original [not decorated] function. Step by step explanation would be:
my_decorator is called to collect options for inner_function
my_decorator returns wrapper
wrapper is responsible for capturing original function or in other words decorate it. In your case original function is foo.
wrapper returns replacement function for original (which is inner_function)
from now foo points to inner_function, therefore inner_function is executed then foo is called
Hope it makes things a bit clearer.