--- title: Python Functions description: In Python, A function is a block of organized code that is used to perform a single task. --- ## Function arguments A function can take `arguments` and `return` values: In the following example, the function `say_hello()` receives the argument "name" and prints a greeting: ```python >>> def say_hello(name): ... print('Hello', name) ... >>> say_hello('Carlos') # Hello Carlos >>> say_hello('Wanda') # Hello Wanda >>> say_hello('Rose') # Hello Rose ``` The above function does not return any value (implicitly, it returns `None`) and is called **void function**. The following function, on the other hand, returns values and is thus called the **fruitful** function ```python >>> def my_sum(x,y): ... "Compute x + y." ... return x + y >>> my_sum(1,2) # 3 ``` ## Keyword Arguments When we define functions, we list the input parameters. These are called positional parameters (or positional arguments) because the position in the `def` statement determines which parameter is which. ```python >>> def poly(x,y): ... "Compute x + y**2." ... return x + y**2 >>> poly(1,2) # 5 >>> poly(2,1) # 3 ``` We can set default values for parameters: ```python >>> def psum(x,y,p=2): ... return x**p + y**p >>> psum(1,2) # 5 ``` To improve code readability, we should be as explicit as possible. We can achieve this in our functions by using `Keyword Arguments`: ```python >>> def say_hi(name, greeting): ... print(greeting, name) ... >>> # with positional arguments >>> say_hi('John', 'Hello') # Hello John >>> # with keyword arguments >>> say_hi(name='Anna', greeting='Hi') # Hi Anna ``` ## Return Values When creating a function using the `def` statement, you can specify what the return value should be with a `return` statement. A return statement consists of the following: - The `return` keyword. - The value or expression that the function should return. ```python >>> def sum_two_numbers(number_1, number_2): ... return number_1 + number_2 ... >>> result = sum_two_numbers(7, 8) >>> print(result) # 15 ``` ## Args and Kwargs `*args` and `**kwargs` allow you to pass an undefined number of arguments and keywords when calling a function. ```python >>> def some_function(*args, **kwargs): ... pass ... >>> # call some_function with any number of arguments >>> some_function(arg1, arg2, arg3) >>> # call some_function with any number of keywords >>> some_function(key1=arg1, key2=arg2, key3=arg3) >>> # call both, arguments and keywords >>> some_function(arg, key1=arg1) >>> # or none >>> some_function() ``` :::info :bulb: You’ll often see the parameter name `**kwargs` used to collect nonspecific keyword arguments. The `**kwargs` must be the rightmost paramter. ::: ## `*args` Positional arguments through the `*args` variable: ```python >>> def some_function(*args): ... print(f'Arguments passed: {args} as {type(args)}') ... >>> some_function('arg1', 'arg2', 'arg3') # Arguments passed: ('arg1', 'arg2', 'arg3') as <class 'tuple'> ``` ## `**kwargs` Keyword arguments are accessed through the `**kwargs` variable: ```python >>> def some_function(**kwargs): ... print(f'keywords: {kwargs} as {type(kwargs)}') ... >>> some_function(key1='arg1', key2='arg2') # keywords: {'key1': 'arg1', 'key2': 'arg2'} as <class 'dict'> ``` ## Local and Global Scope - Code in the global scope cannot use any local variables. - However, a local scope can access global variables. - Code in a function’s local scope cannot use variables in any other local scope. - You can use the same name for different variables if they are in different scopes. That is, there can be a local variable named `spam` and a global variable also named `spam`. ```python global_variable = 'I am available everywhere' >>> def some_function(): ... print(global_variable) # because is global ... local_variable = "only available within this function" ... print(local_variable) ... >>> # the following code will throw error because >>> # 'local_variable' only exists inside 'some_function' >>> print(local_variable) Traceback (most recent call last): File "<stdin>", line 10, in <module> NameError: name 'local_variable' is not defined ``` ## The `global` Statement If you need to modify a global variable from within a function, use the global statement: ```python >>> def spam(): ... global eggs ... eggs = 'spam' ... >>> eggs = 'global' >>> spam() >>> print(eggs) ``` There are four rules to tell whether a variable is in a local scope or global scope: 1. If a variable is being used in the global scope (that is, outside all functions), then it is always a global variable. 1. If there is a global statement for that variable in a function, it is a global variable. 1. Otherwise, if the variable is used in an assignment statement in the function, it is a local variable. 1. But if the variable is not used in an assignment statement, it is a global variable. ## Importing a module To start importing functions, we first need to create a module. **A module is a file ending in `.py` that contains the code you want to import into your program**. Let’s consider a module that contains the function `make_pizza()`. ### Direct import ```python import pizza pizza.make_pizza(16, 'pepperoni') pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') ``` ### Importing Specific Functions using `from` ```python from pizza import make_pizza make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') ``` ### Using `as` to Give a Function or Module an Alias ``` from pizza import make_pizza as mp mp(16, 'pepperoni') mp(12, 'mushrooms', 'green peppers', 'extra cheese') ``` ### Importing All Functions in a Module ```python from pizza import * make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') ``` :::info :bulb: However, it’s best not to use this approach when you’re working with larger modules that you didn’t write: if the module has a function name that matches an existing name in your project, you can get unexpected results! :::