Functions are block of code to perform some task or return some value. Functions can be reuse by the programmer.
#define the function
#this function has no parameters
def printNameAge( ):
print ('My name is Anthony')
print ('I am 23 years old')
#call the function aka function call
printNameAge( )
#this function has parameters, name and age
def selfIntro( name, age):
print ('My name is ' + name)
#Python need to convert integer to string
#when concatenate
print ('I am ' + str(age) + ' years old')
#function call
selfIntro('Cai' , 26)

Using formatted string instead of concatenation
#another way to print, is to use formatted string
#instead of concatenate
def selfIntro2( name, age):
print ( f"My name is {name} and I am {str(age)} years old" )
selfIntro2( 'Tony' , 32 )

Function which return a value
Below is a function that return a value, the above functions perform a task which is to print something.
#previous 3 fn perform a task
#which is to print something
def returnValueFn( interestRate ):
return interestRate
#you can throw this value into a variable
#and use it for other purpose
#the ":.2f" is to provide 2 decimal place
interest = returnValueFn(0.02)
print (f'Your final payment amount is {(1000*(1+interest)):.2f}. Thank you.')

Function with keyword argument
You can give your function a keyword argument. In this way your code will be more readable and people will understand better what your function is trying to do.
#fn with 2 parameters
def multiply( number , by):
return number * by
#fn call directly into print fn.
#by making argument 'by' a keyword
#argument, ie by=6, the code becomes
#more readable.
#multiply 3 by 6.
print(multiply(3, by=6))

Function with default argument
Function can carry a parameter with value during the function definition stage. Hence giving a parameter its value will make it an argument and in this case we call it default argument. Function with default argument.
One thing to take note is that the default argument must be the last in the parameter list. Example, def subtract(finalNum, num1=2, num2) will give an error. The correct way is def subtract(finalNum, num2, num1=2)
#fn with default argument (divisor=2)
def divide(num , divisor =2):
return num/divisor
#fn will use 2 for divisor
print(f'{divide(100):.2f}')

Function with variable number of arguments
#fn which take a variable amount of arguments
def multiplyVariable(*numbers):
print (numbers)
total = 1
for num in numbers:
total = total * num
print(total)
#fn call
multiplyVariable(2,3)
multiplyVariable(2,3,4,5)

Function with variable keyword arguments
#fn with multiple keyward arguments
def student(**profile):
return profile
id132 = student(id=132 , name='Anthony Ant' , gender = 'm' , dob=21011999)
print( id132 )
