[Python basics] day8 -- LEGB principles of function and scope

Keywords: Python Lambda ascii

Function (subroutine, procedures)

definition:

  • Function is to encapsulate a set of statements with a name (function name). To execute this function, you only need to call its function name

effect:

 

  • Easy to reuse a part of code and reduce duplicate code
  • Easy to modify code and expand
  • Keep the consistency of the code to prevent repeated code segments from missing changes
import datetime

def func_first(input_text):
    f = open('test.txt','a')
    f.write("%s-%s\n" % (datetime.datetime.now(),input_text))
    f.close()
    print(datetime.datetime.now(),"-%s" % input_text)

func_first("exec func_1")
func_first("exec func_2")
func_first("exec func_3")
func_first("exec func_4")
func_first("exec func_5")

import datetime

def func_first(input_text):                              #Input here_ Text equivalent to position parameter
    f = open('test.txt','a')
    f.write("%s-%s\n" % (datetime.datetime.now(),input_text))  #The result of the implementation is that the current time can appear in front of each line. Note that when the previous line of code is inserted into the current time, it needs to be converted to str string format
    f.close()
    print(datetime.datetime.now(),"-%s" % input_text)

func_first("exec func_1")                                #Call the function to pass in variable parameters, and write them directly in the brackets of the function
func_first("exec func_2")
func_first("exec func_3")
func_first("exec func_4")
func_first("exec func_5")

Execution result:

2020-06-19 10:08:26.375084 -exec func_1
2020-06-19 10:08:26.376080 -exec func_2
2020-06-19 10:08:26.377078 -exec func_3
2020-06-19 10:08:26.378076 -exec func_4
2020-06-19 10:08:26.379073 -exec func_5

Process finished with exit code 0

What to write to the file:

2020-06-19 10:08:26.374126-exec func_1
2020-06-19 10:08:26.375084-exec func_2
2020-06-19 10:08:26.376080-exec func_3
2020-06-19 10:08:26.377078-exec func_4
2020-06-19 10:08:26.378076-exec func_5

Naming rules for function names:

  • The function name must start with an underscore or a letter. It can contain any combination of letters, numbers or underscores. No punctuation is allowed
  • Function names are case sensitive
  • Reserved words cannot be used for function names


Formal and actual parameters:

  • Parameter: a formal parameter, which does not exist in reality, is a virtual variable. When defining a function and a function body, the parameter is used. The purpose is to receive the actual parameter when the function is called (the number and type of the actual parameter should correspond to the actual parameter one by one)
  • Actual parameter: actual parameter, the parameter passed to the function when calling the function. It can be always on, variable, expression, function, passed to parameter


Using function to make adder:

def add(a,b):
    print(a+b)

add(5,7)

Execution result:

12

Process finished with exit code 0


Parameters of function

Required parameters

The required parameters are passed into the function in the correct order, and the number of calls must be the same as that of declarations

def print_info(name,age):
    print("Name: %s"%name)
    print("Age: %s"%age)

print_info('yuyang',18)

Execution result:

Name: yuyang
Age: 18

Process finished with exit code 0

Key parameters

 

def print_info(name,age):
    print("Name: %s"%name)
    print("Age: %s"%age)

print_info(age=18,name='yuyang')

Execution result:

Name: yuyang
Age: 18

Process finished with exit code 0

Default parameters

def print_info(name,age=18):
    print("Name: %s"%name)
    print("Age: %s"%age)

print_info('yuyang')
print_info('jiayanping',20)

Execution result:

Name: yuyang
Age: 18
Name: jiayanping
Age: 20

Process finished with exit code 0

Indefinite length parameter

Example 1:

def add(*args):
    print(args)

add(1,2,3,4)

Execution result:

(1, 2, 3, 4)

Process finished with exit code 0


Example 2:

def print_info(*xargs,**kwargs):                 #If you pass in a key value pair, add two before the variable of indefinite length*
    print(xargs)
    print(kwargs)
    print('---')
    for i in kwargs:
        print("%s:%s" % (i,kwargs[i]))

print_info('yuyang',18,name='jiayanping',age=20)

Execution result:

('yuyang', 18)                                      #tuple
{'name': 'jiayanping', 'age': 20}                   #Dictionary (because it is a key value pair)
---
name:jiayanping
age:20

Process finished with exit code 0


In example 2, if the result cannot be printed according to the following line code, an error will be reported:

print_info(name='jiayanping','yuyang',18,age=20)

ERROR:

  File "H:/python_scripts/study_scripts/daily/day14/kwargs.py", line 10
    print_info(name='jiayanping','yuyang',18,age=20)
                                ^
SyntaxError: positional argument follows keyword argument

Process finished with exit code 1


Adder:

def add(*args):
    print(args)
    sum = 0
    for i in args:
        sum += i
    print("Sum: %s" % sum)
    print('---')

add(1,2,3,4)
add(1,2,3,4,5,6,7,8)

Execution result:

(1, 2, 3, 4)
Sum: 10
---
(1, 2, 3, 4, 5, 6, 7, 8)
Sum: 36
---

Process finished with exit code 0

Use the following lines of code to basically let the function receive all the parameters, whether it is string, list, key value pair

def print_info(*xargs,**kwargs):     

 

  • For indefinite length parameters, * args unnamed parameters are placed on the left, while * * kwargs named parameters are placed on the right

  • If there are default parameters, put them on the left

 

 

Return value of function return

To get the execution result of a function, you can use the return statement to return the result

be careful:

  1. When a function encounters a return statement during execution, it stops execution and returns results. Therefore, it can be understood that the return statement represents the end of the function
  2. If return is not specified in the function, the return value of the function is None
  3. return multiple objects. The interpreter will assemble the Acura object into a tuple and output the result as a whole

 

return
 

Function:

  1. End function
  2. Return an object


Example:

def f():
    print("ok")
    return 'success'

rst=f()
print(rst)

Execution result:

ok
success

Process finished with exit code 0

 

  • The default return value of the function is None

  • If you return multiple objects, python will encapsulate multiple objects into a tuple to return

 

def f():
    print("ok")
    return 'success',1,[5,6,7]

rst=f()
print(rst)

result:

ok
('success', 1, [5, 6, 7])

Process finished with exit code 0


As can be seen from the above results, return can return multiple values, but it encapsulates the returned multiple values into one object to return

 

Scope of function


In python, there are four kinds of functions:

  • 50: L ocal, the local scope, which is the variable defined in the function
  • E: Embedding, the local scope of the nested parent function, that is, the local scope of the parent function containing this function, but not the global scope
  • G: Global, a global variable, is a variable defined at the module level
  • B: Built in: variables in the system fixed module, such as int, bytearray, etc.
  • LEGB: the priority order of search variables is: scope local > outer scope > Global python built-in scope in the current module


Examples of LEGB variables:

x = int(3.6)   #int----built-in

y = 'yuyang'      #global

def outer():
    a = 1            #enclosing
    def inner():
        b = 2            #local
        print(x,y,a,b)
    inner()                  #Note that in a nested function, the child function must be executed in the parent function after it is written

outer()

Execution result:

3 yuyang 1 2

Process finished with exit code 0

Note that in a nested function, the child function must be executed in the parent function after it is written


ERROR case

count = 10
def f():
    print(count)
    count = 5

f()

Execution result:

Traceback (most recent call last):
  File "H:/python_scripts/study_scripts/daily/day14/le.py", line 6, in <module>
    f()
  File "H:/python_scripts/study_scripts/daily/day14/le.py", line 3, in f
    print(count)
UnboundLocalError: local variable 'count' referenced before assignment


The reason for the error is:

  • Global variables are not allowed to be modified locally. If this variable is modified locally, two variables with the same name will be created, but with different scopes.
  • If you want to modify global variables locally, you can use the following global method
count = 10
def f():
    global count
    print(count)
    count = 5
    print(count)
f()

result:

10
5

Process finished with exit code 0


nonlocal method

 

def outer():
    a = 1
    def inner():
        nonlocal a            #If the upper level of the variable is not a global variable, you need to use nonlocal to modify the variable
        a = 2
        print(a)
    inner()
    print(a)

outer()

Execution result:

2
2

Process finished with exit code 0


If we need to pass a dictionary into the function:

def f(**kwargs):
    print(kwargs)

f({'name':'yuyang'})

result:

Traceback (most recent call last):
  File "H:/python_scripts/study_scripts/daily/day14/dict_func.py", line 4, in <module>
    f({'name':'yuyang'})
TypeError: f() takes 0 positional arguments but 1 was given

Process finished with exit code 1


The right way is to:

def f(**kwargs):
    print(kwargs)

f(**{'name':'yuyang'})

results of enforcement

{'name': 'yuyang'}

Process finished with exit code 0


Summary:

  1. Variable search order: LEGB, scope local > outer scope > global in current module > Python built-in scope
  2. Only modules, classes, and functions can reference new scopes
  3. For a variable, if the internal scope is declared first, the external variable will be overwritten. If it is not declared and used directly, the external scope variable will be used
  4. When the internal scope needs to modify the value of the external scope variable, if the global keyword is used for the global variable and the non local keyword is used for the nested scope variable. The non local keyword is a new keyword added by Python 3. With this keyword, the closure can be perfectly implemented.
  5. Function name can be assigned
  6. The function name can be used as a function parameter or as a function return value

 


Higher order function

One of the following conditions is a higher-order function

  • The function name can be entered as an argument
  • Function name can be used as return value

Example:

def f(n):
    return n*n

def foo(a,b,func):
    print(func(a)+func(b))

foo(1,2,f)

Execution result:

5

Process finished with exit code 0


For the function f(), f is only the function name and also a variable. Only when it runs to f(), the code block in the function will be executed

 

Conclusion:

  • Function name is a variable, so function name can be assigned
  • The function name can be used as a function parameter or as a function return value


The function name can be used as an example of a function return value:

def foo():
    x=5
    return x

print(foo())

Execution result:

5

Process finished with exit code 0

Example 2:

def foo():
    def inner():
        return 8
    return inner()

print(foo())

Execution result:

8

Process finished with exit code 0


Scope generation

  • Only module s, class es and functions (def, lambda) will introduce new scopes, and other code blocks will not


Recursive function


Factorial apparatus

def jc(a):
    number=1
    while True:
        number = a * number
        a -= 1
        if a == 1:
            break
    print(number)

jc(7)

Or:

def jc(a):
    number=1
    for i in range(a):
        i += 1
        number = i * number
    print(number)

jc(7)

Execution result:

5040

Process finished with exit code 0


The recursive function evolved from the factorizer above, that is, the program above, is written with recursive function:

def fact(n):
    if n == 1:                            #For recursive functions, we need to set the maximum value so that the recursive function has the upper limit of execution to prevent infinite execution
        return 1                          #Return can end the function. The program after return will no longer be executed
    return n*fact(n-1)

print(fact(5))


Execution result:

120

Process finished with exit code 0

On the characteristics of recursive functions

  • Call own function
  • There is an end condition
  • But any program that can be written recursively can be solved by loop
  • The efficiency of recursion is very low in many cases, which is not recommended
  1. There must be a clear end condition
  2. Every time we go to a deeper level of recursion, the scale of the problem should be reduced compared with the last recursion
  3. Low efficiency of recursion, too many recursion levels will lead to stack overflow (in computer, function call is realized by stack data structure. When entering a function call, the stack will add a stack frame. Because the stack size is not infinite, too many recursion calls will lead to stack overflow)


Fibonacci series: (the last number is the sum of the first two numbers)

0 1 1 2 3 5 8 13 21 34 55 89


Fibonacci implementation procedure:

 

def fibo(n):
    if n<2:
        return n
    return fibo(n-1)+fibo(n-2)

print(fibo(9))

Execution result:

34

Process finished with exit code 0


Built in functions

Print all built-in functions in python

for item in dir(__builtins__):
    print(item)

result:

ArithmeticError
AssertionError
AttributeError
BaseException
BlockingIOError
BrokenPipeError
BufferError
BytesWarning
ChildProcessError
ConnectionAbortedError
ConnectionError
ConnectionRefusedError
ConnectionResetError
DeprecationWarning
EOFError
Ellipsis
EnvironmentError
Exception
False
FileExistsError
FileNotFoundError
FloatingPointError
FutureWarning
GeneratorExit
IOError
ImportError
ImportWarning
IndentationError
IndexError
InterruptedError
IsADirectoryError
KeyError
KeyboardInterrupt
LookupError
MemoryError
ModuleNotFoundError
NameError
None
NotADirectoryError
NotImplemented
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
PermissionError
ProcessLookupError
RecursionError
ReferenceError
ResourceWarning
RuntimeError
RuntimeWarning
StopAsyncIteration
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TimeoutError
True
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
WindowsError
ZeroDivisionError
__build_class__
__debug__
__doc__
__import__
__loader__
__name__
__package__
__spec__
abs
all
any
ascii
bin
bool
bytearray
bytes
callable
chr
classmethod
compile
complex
copyright
credits
delattr
dict
dir
divmod
enumerate
eval
exec
exit
filter
float
format
frozenset
getattr
globals
hasattr
hash
help
hex
id
input
int
isinstance
issubclass
iter
len
license
list
locals
map
max
memoryview
min
next
object
oct
open
ord
pow
print
property
quit
range
repr
reversed
round
set
setattr
slice
sorted
staticmethod
str
sum
super
tuple
type
vars
zip

Process finished with exit code 0

Several important built-in functions

filter function

str=['a','b','c','y','n']

def f(s):
    if s != 'y':
        return s

rst = filter(f,str)
print(rst)
print(list(rst))

Execution result:

<filter object at 0x0000025F760A39B0>
['a', 'b', 'c', 'n']

Process finished with exit code 0


map function

 

str=['a','b','c']

def f(s):
    return s + 'yuyang'

rst = map(f,str)
print(rst)
print(list(rst))

Execution result:

<map object at 0x000001E9FF4039B0>
['ayuyang', 'byuyang', 'cyuyang']

Process finished with exit code 0

 

 

reduce function

 

from functools import reduce

def add(x,y):
    return x+y

print(reduce(add,range(1,101)))

Execution result:

5050

Process finished with exit code 0


The result of reduce is a value


lambda function

a= lambda a,b: a+b

print(a(1,2))

Execution result:

3

Process finished with exit code 0

 

Posted by jedney on Thu, 25 Jun 2020 23:16:12 -0700