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

[Python] advanced syntax -- closures and decorators

編輯:Python

source :
【 Reference resources :Python Will know - Closures and decorators 】
【 Reference resources :Python Closures and decorators , That's how I understand it _ Bili, Bili _bilibili】

Add your own thinking process to the original foundation

Code visualization website :【 Reference resources :Python Tutor: Learn Python, JavaScript, C, C++, and Java by visualizing code】

summary

  1. LEGB Search principles ( Local , nesting , overall situation , Built-in scope )
  2. Python Closure (def Nested one def, Characteristic is Can remember the nested scope at that time
  3. Python Decorator ( A special closure , Add the same functionality to multiple functions , Such as timing function )
  • def Statement assigns a function object to a variable name at the top level of the module file func
  • def Is a simple executable statement , It can appear where any other statement can appear , Include nested in another def In .
  • The scope of a variable depends only on the location of the definition , Independent of function call location

LEGB

Local、Enclosing function locals、Global、Built-in

When referring to a variable ,Python Search in the following order :

  1. Local scope L
  2. The scope of the upper nested function E
  3. Global scope G
  4. Built-in scope B

The first one who can complete the search is successful , Will stop looking down

s = "G" # 3. (G) Global scope 
def computer(value=20):
# Nested variables within the scope :value, prize function , s
def prize():
print("s:", s) # 1.(L) The local variable 
print("inner:", value)
s = "E" # 2.(E) In the upper layer structure def or lambda The local scope of 
prize() # The scope of a variable depends only on the location of the definition , Independent of function call location 
computer(88)
""" s: E inner: 88 """
word = "global"
def outer(word="TAT"):
# Scope :word( Parameters ), inner function 
print(word) # L
def inner():
print(word) # E
word += "enclose"
inner()
outer()
print(word) # G
""" TAT TATenclose global """

Closure

【 Reference resources :python The function of closures _whgiser The blog of -CSDN Blog 】

Wikipedia : In some languages , In a function, you can ( nesting ) When defining another function , If an internal function references a variable of an external function , Then a closure may be generated . Closures can be used in a function with a set of “ private ” Create relationships between variables . In the process of a given function being called multiple times , These private variables can keep their persistence .

Closure not used

# Why do we introduce closures ?
func_list = []
for k in range(1, 5):
def func(x):
return x * k
func_list.append(func) # Save only the function name , The value of the parameter is not stored in 
# After the above operation k=4
for func in func_list: # The hope is 1x,2x,3x,4x
print(func(3)) # The hope is 3, 6, 9, 12
# The result is 3*4=12
""" 12 12 12 12 """

Introduce closures

# Use closures to solve the above problems 
def enclose(k):
# Nested scope : Parameters k, function func
def func(x):
return x * k
return func
func_list = []
for k in range(1, 5):
func_list.append(enclose(k)) # Closures can remember the scope at that time Here are the function and parameter values 
for func in func_list: # 1x,2x,3x,4x
print(func(3)) # 3, 6, 9, 12
""" 3 6 9 12 """

remarks : Closures can't remember variables in the global scope

# ============================================
# == Closures can remember nested scopes ( That is, the upper level scope )
# ============================================
T = 1
def enclose(day):
# Nested scope Variable day, function func
day = day + T
def func(x):
print("day: ", day) # 1. Nested variables within the scope day You can remember 
print(x + T) # 2. Global variables T Still can't remember , Only when calling func Function T Value 
return func
f = enclose(day=7)
# This function returns a variable name func And assign it to f, also func Remember when enclose Nested variables within the scope day
""" Global variables T=1 day = 7+1 =8 """
T += 1
g = enclose(day=7)
""" Global variables T=2 day= 7+2 =9 """
f(x=1)
""" Global variables T=2 func(): x+T = 1+2 """
g(x=1)
""" Global variables T=2 func(): x+T = 1+2 """
Output :
""" day: 8 3 day: 9 3 """

Decorator

A decorator is a closure ( It's just the outer layer def The parameter passed in is The function variables ), Just one more grammar sugar

Decorators let you in a Before and after the function To execute the code .

import time
# Decorator function 
def outer(origin):
# origin Is a function name 
def inner():
t1 = time.time()
origin()
t2 = time.time()
print(f"finish func: {
origin.__name__}, time cost: {
t2 - t1:.6f}(sec)")
return inner
# --------1----------
def myfunc1():
for i in range(100000):
pass
print(" I am a myfunc1 function ")
func = outer(myfunc1)
""" amount to origin = myfunc1 func = inner """
func()
""" Equivalent to calling inner() And then it will execute origin() namely myfunc1() """
# --------2---------- Decorator 
# Grammatical sugar Use decorators 
@outer # myfunc2= outer(myfunc2) stay def After performing 
def myfunc2():
for i in range(100000):
pass
print(" I am a myfunc2 function ")
myfunc2()
""" I am a myfunc1 function finish func: myfunc1, time cost: 0.001995(sec) I am a myfunc2 function finish func: myfunc2, time cost: 0.001994(sec) """

The typical way to write ornaments

import time
def outer(origin):
def inner(*args, **kwargs):
t1 = time.time()
origin(*args, **kwargs) # Need to receive parameters 
t2 = time.time()
print(f"finish func: {
origin.__name__}, time cost: {
t2 - t1:.6f}(sec)")
return inner
@outer # func1_new = outer(func1) stay def After performing 
def func1(a1):
print(" I am a func1 function ")
print(a1)
value = 11
return value
""" amount to origin=func1 func1_new =inner """
func1(-1) # func1_new 
""" Equivalent to calling inner(-1) And then it will execute origin(-1) namely func1(-1) """
@outer
def func2(b1,b2):
print(" I am a func2 function ")
print(b1,b2)
value = 22
return value
@outer
def func3(s="special"):
print(" I am a func3 function ")
value = 33
return value
func2(8, 9)
func3(s="time")
 I am a func1 function
-1
finish func: func1, time cost: 0.000000(sec)
I am a func2 function
8 9
finish func: func2, time cost: 0.000000(sec)
I am a func3 function
finish func: func3, time cost: 0.000000(sec)

Multi layer decorator

import logging
logging.basicConfig()
# Make a statement Logger object 
logger = logging.getLogger(__name__)
# Set the ignore level 
logger.setLevel(level=logging.INFO)
# Nested decorators 
def use_logging(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "info":
logger.info("%s is running" % func.__name__)
func(*args)
return wrapper
return decorator
def foo(name='foo'):
print("i am %s" % name)
foo = use_logging(level='warn')(foo)
foo()
# ============= Equivalent ==============
# python Grammatical sugar 
# foo = use_logging(level='warn')(foo)
# It can be seen that @ The following content is to remove the left... From the uplink code foo And on the right (foo) The rest 
@use_logging(level='warn')
def foo(name='foo'):
print("i am %s" % name)
""" level='warn' func=foo foo_new = decorator """
foo() # foo_new
""" Equivalent to calling decorator() And then it will execute wrapper(),wrapper It will execute func() namely foo() """
i am foo
i am foo

Class decorator

class myDecorator(object):
def __init__(self, f):
print("inside myDecorator.__init__()")
f() # Prove that function definition has completed
self.g = f # Put the function variable f Set as class property g
def __call__(self):
print("inside myDecorator.__call__()")
self.g()
def aFunction():
print("inside aFunction()")
aFunction = myDecorator(aFunction) # aFunction Is an object after class instantiation 
print("=== Finished decorating aFunction() ===")
aFunction() # Would call call
print('------------------------------')
@myDecorator
def bFunction():
print("inside bFunction()")
bFunction()
inside myDecorator.__init__()
inside aFunction()
=== Finished decorating aFunction() ===
inside myDecorator.__call__()
inside aFunction()
------------------------------
inside myDecorator.__init__()
inside bFunction()
inside myDecorator.__call__()
inside bFunction()

Object decorator

class Decorator:
def __init__(self, arg1, arg2):
print(' Executive class Decorator Of __init__() Method ')
self.arg1 = arg1
self.arg2 = arg2
def __call__(self, f):
print(' Executive class Decorator Of __call__() Method ')
# wrap = xxx
def wrap(*args):
print(' perform wrap()')
print(' Decorator parameters :', self.arg1, self.arg2)
print(' perform ' + f.__name__ + '()')
f(*args) # Perform customer functions 
print(f.__name__ + '() completion of enforcement ')
return wrap
@Decorator('Hello', 'World') # 2. example = Decorator('Hello', 'World')(example)
def example(a1, a2, a3): # 1. example = xxx
print(' Pass in example() Parameters of :', a1, a2, a3)
print(' Decoration completed ')
print(' Ready to call example()')
example('Wish', 'Happy', 'EveryDay') # 3.
print(' The test code is executed ')
 Executive class Decorator Of __init__() Method
Executive class Decorator Of __call__() Method
Decoration completed
Ready to call example()
perform wrap()
Decorator parameters : Hello World
perform example()
Pass in example() Parameters of : Wish Happy EveryDay
example() completion of enforcement
The test code is executed

wraps

not used wraps

from functools import wraps
def my_decorator(func):
# @wraps(func) # Prevent decorated functions example Function name and docstring Be modified 
def wrapper(*args, **kwargs):
'''decorator'''
print('Calling decorated function...')
func(*args, **kwargs)
return wrapper
@my_decorator
def example(): # Decorated function 
"""Docstring"""
print('Called example function')
example()
print(example.__name__, example.__doc__)
""" Calling decorated function... Called example function wrapper decorator """

Use wraps

from functools import wraps
def my_decorator(func):
@wraps(func) # Prevent decorated functions example Function name and docstring Be modified 
def wrapper(*args, **kwargs):
'''decorator'''
print('Calling decorated function...')
func(*args, **kwargs)
return wrapper
@my_decorator
def example(): # Decorated function 
"""Docstring"""
print('Called example function')
example()
print(example.__name__, example.__doc__)
""" Calling decorated function... Called example function example Docstring """

Decorator template

from functools import wraps
def outer(origin):
@wraps(origin)
def inner(*args, **kwargs):
print("before ...") # Before execution 
sum = origin(*args, **kwargs) # Call the original func function 
print("after ...") # After execution 
return sum
return inner
@outer # func = outer(func)
def func(x, y):
print(f"x: {
x}, y: {
y}")
return x + y
res = func(3,7)
print(res)
""" before ... x: 3, y: 7 after ... 10 """

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