# Python- user-defined Functions

In order to organize your code with some repeating requirements, calling functions can be quite efficiently. Other than those built-in function, you can also create your own user-defined functions. The basic syntax of Function is:

``````def function_name(parameters):
"""docstring"""
statement(s)

return return_value
``````

Return statement is an option since the return value is not always necessary. Also the docstring, short remark for this function, in between triple double quotes is optional. Docstring is available to us as doc attribute of the function. Multiple input is allowed and using list or tuple can implement various returns.

```def sum(X):
"""Rerurn the summary amount of input values"""
total_amount=0
for x in X:
total_amount+=x

return total_amount

test=[15,45,10,5,30,25]
sum_test=sum(test)
print(sum_test)    #130
print(sum.__doc__) # Rerurn the summary amount of input values
#print(total_amount) #NameError: name 'total_amount' is not defined
```

# Nested function

A function can also be inside of another function, the syntax would be:

``````def outer(outer_parameters):
statement(s)
def inner(inner_parameters):
statement(s)
return return_value    ``````
```def array_sum(Xs):

def sum(X):
total_amount=0
for x in X:
total_amount+=x

return total_amount

return [sum(x) for x in Xs]

print(array_sum(([1,2,3],[4,5,6],[7,8,9])))  #
[6, 15, 24]
```

# Using a function as the return value

```def first_n_sum(n):

def sum(X):
total_amount=0
for i in range(n):
total_amount+=X[i]

return total_amount

return sum

test_data=(1,2,3,4,5,6)
first_three=first_n_sum(3)
first_five=first_n_sum(5)
print(first_three(test_data),first_five(test_data)) #(6, 15)
```

# global and nonlocal

Keyword global can let you modify the variable outside of the function. Once a global variable is created, it can be changed in a local scope; similiarly, nonlocalallows modifying in outer function. Remember the search sequence is local scope->enclosing function->global

### global:

```n=10
def outer():
global n
n=1
def inner():

n=2
print(n)    #2

inner()
print(n)        #1
outer()
print(n)            #1
```

### nonlocal

```n=10
def outer():

n=1
def inner():<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;">﻿</span>
nonlocal n
n=2
print(n)      #2

inner()
print(n)          #2
outer()
print(n)              #10
```

# Default arguments

Just assign the default value to the argument with =

```def first_n_sum(n=4):

def sum(X):
total_amount=0
for i in range(n):
total_amount+=X[i]

return total_amount

return sum

test_data=(1,2,3,4,5,6)
default=first_n_sum()
first_four=first_n_sum(4)
print((default(test_data),first_four(test_data)))  #
(10, 10)
```

# Flexible arguments

In the beginning, the case of function sum(), even though the argument X can be a list, the input of this function is single argument. There is a way to pass a variable number of arguments to a function: put asterisk (*) or double asterisk (**) in front of the argument. The single asterisk form is used to pass a non-keyworded, variable-length argument list, and the double asterisk form is used to pass a keyworded, variable-length argument list.

```def sum(*X):
"""Rerurn the summary amount of input values"""
total_amount=0
for x in X:
total_amount+=x

return total_amount

#test=[15,45,10,5,30,25]
#sum_test=sum(test)
sum_test=sum(15,45,10,5,30,25)  #it actually accepts six parameters

print(sum_test)         #130
```