I have two pieces of code that do almost the same thing. Can anyone tell me what is the difference between them or which one is the proper syntax in Python?
Code 1:
p = lambda content: print(content)
p("Hello")
# Prints Hello
Code 2:
p = print
p("Hello")
# Also Prints Hello
Code 1 is defining a new function, which calls the print() function. It would be more pythonic to write it as:
def p(content):
print(content)
lambda is normally only used for anonymous functions, not named functions.
Case 2 is simply giving another name to the print function. The two names can be used interchangeably.
The lambda function only accepts one argument, while the standard print function alloes multiple positional arguments and named arguments.
So with Code 2 you can write:
p("Hello", "world", end="")
but if you try this with Code 1 you'll get an error because you gave too many arguments to the function.
If you want to define a new function that can take all the arguments that print() takes, you can use *.
def p(*args, **kwds):
print(*args, **kwds)
or:
p = lambda *args, **kwds: print(*args, **kwds)
See What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
The first you are creating a anonymous function and assigning it to the variable p.
While in the second you are assigning the function print directly to the variable p.
Since in python functions are first class citizens, you can perform this kind of operations. Both are valid syntax, but if you only want to give a shorter name to a function, the second is simpler.
Related
python newbie here, I'm currently learning about nested functions in python. I'm having a particularly hard time understanding code from the example below. Particularly, at the bottom of the script, when you print echo(2)("hello") - how does the inner_function know to take that string "hello" as its argument input? in my head, I'd think you would have to pass the string as some sort of input to the outer function (echo)? Simply placing the string in brackets adjacent to the call of the outer function just somehow works? I can't seem to wrap my head around this..
-aspiring pythonista
# Define echo
def echo(n):
"""Return the inner_echo function."""
# Define inner_echo
def inner_echo(word1):
"""Concatenate n copies of word1."""
echo_word = word1 * n
return echo_word
# Return inner_echo
return inner_echo
# Call twice() and thrice() then print
print(echo(2)('hello'), echo(3)('hello'))
The important thing here is that in Python, functions themselves are objects, too. Functions can return any type of object, so functions can in principle also return functions. And this is what echo does.
So, the output of your function call echo(2) is again a function and echo(2)("hello") evaluates that function - with "hello" as an input argument.
Maybe it is easier to understand that concept if you would split that call into two lines:
my_function_object = echo(2) # creates a new function
my_function_object("hello") # call that new function
EDIT
Perhaps this makes it clearer: If you spell out a function name without the brackets you are dealing with the function as an object. For example,
x = numpy.sqrt(4) # x is a number
y = numpy.sqrt # y is a function object
z = y(4) # z is a number
Next, if you look at the statement return echo_word in the echo function, you will notice that what is returned is the inner function (without any brackets). So it is a function object that is returned by echo. You can check that also with print(echo(2))
This question already has answers here:
Passing functions with arguments to another function in Python? [duplicate]
(9 answers)
Closed 1 year ago.
Imagine that I want to create a function called "execute()". This function takes the name of another function and its input as parameters and outputs whatever it returns.
Here is an example:
execute(print, "Hello, World!") # "Hello, World!"
execute(str, 68) # "68"
Of course, this function wouldn't be of any use, but I want to grasp the main idea of putting another function in as a parameter.
How could I do this?
Functions can easily be passed into functions. To pass a variable length argument list, capture it with *args in the function definition and when calling the func use the same syntax to expand the arguments again into multiple parameters.
def execute(fn, *args):
return fn(*args)
Note: we are not passing the name of a function to execute(), we are passing the function itself.
You can just do this,
def execute (func, argv):
return func(argv)
execute(print, 'test')
returns test
execute(str, 65)
returns '65'
I believe this should work:
def execute(fn, *args, **kwargs):
return fn(*args, **kwargs)
Here:
args = Arguments (list)
kwargs = Keyworded Arguments (dictionary)
If you want to do more, then you can look for Decorators in Python.
Yes, you can pass functions as parameters into another function.
Functions that can accept other functions as arguments are also called higher-order functions.
I hope the following example helps:
def shout(text):
return text.upper()
def greet(func):
greeting = func("Hi, I am created by a function passed as an argument.")
print(greeting)
greet(shout)
The output of the code will be :
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.
I was unable to find a reasonable way to create a variable which calls a function requiring parameters.
Here is a simplified version of my code. I would like ‘print_hello’ to print ‘hello’ when it is called, and not when it is defined.
print_hello = print(‘hello’)
When I define ‘print_hello’, it calls print(‘hello’). When I call ‘print_hello’, it gives me an error. How do I fix this?
If you just want a function that does precisely what you describe, Sheldore's answer is the simplest way to go (and more Pythonic than using a named lambda).
An alternative approach is to make a partial application of the function with functools.partial, which allows you to pass additional arguments at call time:
from functools import partial
print_hello = partial(print, "hello")
print_hello() # Prints "hello" to stdout
print_hello(file=sys.stderr) # Prints "hello" to stderr
print_hello("world") # Prints "hello world" to stdout
Just define print_hello as a lambda function
>>> print_hello = lambda: print('hello')
>>> print_hello()
hello
To delay execution, you'll have to wrap the call to print in another function. A lambda is less code than defining another function.
Note: that pep08 recommends using a def function rather than a lambda when assigning to a variable. See here. So #Sheldores answer is probably the way to go.
You need to define a function. In python a function is defined using def as shown in a simple example for your purpose below. You then call the function using the function name and (), for instance print_hello().
def print_hello(): # <--- Does not accept an argument
print('hello')
print_hello() # <--- No argument is passed
# hello
Another example to give you more idea on how to pass an argument to the function. You can define a variable that contains the string you want to print, let's say to_print and then pass this as an argument to your function during calling it. While explaining more details is out of the scope of this answer, the two examples I gave should get you started. For more details, you can refer to the official docs here
def print_hello(to_print): # <--- Accepts an argument
print(to_print)
to_print = "hello"
print_hello(to_print) # <--- Argument is passed
# hello
You could use a lambda expression:
print_hello = lambda: print('hello')
Or an actual function definition:
def print_hello(): print('hello')
Or functools.partial (this is different in that you can still use other arguments for print whereas you lose that functionality with the others unless specified in the definitions)
from functools import partial
print_hello = partial(print, 'hello')
To use any of these:
print_hello()
#'hello'
I have already found various answers to this question (eg. lambda function acessing outside variable) and all point to the same hack, namely (eg.) lambda n=i : n*2 with i a variable in the external scope of lambda (hoping I'm not misusing the term scope). However, this is not working and given that all answers I found are generally from couple of years ago, I thought that maybe this has been deprecated and only worked with older versions of python. Does anybody have an idea or suggestion on how to solve this?
SORRY, forgot the MWE
from inspect import getargspec
params = ['a','b']
def test(*args):
return args[0]*args[1]
func = lambda p=params : test(p)
I expected the signature of func to be ['a','b'] but if I try
func(3,2)
I get a Type error (TypeError: <lambda>() takes at most 1 argument (2 given) )
and it's true signature (from getargspec(func)[0] ) is ['p']
In my real code the thing is more complicated. Shortly:
def fit(self, **kwargs):
settings = self.synch()
freepars = self.loglike.get_args()
func = lambda p=freeparams : self.loglike(p)
minuit = Minuit(func,**settings)
I need lambda because it's the only way I could think to create inplace a function object depending on a non-hardcoded list of variables (extracted via a method get_params() of the instance self.loglike). So func has to have the correct signature, to match the info inside the dict settings
The inspector gives ['p'] as argument of func, not the list of parameters which should go in loglike. Hope you can easily spot my mistake. Thank you
There's no way to do exactly what you want. The syntax you're trying to use to set the signature of the function you're creating doesn't do what you want. It instead sets a default value for the argument you've defined. Python's function syntax allows you to define a function that accepts an arbitrary number of arguments, but it doesn't let you define a function with argument names in a variable.
What you can do is accept *args (or **kwargs) and then do some processing on the value to match it up with a list of argument names. Here's an example where I turn positional arguments in a specific order into keyword arguments to be passed on to another function:
arg_names = ['a', 'b']
def foo(*args):
if len(args) != len(arg_names):
raise ValueError("wrong number of arguments passed to foo")
args_by_name = dict(zip(arg_names, args))
some_other_function(**args_by_name)
This example isn't terribly useful, but you could do more sophisticated processing on the args_by_name dict (e.g. combining it with another dict), which might be relevant to your actual use case.
Sorry for the newbie question guys, but I'm relatively new to python. I want to write a function that passes keyword and value arguments into another function:
e.g.
def function_that_passes_arguments(arguments):
some_other_function(arguments)
so when I call the first function they are passed into the second... e.g.
function_that_passes_arguments(arg1=1, arg2=2)
is effectively
some_other_function(arg1=1, arg2=2)
The argument names will change so it is important that I pass both keyword and value from one function to another.
Accept *args, **kwargs and pass those to the called function:
def function_that_passes_arguments(*args, **kwargs):
some_other_function(*args, **kwargs)
In both places you can also use regular arguments - the only requirement is that the * and ** arguments are the last ones.