def
print_msg()
:# print_msg是外函式
msg =
"i'm 狂師"
defprinter()
:# printer是巢狀函式
print
(msg)
return printer # 返回巢狀函式printer
def
func
(a, b)
:def
line
(n):
nonlocal a # nonlocal用於宣告變數a是外圍函式的變數
a = a +
1return a * n - b
return line
裝飾器的作用是在不改變函式源**並且不改變函式呼叫方式的情況下,增強函式的功能,裝飾器本身也是乙個函式或者類。
寫乙個裝飾器可以為函式新增列印日誌的功能
import logging
logging.basicconfig(
format
='%(asctime)s - %(levelname)s: %(message)s'
, level=logging.debug)
# 這個裝飾器可以修飾任何引數和內嵌函式一致的函式
defuse_logging
(func)
:def()
: logging.info(
"%s is running"
% func.__name__)
func(
)@use_logging
deffun_a()
:print
('i am a'
)@use_logging
deffun_b()
:print
('i am b'
)fun_a(
)fun_b(
)# 裝飾器的第二種使用方式
fun_a = use_logging(fun_a)
fun_a(
)
class
testclass
(object):
def__init__
(self, func)
: self._func = func
def__call__
(self)
:# 類裝飾器必須實現__call__方法
print
('class decorator runing'
) self._func(
)print
('class decorator ending'
)@testclass
deffun_a()
:print
('fun_a is running'
)fun_a(
)
import logging
logging.basicconfig(
format
='%(asctime)s - %(levelname)s: %(message)s'
,level=logging.debug)
defuse_logging
(level)
:# 裝飾器帶引數
defdecorator
(func)
:def
(*args,
**kwargs)
:# 修飾函式的引數要和被修飾函式的引數一致
if level ==
"warn"
: logging.warning(
"%s is running by warning"
% func.__name__)
elif level ==
"info"
: logging.info(
"%s is running by info"
% func.__name__)
return func(
*args,
**kwargs)
return decorator
@use_logging(level=
"warn"
)def
fun_a
(*args,
**kwargs)
:print
("i am %s %s"
%(args,kwargs)
)@use_logging(level=
"info"
)def
fun_b
(*args,
**kwargs)
:print
("i am %s %s"
%(args,kwargs)
)fun_a(18,
20,name=
"張三"
)fun_b(
20,name=
"李四"
,age=
18)
from functools import wraps
# 裝飾器
defuse_print
(func)
: @wraps(func)
defwith_logging
(*args,
**kwargs)
:print
('calling decorated function...'
)return func(
*args,
**kwargs)
return with_logging
# 被裝飾函式
@use_print
deffun_a
(x):
"""does some math"""
print
('fun_a'
)# 如果裝飾器的內嵌函式不使用@wraps()裝飾器,則fun_a的名字和文件字串會是裝飾函式的,如果想列印fun_a自己的名字和文件字串,就要加@wraps()裝飾器
print
(fun_a.__name__, fun_a.__doc__)
用於修飾類的方法,從而把方法當做屬性使用
class
dataset
(object):
def__init__
(self)
: self.__name =
"張三"
self.__age =
18
@property
defname
(self)
:return self.__name
@property
defage
(self)
:return self.__age
# 加了這個裝飾器,使用者就可以設定__age的值了,並且進行一些校驗
@age.setter
defage(self, value):if
notisinstance
(value,
int)
:raise valueerror(
'age must be an integer!'
)if value <
0or value >
100:
raise valueerror(
'age must between 0 ~ 100!'
) self.__age = value
test_object = dataset(
)#使用者進行屬性呼叫的時候,直接呼叫name即可,而不用知道屬性名__name,因此使用者無法更改屬性,從而保護了類的屬性。
# 加了@property後,可以用呼叫屬性的形式來呼叫方法,後面不需要加()。
print
(test_object.name)
print
(test_object.age)
test_object.age =
60
def
decorator_a
(func)
:print
('get in a'
)def
inner_a
(*args,
**kwargs)
:print
('get in inner_a'
)return func(
*args,
**kwargs)
return inner_a
defdecorator_b
(func)
:print
('get in b'
)def
inner_b
(*args,
**kwargs)
:print
('get in inner_b'
)return func(
*args,
**kwargs)
return inner_b
# 會先執行a裝飾器,然後執行b裝飾器
@decorator_b
@decorator_a
deff
(x):
print
('fun a'
)return x *2f(
2)# 輸出結果
get in a
get in b
get in inner_b
get in inner_a
fun a
Python之裝飾器學習筆記
裝飾器本質上是乙個python函式,其返回值也是乙個函式物件 作用 不修改原函式情況下,為已有函式新增新的功能。如插入日誌 效能測試 事務處理 快取 許可權校驗等場景。閉包函式 在函式內部定義乙個內嵌函式,內嵌函式引用了外部函式的變數,此時內嵌函式稱為閉包函式。閉包函式所引用的外部定義的變數被叫做自...
Python之裝飾器筆記
概述 用於管理和增強函式和類行為的 提供一種在函式或類定義中插入自動執行 的機制 特點 更明確的語法 更高的 可維護性 更好的一致性 編寫函式基礎 將函式賦給變數 將函式作為引數傳遞 函式巢狀及跨域訪問 函式定義裝飾器 通用性更好 1 函式定義裝飾器 2 通用性更好34 引數化裝飾器 5def ta...
Python 學習筆記 裝飾器
裝飾器也是乙個函式 巢狀 用來裝飾某個函式,來看下面的 import time deftime count func def start time.time func end time.time print this funnction costs end start deftellhi print...