# Functions

Some tasks need to be performed multiple times within a program. Rather than rewrite the same code in multiple places, a function may be defined.

## Write a Function

To write a function, you must have a heading and an indented block of code. The heading starts with the keyword `def` and the name of the function, followed by parentheses, and a colon. The indented block of code performs some sort of operation.&#x20;

```python
def greet_customer():
  print("Welcome to Engrossing Grocers.")
  print("Our special is mandarin oranges.")
  print("Have fun shopping!")

greet_customer()
# prints greeting lines
```

The keyword `def` tells Python that we are defining a function. This function is called `greet_customer`. Everything that is indented after the `:` is what is run when `greet_customer()` is called. So every time we call `greet_customer()`, the three `print` statements run.

Function definitions may include parameters, providing data input to the function. Functions may return a value using the `return` keyword followed by the value to return.

Python uses simple syntax to use, invoke, or *call* a preexisting function. A function can be called by writing the name of it, followed by parentheses.

```python
# Define a function my_function() with parameter x
def my_function(x):
  return x + 1

# Invoke the function
print(my_function(2))      # Output: 3
print(my_function(3 + 5))  # Output: 9
```

## Function Indentation

Python uses indentation to identify blocks of code. Code within the same block should be indented at the same level. A Python function is one type of code block. All code under a function declaration should be indented to identify it as part of the function. There can be additional indentation within a function to handle other statements such as `for` and `if` so long as the lines are not indented less than the first line of the function code.

```python
# Indentation is used to identify code blocks
def testfunction(number):
  # This code is part of testfunction
  print("Inside the testfunction")
  sum = 0
  for x in range(number):
    # More indentation because 'for' has a code block
    # but still part of he function
    sum += x
  return sum
print("This is not part of testfunction")
```

## Function Parameters

Sometimes functions require input to provide data for their code. This input is defined using *parameters*.

*Parameters* are variables that are defined in the function definition. They are assigned the values which were passed as arguments when the function was called, elsewhere in the code.

For example, the function definition defines parameters for a character, a setting, and a skill, which are used as inputs to write the first sentence of a book.

```python
def write_a_book(character, setting, special_skill):
  print(character + " is in " + 
        setting + " practicing her " + 
        special_skill)
```

#### Multiple Parameters

Python functions can have multiple *parameters*. To define a function with multiple parameters, parameter names are placed one after another, separated by commas, within the parentheses of the function definition.

#### Parameters as Local Variables

Function parameters behave identically to a function’s local variables. They are initialized with the values passed into the function when it was called. Like local variables, parameters cannot be referenced from outside the scope of the function.

## Function Arguments

*Parameters* in python are variables — placeholders for the actual values the function needs. When the function is *called*, these values are passed in as *arguments*.

For example, the arguments passed into the function `.sales()` are the “The Farmer’s Market”, “toothpaste”, and “$1” which correspond to the parameters `grocery_store`, `item_on_sale`, and `cost`.

```python
def sales(grocery_store, item_on_sale, cost):
  print(grocery_store + " is selling " + item_on_sale + " for " + cost) 

sales("The Farmer’s Market", "toothpaste", "$1")
```

Here are the main types of arguments:

* **positional arguments:** the assignments depend on their positions in the function call.

  ```python
  def sales(grocery_store, item_on_sale, cost):
    print(grocery_store + " is selling " + 
      item_on_sale + " for " + cost) 

  sales("The Farmer’s Market", "toothpaste", "$1")
  ```
* **keyword arguments:** explicitly refer to what each argument is assigned to in the function call. Keyword arguments, must be written after all the positional arguments.

  ```python
  def sales(grocery_store, item_on_sale, cost):
    print(grocery_store + " is selling " + 
      item_on_sale + " for " + cost) 

  sales(grocery_store = "The Farmer’s Market", 
        item_on_sale = "toothpaste", 
        cost = "$1")
  ```
* **Default arguments**: used during the function definition. If the function is called without an argument for that parameter, it relies on the default.

  ```
  def sales(grocery_store, item_on_sale, cost = "$1"):
    print(grocery_store + " is selling " + 
      item_on_sale + " for " + cost) 

  sales("The Farmer’s Market", "toothpaste")
  ```

Note:

* Once you give an argument a default value, no arguments that follow can be used positionally.&#x20;
* Once you use keyword arguments, position arguments do not work.

## Returning Value from Function

A `return` keyword is used to return a value from a Python function. The value returned from a function can be assigned to a variable which can then be used in the program.

#### Returning Multiple Values

Python functions are able to return multiple values using one `return` statement. All values that should be returned are listed after the `return` keyword and are separated by commas.

In the example, the function `square_point()` returns `x_squared`, `y_squared`, and `z_squared`.

```python
def square_point(x, y, z):
  x_squared = x * x
  y_squared = y * y
  z_squared = z * z
  # Return all three values:
  return x_squared, y_squared, z_squared

three_squared, four_squared, five_squared = square_point(3, 4, 5)
```

## Lambda Function

A *lambda function* is a way of defining a function in a single line of code. Usually, we would assign them to a variable.

For example, the following lambda function multiplies a number by 2 and then adds 3:

```
mylambda = lambda x: (x * 2) + 3
print(mylambda(5))
# 13
```

Lambda functions work with all types of variables, not just integers! Here is an example that takes in a string, assigns it to the temporary variable `x`, and then converts it into lowercase:

```
stringlambda = lambda x: x.lower()
print(stringlambda("Oh Hi Mark!"))
# "oh hi mark!"
```

### Lambda Function with If Statements

We can make our lambdas more complex by using a modified form of an if statement.

Suppose we want to pay workers time-and-a-half for overtime (any work above 40 hours per week). The following function will convert the number of hours into time-and-a-half hours using an if statement:

```
def myfunction(x):
    if x > 40:
        return 40 + (x - 40) * 1.50
    else:
        return x
```

Below is a lambda function that does the same thing:

```
myfunction = lambda x: 40 + (x - 40) * 1.50 
                if x > 40 else x
```

In general, the syntax for an if function in a lambda function is:

```
lambda x: [OUTCOME IF TRUE] 
        if [CONDITIONAL] 
        else [OUTCOME IF FALSE]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lei-d.gitbook.io/python-for-data-analysis/python/functions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
