程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python learning 3 (functions, decorators)

編輯:Python

Qianfeng education b The course of the station

function

Function definition

Parameters are optional

def Function name ([ Parameters ...]):
Code

Print function names directly , You will see the memory address where the function is located , The function name is equivalent to a variable , Points to this memory address

def gen():
print(1)
print(gen) # <function gen at 0x000002B1092DC268>

call , Function name ()

The order of the arguments when the function is called

>>> def test(a,b):
... print(a,b)
...
>>> test(1,2) # Positional arguments 
1 2
>>> test(b=1,a=2) # Key parameters 
2 1
>>>
>>> test(b=1,2) # Writing keyword parameters before positional parameters will cause errors 
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument

How to ensure that the parameters passed in meet the type requirements
isinstance( Variable , type )

def get_sum(a,b):
if isinstance(a, int) and isinstance(b, int):
print(a + b)
else:
print('type error')
get_sum(1.2,2)

Parameter default

When defining parameters, you can assign default values to parameters , In this way, you can not pass this parameter when calling
And the default value parameter must be after the ordinary parameter ( It's easy to understand , Because the calling function is passed by position )

# def get_sum(a, c = 100,b): # Report errors 
def get_sum(a,b, c = 100): # c The default value is given 100
if isinstance(a, int) and isinstance(b, int):
print(a + b + c)
else:
print('type error')
get_sum(1,2) #103

Key parameters

The parameter name assignment is explicitly used when calling , Because the default is to assign values in order of position , To prevent errors due to location transfer , You can assign values using keyword parameters
For example, in the following example , If c Want to use the default , and d To pass parameters , You need to use keyword parameters

def get_sum(a,b, c = 100,d=200):
if isinstance(a, int) and isinstance(b, int):
print(a + b + c + d)
else:
print('type error')
get_sum(1,2, d = 5)

Variable parameters

*args Receive individual variables
**kwargs

*args

Consider the scene : If you want to find two numbers with a function 、 Three numbers … The sum of multiple numbers
You can use variable parameters , In this way, multiple parameters passed in form a tuple , Pass to function
Or you can pass nothing , Equivalent to an empty tuple
This behavior of automatically forming tuples becomes packaging

def get_sum(*args):
print(args)
get_sum(1,2) # (1, 2) The output is a tuple 
get_sum(1,2,3,4,5) # (1, 2, 3, 4, 5)
get_sum() # ()

Here is the list

a,*b,c,d = 1,2,3,4,5,6
print(a,b,c,d)
# 1 [2, 3, 4] 5 6

If there are two variable parameters , Report errors

*a,*b,c,d = 1,2,3,4,5,6
# SyntaxError: two starred expressions in assignment

unpacking

a,b,c = (1,2,3)
print(a,b,c) # 1 2 3
# Unpack first and then pack 
*a,b,c = (1,2,3,5,6,7)
print(a,b,c) # [1, 2, 3, 5] 6 7

Pass in a list in a function with variable parameters , You can see that the output is a tuple with only one element
So how can we make the incoming function be separated by several numbers ?
You can unpack when calling , That is, add * Number

def get_sum(*args):
print(args)
get_sum([1,2,3]) # ([1, 2, 3],)
get_sum(*[1,2,3]) # (1, 2, 3)
def get_sum(a, *args):
print(a,args)
get_sum(1,2) # 1 (2,)
get_sum(1,2,3,4,5) # 1 (2, 3, 4, 5)
get_sum([1,2,3]) # [1, 2, 3] ()
get_sum(*[1,2,3]) # 1 (2, 3)

**kwargs

The output is a dictionary , An error will be reported if two position parameters are passed , Show the need for 0 Position parameters
So how should it be delivered ?
Keyword parameters can be passed , Will be converted into a dictionary
kw refer to key word
Keyword parameters must be passed , It will be converted into key:value In the form of , Encapsulated in a dictionary

def show_book(**kwargs):
print(kwargs)
show_book() # {}
show_book('a','b') # Report errors :TypeError: show_book() takes 0 positional arguments but 2 were given
show_book(name ='a') # {'name': 'a'}
# Unpack and pass the dictionary 
dict1 = {
'name':'a', 'num': 2}
show_book(**dict1) # {'name': 'a', 'num': 2}
# Use one * unpacking , Take out two key value 
print(*dict1) # name num
# Direct output **dict1 Will report a mistake 
# print(**dict1) # TypeError: 'name' is an invalid keyword argument for print()

Use both together

def show(*args, **kwargs):
print(args)
print(kwargs)
show(1,2) # (1, 2)/n {}
dict1 = {
'name':'a', 'num': 2}
show(1,2,**dict1)
# (1, 2)
# {'name': 'a', 'num': 2}

If many values are indefinite length parameters , So in this case , You can put the default parameters in args Behind , But if you have *kwargs Words ,kwargs Must be the last

def sum_nums_3(a, *args, b=22, c=33, **kwargs):
print(a)
print(b)
print(c)
print(args)
print(kwargs)
sum_nums_3(100, 200, 300, 400, 500, 600, 700, b=1, c=2, mm=800, nn=900)

Generally, the default value parameter will be placed in *args Behind

# c In the front , When transferring parameters, the third parameter will be assigned to c
def fun(a, b, c = 10, *args, **kwargs):
print(a,b,c,args,kwargs)
fun(1,2,3,4,5,name='a')
# 1 2 3 (4, 5) {'name': 'a'}
# c After variable parameters , When you assign c You need to use the keyword parameter assignment method 
def fun(a, b, *args, c = 10, **kwargs):
print(a,b,c,args,kwargs)
fun(1,2,3,4,5,name='a')
# 1 2 10 (3, 4, 5) {'name': 'a'}

kwargs It has to be at the back

Return value

python Functions in can return multiple return values
If multiple values are returned , Multiple values will be encapsulated into a tuple and returned

def returning():
return 1,2
res = returning()
a,b = returning() # 1,2
print(res) # (1, 2)

Global and local variables

When the local variable and the global variable have the same name in the function , Inside the function Variable name = data At this point, it is understood that a local variable is defined , Instead of modifying the value of the global variable
( It seems different from learning other languages before , stay java Global variables can be changed directly in a method in , And in the python Variables outside the function cannot be modified directly in , You can only view ; Why? , Just went to write a paragraph java The code feels , You can make an unprofessional and intuitive explanation , because java The declaration of variables in requires the addition of variable types , So if you declare the same variables as all variables in the function , Then the local variable is used in the function , Simply put, modifying variables is different from declaring variable code ; And in the python Variables declared in do not need to add variable types , Similarly, if you declare a variable in the function that is the same as the global variable , Then this can only be regarded as an operation of declaring variables , It cannot be used as an operation to modify global variables , Otherwise there will be problems , So in python Functions in cannot directly modify global variables )

So how can we modify global variables in functions ?
I need to declare in the function that I use global variables

a = 10
def check():
global a # If you don't add this sentence, you will report an error , Because global variables cannot be modified directly 
a -= 10
print(a)
check() # 0

If... Appears in a function global The name of the global variable Then, even if the variable name in this function is the same as the global variable name = data It is also understood as modifying global variables , Instead of defining local variables
If you need to modify multiple global variables in a function , Then you can declare it all at once , It can also be declared separately

# Can be used once global Declare multiple global variables 
global a, b
# It can also be used many times global Statements are OK 
# global a
# global b

View all global and local variables

Python Two built-in functions are provided globals() and locals() It can be used to view all global and local variables .

def test():
a = 100
b = 40
print(locals()) # {'a': 100, 'b': 40}
test()
x = 'good'
y = True
print(globals()) # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101710630>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/jiangwei/Desktop/Test/test.py', '__cached__': None, 'test': <function test at 0x101695268>, 'x': 'good', 'y': True}

Variable data types and immutable data types

The so-called variable type and immutable type refer to : Data can be modified directly , If you can modify it directly, it is variable , Otherwise, it is immutable
Variable type ( Modifying data , The memory address will not change ) Yes : list 、 Dictionaries 、 aggregate
Immutable type ( Modifying data , The memory address must change ) Yes :int、float、bool、 character string 、 Tuples
(python There is a small integer object pool in , String cache pool )
Only immutable data types need to be added global

Comments in functions

Use a string as the function document in the first line of the function

>>> def test(a,b):
... " To complete the right 2 Sum the numbers " # The first line of the function writes a string as the function document 
... print("%d"%(a+b))
...
>>>
>>> test(11,22) # Functions can be called normally 
33
>>>
>>> help(test) # Use help see test Function documentation 
Help on function test in module __main__:
test(a, b)
To complete the right 2 Sum the numbers

Put a pair of three quotation marks inside the function , Will appear automatically param… Allied , And java Medium /** */ be similar

def get_info(name: str, age: int):
""" The name and age of the receiving user , Splice a string and return :param name: Receive a name :param age: The age of the receiving user , Must be 0-200 An integer between :return: Returns the concatenated string """
return " My name is %s, This year is %d year " % (name, age)
get_info(" Wu Yanzu ", 19)
get_info(520, 19) # Be careful , The types marked on formal parameters only improve the readability of the code , It does not restrict the type of arguments 
help(get_info)

quote

sys.getrefcount() Get the number of references ( Calling this method itself also has a reference to the target address ), Take the following example 3 + 1 = 4

import sys
list1 = [1,2,3,4]
list2 = list1
list3 = list1
print(sys.getrefcount(list1)) # 4
# del list3
# print(sys.getrefcount(list1)) # 3
del list1
print(sys.getrefcount(list2)) # 3

Nested function

A function is just a piece of executable code , After compiling “ curing ” 了 , Each function has only one instance in memory , Get the entry point of the function and you can execute the function . Functions can also be nested , That is, you can define another function inside a function , With the structure of nested functions , The closure problem arises .

Nested function
A function is also a variable , Therefore, functions can also be defined inside functions , It's equivalent to declaring a variable

If you want to modify the variables of an external function , You need to declare the use of external variables in internal functions , That is, add keywords nonlocal

def outer():
a = 10
print('outer----hello')
def inner(): # inner This function is in outer Functions are defined internally 
b = 20
nonlocal a # nonlocal It refers to the local variable outside the internal function a
a += b
print('inner----hello')
inner() # inner Function is only in outer Visible inside the function 
print(inner) # <function outer.<locals>.inner at 0x00000134E031AEA0>
# Used to view local variables 
print(locals()) # {'a': 10, 'inner': <function outer.<locals>.inner at 0x00000223594EAEA0>}
outer()
# inner() There will be an error , stay outer Cannot access outside the function inner function 

Closure

If the following three conditions are met, it is a closure :

Is a nested function
The inner function references the variables of the outer function
The return value is an internal function

A closure is an entity composed of a function and its associated reference environment ( namely : Closure = Function block + Citation environment ).

In the first two calls of the following code , Because the internal function returns the function name , We know , Equivalent to a variable , Print out its address
In the last two calls , because outer(x) What is returned is a function name , Call internal functions with function names , So what is returned is the return value of the internal function , amount to res = outer(x), t = res()

Because you can't directly call the internal inner() function , So here in the external function inner() Return as a return value , You can use this internal function externally

def outer(n):
num = n
def inner():
return num+1
return inner
print(outer(3)) # <function outer.<locals>.inner at 0x0000020E2905AEA0>
print(outer(5)) # <function outer.<locals>.inner at 0x0000020E2905AEA0>
print(outer(3)()) # 4
print(outer(5)()) # 6

In this procedure , function inner Is the function outer The embedded function of , also inner The function is outer The return value of the function . We noticed a problem : Nested Function inner Local variables referenced in the outer function in num,Python This is how the interpreter handles this problem ? First let's take a look at the running result of this code , When we call by different parameters outer The function obtained by function , The result is isolated ( Mutual indifference ), That is to say, every call outer Function will generate and save a new local variable num, here outer The function returns a closure . If it's in an internal function , On the external scope ( But not in the global scope ) The variables are quoted , So internal functions are considered closures (closure).

Closures are commonly used in decorators

Decorator

First of all, understand , The function name is also a variable
As in the following code , Set function name b Assign a value to a,a The variable points to b Address of function , Therefore, the operation result is b

def a():
print('a')
def b():
print('b')
a = b
a() # b

In order not to modify the original existing function , Add new functions to functions ( Follow the principle of opening and closing ), There are decorators

To paint the walls of the house , Wrote an anonymous function , Perform discovery directly , It seems that no function is called , But there was 12 Result , explain @decorator Implemented decorator function , The parameters of the decorator function are house, the house Function is passed into the decorator as a parameter , So I will print those two lines , then return Back to wapper,house Receive this return value ,house = wrapper
here ,house Functions are decorated , It has become a new function wrapper, Execute at this time house Will be output wrapper Function execution result

def decorator(func):
print('--------------1')
print(func)
def wrapper():
print('---------')
func()
print(' Brush the wall ')
print('--------------2')
return wrapper
# house = decorator(house)
@decorator
def house():
print(' Rough house ')
# Output 
# --------------1
# <function house at 0x000002112911AEA0> ( This sentence can be seen before implementation , Will decorate , take house Function passed into decorator )
# --------------2
# Decorated house Turned into wrapper
print(house) # <function decorator.<locals>.wrapper at 0x000002112911C1E0> 
house()
# Output 
# ---------
# Rough house 
# Brush the wall 

The function of the decorator

  • Introducing logs
  • Function execution time statistics
  • Prepare for function execution
  • Clean up after function execution
  • Permission check and other scenarios
  • cache

Decorator with parameters

If the original function has parameters , Then the decorator internal function also needs to have parameters

def check_time(action):
def do_action(a,b):
action(a,b)
return do_action
@check_time
def go_to_bed(a,b):
print('{} Go to {} sleep '.format(a,b))
go_to_bed("zhangsan"," In bed ")

Indefinite length parameter

def test(cal):
def do_cal(*args,**kwargs):
# At this time, a tuple is passed into the internal function , Need to unpack 
cal(*args,**kwargs)
return do_cal
# Experience the transfer of multiple parameters , need *args
@test
def demo(a, b):
sum = a + b
print(sum)
# Experience the transfer of keyword parameters , need **kwargs
@test
def demo2(a, b, c = 4):
sum = a + b + c
print(sum)
demo(1, 2)
demo2(1, b = 2)

So in general , The parameters in the decorator will be written as these two variable parameters

Decorator decorated function with return value

In general, in order to make decorators more versatile , There can be return

def t_2(cal):
def do_cal(*args,**kwargs):
return cal(*args,**kwargs) # Need to write here again return sentence , Represents the calling function , Get the return value of the function and return 
return do_cal
@t_2
def demo(a,b):
return a + b
print(demo(1, 2)) #3

Decorator with parameters

understand

The order of execution is as follows , Detected first outer_check(23), The parameter 23 Into the outer_check Function , Execute this function , return check_time
And then execute check_time, take play_game In the incoming function , return do_action, here play_game = check_time

def outer_check(time):
def check_time(action):
def do_action():
if time < 22:
return action()
else:
return ' I'm sorry , You do not have this permission '
return do_action
return check_time
@outer_check(23)
def play_game():
return ' Play games '
print(play_game())

With multiple decorators

so , First load the closest decorator , Then load the far decorator

# Defined function : Complete package data 
def makeBold(fn):
print(1)
def wrapped():
return "<b>" + fn() + "</b>"
print(2)
return wrapped
# Defined function : Complete package data 
def makeItalic(fn):
print(3)
def wrapped():
return "<i>" + fn() + "</i>"
print(4)
return wrapped
def make(fn):
print(5)
def wrapped():
return "<z>" + fn() + "</z>"
print(6)
return wrapped
@make
@makeBold
@makeItalic
def t_3():
return "hello world-3"
print(t_3())
# Output :3 4 1 2 5 6
# <z><b><i>hello world-3</i></b></z>

Anonymous functions

Generally do not use

use lambda Keywords can create small anonymous functions . This kind of function gets its name from omitting def Standard steps for declaring functions .

lambda The syntax of a function contains only one statement , as follows :
lambda parameter list : Return value expression

sum = lambda arg1, arg2: arg1 + arg2
# call sum function 
print("Value of total : %d" % sum( 10, 20 ))
print("Value of total : %d" % sum( 20, 20 ))

Lambda Function can take any number of arguments but can only return the value of one expression

Anonymous functions can execute arbitrary expressions ( even to the extent that print function ), But it is generally believed that an expression should have a calculated result for return .

python When writing some execution scripts, you can use lambda, In this way, the process of defining functions can be accepted , For example, write a simple script to manage the server .

applications :

It can be passed as a parameter

>>> def fun(a, b, opt):
... print("a = " % a)
... print("b = " % b)
... print("result =" % opt(a, b))
...
>>> add = lambda x,y:x+y
>>> fun(1, 2, add) # hold add Pass as arguments 
a = 1
b = 2
result = 3

Python Built in functions and classes that use functions as parameters in :

Higher order function of system

stay Python in , Functions are also data types .
The data type corresponding to the function is function, It can be regarded as a complex data type .
Since it is also a data type , We can treat it as a number or a string .

Since variables can point to functions , The parameters of the function can receive variables , Then one function can take another function as an argument , Again , We can also treat one function as the return value of another function . The use of this function is called higher-order function .

Function as the parameter of another function has been mentioned above , As a return value, it is like returning an internal function in a closure , Take the function name as the return value

def test():
print(' I am a test What is entered in the function ')
def demo():
print(' I am a demo What you type in ')
return test # test Function as demo The return value of the function 
result = demo() # I am a demo What you type in call demo function , hold demo The return value of the function is assigned to result
print(type(result)) # <class 'function'> result The type of is a function 
result() # I am a demo What you type in I am a test What is entered in the function since result It's a function , Then you can use () Call this function 
demo()() # I am a demo What you type in I am a test What is entered in the function 

Higher order function of system :
max,min,sorted
If you want to find the oldest one of the following

students = [
{
'name': 'zhangsan', 'age': 18, 'score': 92},
{
'name': 'lisi', 'age': 20, 'score': 90},
{
'name': 'wangwu', 'age': 19, 'score': 95},
{
'name': 'jerry', 'age': 21, 'score': 98},
{
'name': 'chris', 'age': 17, 'score': 100},
]

Call directly max Is not workable ,max Medium key Keywords can be passed into a function , Indicates the basis for sorting

students = [
{
'name': 'zhangsan', 'age': 18, 'score': 92},
{
'name': 'lisi', 'age': 20, 'score': 90},
{
'name': 'wangwu', 'age': 19, 'score': 95},
{
'name': 'jerry', 'age': 21, 'score': 98},
{
'name': 'chris', 'age': 17, 'score': 100}
]
print(max(students, key=lambda x: x['age']))

filter() Filter ,filter Anonymous functions in require that the return value must be Boolean
Choose an age greater than or equal to 20 People who

res = filter(lambda x : x.get('age') >= 20, students)
print(list(res))
# [{'name': 'lisi', 'age': 20, 'score': 90}, {'name': 'jerry', 'age': 21, 'score': 98}]

map() function , What you want to extract through anonymous functions , And process the content , Put it in an iteratable object

print(list(map(lambda x: x['score'] / 2, students)))
# [46.0, 45.0, 47.5, 49.0, 50.0]

reduce, stay functools In the module , Compress the sequence


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved