一、裝飾器的執行
裝飾器本質就是函數,功能是爲其他函數添加附加功能。
實現原則:
不修改被修飾函數的源代碼。
不修改被修飾函數的調用方法。
def auth(func):
import functools
@functools.wraps(func) # 把被裝飾函數的信息放入到閉包中
def inner(*args,**kwargs):
# 傳入函數執行前可以寫入代碼
ret = func(*args,**kwargs) # 閉包,執行 index()
# 傳入函數執行後可以寫入代碼
return ret
return inner
'''
@auth = auth(index) 把被裝飾函數傳入到裝飾器函數中
'''
@auth
def index():
print('index')
print(index.__name__)
# 加裝飾器輸出:inner;不加裝飾器輸出:index
# @functools.wraps(func) 輸出:index
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return “Function will not run”
return f(*args, **kwargs)
return decorated
二、多個裝飾器的執行順序
如果裝飾器的功能需要先執行,應該放在離要執行函數最近的位置,否則會無法執行裝飾器的功能,具體情況根據裝飾器的功能而定。
三、裝飾器執行過程
3.1、不帶參數的裝飾器
@auth
def index():
print('index')
'''
在執行時先把 index 函數傳入到 auth 裝飾器函數中,並在裝飾器函數的閉包中運行 index(),並返回函數。
'''
帶參數的裝飾器
@auth(‘參數’)
def index():
print('index')
'''
1、去掉@,運行auth(‘參數’),返回裝飾器中的函數;
2、再執行時把 index 函數傳入裝飾器函數中,在裝飾器函數的閉包中運行 index(),並返回。
'''
四、裝飾器實現過程
#裝飾器:對類或者函數進行功能的擴展
'''
#第一步:基本函數
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#調用函數
la()
la()
#第二步:擴展函數功能(不能修改原函數)
#用於擴展基本函數的函數
def kuozhan(func):
#擴展功能1
print('la前參拜祈求')
#調用基本函數
func()
#擴展功能2
print('la後還願感謝')
#基本函數
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#擴展之後的函數要重新賦值給基本函數!(但是此步驟還實現不了)
la = kuozhan(la)
print(la)
#調用函數
#la()
#la()
#第三步:使用語法糖(就是語法) @語法
#用於擴展基本函數的函數
def kuozhan(func):
#擴展功能1
print('la前參拜祈求')
#調用基本函數
func()
#擴展功能2
print('la後還願感謝')
#基本函數
@kuozhan #la = kuozhan(la)#擴展之後的函數要重新賦值給基本函數!(但是此步驟還實現不了)
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
print(la)
#調用函數
#la()
#la()
#第四步:基本裝飾器的實現
#用於擴展基本函數的函數
def kuozhan(func):
#內部函數(擴展之後的la函數)
def newla():
#擴展功能1
print('la前參拜祈求')
#調用基本函數
func()
#擴展功能2
print('la後還願感謝')
#添加返回值
return newla
#基本函數
@kuozhan #la = kuozhan(la)#擴展之後的函數要重新賦值給基本函數!(但是此步驟還實現不了)
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#print(la)
#調用函數
la()
la()
#第五步:帶有參數的裝飾器和帶有返回值的裝飾器
#用於擴展基本函數的函數
def kuozhan(func):
#內部函數(擴展之後的la函數)
def newla(shui,na):
#擴展功能1
print('la前參拜祈求')
#調用基本函數
func(shui,na)
#擴展功能2
print('la後還願感謝')
#添加返回值
return newla
#基本函數
@kuozhan #la = kuozhan(la)#擴展之後的函數要重新賦值給基本函數!(但是此步驟還實現不了)
def la(who,where):
print(who,'在',where,'tuokuzi')
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#print(la)
#調用函數
la('yangjun','羊圈')
la('yanfei','鳥巢')
#帶有返回值的函數
#用於擴展基本函數的函數
def kuozhan(func):
#內部函數(擴展之後的la函數)
def newla():
#擴展功能1
print('la前參拜祈求')
#調用基本函數
result = func()
#擴展功能2
print('la後還願感謝')
#爲newla添加返回值
return result
#添加返回值(裝飾器用於返回未來的la函數的return)
return newla
#基本函數
@kuozhan #la = kuozhan(la)#擴展之後的函數要重新賦值給基本函數!(但是此步驟還實現不了)
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
return '熱翔'
#print(la)
#調用函數
result = la()
print('函數的返回值爲:',result)
#第六步:帶有收集參數的函數的裝飾器
def kuozhan(func):
#定義內部函數
def newla(*w,**n):
#擴展功能1
print('la前參拜祈求')
#調用基本函數
func(*w,**n)
#擴展功能2
print('la後還願感謝')
#返回未來的la函數
return newla
#基本函數
@kuozhan
def la(*who,**nums):
print('參與la的人有',who)
print('la了多少',nums)
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#調用函數
la('xuyu','wangcheng','xiufeng','zhangbo',xy = '15斤',wc = '15噸',xf = '15克',zb = '15ml')
#第七步:帶有參數的裝飾器
#裝飾器
def outer(arg):
#這是裝飾器代碼
def kuozhan(func):
#print(func)
#未來的la函數
def newla():
# 擴展功能1
print('la前參拜祈求')
# 調用基本函數
func()
# 擴展功能2
print('la後還願感謝')
#未來的chifan函數
def newchifan():
#擴展功能1
print('飯前洗洗手')
#調用基本函數
func()
#擴展功能2:
print('飯後抖一抖')
#根據裝飾的函數不同 返回不同的結果
if arg == 'la':
#返回的未來的la函數
return newla
elif arg == 'chi':
return newchifan
#返回裝飾器
return kuozhan
#基本函數1
@outer('la')#@裝飾器函數
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#基本函數2
@outer('chi')
def chifan():
print('eat meat')
#調用基本函數
la()
chifan()
#第八步:使用類作爲裝飾器參數
#裝飾器使用的操作類
class Wish:
#祈求方法
def before():
print('la前參拜祈求')
#還願方法
def after():
print('la後還願感謝')
def outer(cls):
#裝飾器函數
def kuozhan(func):
def newla():
#擴展1(類中存在擴展內容)
cls.before()
#調用基本函數
func()
#擴展2(類中存在擴展內容)
cls.after()
return newla
return kuozhan
#基本參數
@outer(Wish)#裝飾器
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#調用函數
la()
#第九步:使用類作爲裝飾器
class Kuozhan:
#接受裝飾器函數(函數outer)
def __init__(self,arg):
#此處可以將參數存入對象
self.arg = arg
#製作一個內部函數(真正的裝飾器 函數kuozhan)
def __call__(self,func):
#print(func)
#將func函數存入對象
self.func = func
#返回內部函數
return self.newla
#定義內部函數
def newla(self):
#擴展功能1
print('la前參拜')
#調用基本函數
self.func()
#擴展功能2
print('la後還願')
#基本函數
@Kuozhan('la') #la = 對象(la)
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#調用函數
la()
#第十步:裝飾器來裝飾一個類
#裝飾器函數
def kuozhan(cls):
print(cls)
#聲明一個類(函數)
def newHuman():
#擴展類的功能1
cls.cloth = '衣服'
#擴展功能2
cls.hat = '帽子'
#調用類(實例化對象)
obj = cls()
#返回實例化的對象
return obj
return newHuman
#類 (被裝飾的類)
@kuozhan #Human = kuozhan(Human)
class Human:#當作一個函數處理 Human()的返回值不是對象
#屬性
sex = 'man'
age = 18
#方法
def liaomei(self):
print('妹子,這塊磚頭是你掉的嗎')
def tian(self):
print('kubi')
#實例化對象
result = Human()
print(result)
print(result.cloth)
print(result.hat)
'''
#第十一步
#裝飾器1
def kuozhan1(func):
#定義裝飾之後的函數
def newla1():
#擴展功能1
print('1-----la前參拜')
#調用基本函數
func()
#擴展功能2
print('1-----la後還願')
return newla1
#裝飾器2
def kuozhan2(func):
#定義裝飾之後的函數
def newla2():
#擴展功能1
print('2-----la前tuokuzi')
#調用基本函數
func()
#擴展功能2
print('2-----la後capigu')
return newla2
#基本函數
@kuozhan2
@kuozhan1
def la():
print('腳踏黃河兩岸,手拿機密文件,前面機槍掃射,後面炮火連天')
#調用函數
la()
#方法的分類
class Cat:
#屬性
color = 'orange'
age = 2
sex = '公'
#方法
#非綁定類的方法/對象方法/實例方法
def getFish(self):
print(self)
print('抓魚方法')
#綁定類的方法
def say():
print('喵喵~~~')
#類方法
@classmethod
def run(cls):
print(cls)
print('貓跑不跑直線取決於耗子')
#靜態方法
@staticmethod
def jump():
print('跳起來四腳朝地')
#實例化對象
mimi = Cat()
#對象方法
mimi.getFish()
#綁定類的方法
Cat.say()
#類方法
Cat.run()
抽象類
#抽象類
#具有抽象方法的類就是抽象類
#抽象方法
#沒有方法體的方法就是抽象方法
import abc
class Dog(metaclass = abc.ABCMeta):#指定類的元素 -> 製作類的方法
#屬性
age = 10
sex = '母'
color = '黑色'
#方法
#對象抽象方法
@abc.abstractmethod
def swimming(self):
pass
#靜態抽象方法
@abc.abstractstaticmethod
def eat():
pass
#類抽象方法
@abc.abstractclassmethod
def drink(cls):
pass
#綁定類的方法
@abc.abstractmethod
def run():
pass
#具體的有內容的方法
def say(self):
print('旺旺')
#實例化對象 會報錯
#xiaohei = Dog()
#抽象類的使用
import abc
#conghao (boss)
class User(metaclass = abc.ABCMeta):
#屬性
username = ''
userid = 0
#方法
#添加用戶(mengfei)
@abc.abstractmethod
def add(self,name,pwd):
pass
#刪除用戶(yujiao)
@abc.abstractclassmethod
def dele(cls,uid):
pass
#修改用戶(shengyue)
@abc.abstractstaticmethod
def mod():
pass
#查找用戶(conghao)
def find(self):
print('查找用戶操作')
#文件2(mengfei)
class MFUser(User):
#添加用戶(mengfei)
def add(self,name,pwd):
print('添加用戶操作')
#文件3(yujiao)
class YJUser(MFUser):
#刪除用戶(yujiao)
@classmethod
def dele(cls,uid):
print(uid)
print('刪除用戶操作')
#文件4(shengyue)
class SYUser(YJUser):
#修改用戶(shengyue)
@staticmethod
def mod():
print('修改用戶操作')
#SYUser是真實的類不是抽象類
user = SYUser()
#添加操作
user.add('mengfei','mf')
#刪除操作
SYUser.dele(250)
#修改操作
user.mod()
#查找操作
user.find()
#多態的實現
#1.設計抽象類 定義規則
import abc
class Animal(metaclass = abc.ABCMeta):
#尿
@abc.abstractmethod
def niao(self):
pass
#拉
@abc.abstractmethod
def la(self):
pass
#叫
@abc.abstractmethod
def jiao(self):
pass
#定義小狗類
class Dog(Animal):
#尿
def niao(self):
print('擡起後腿尿')
#拉
def la(self):
print('蹲着拉')
#叫
def jiao(self):
print('汪汪叫')
#定義小貓類
class Cat(Animal):
#尿
def niao(self):
print('蹲着尿')
#拉
def la(self):
print('蹲着拉')
#叫
def jiao(self):
print('喵喵叫')
#定義小雞類
class Chick(Animal):
#尿
def niao(self):
print('站着尿')
#拉
def la(self):
print('站着拉')
#叫
def jiao(self):
print('嗷嗷叫')
#動物行爲類
class Action():
#定義初始化方法
def __init__(self,animal):
#將動物存入對象成員
self.animal = animal
#尿
def niao(self):
self.animal.niao()
#拉
def la(self):
self.animal.la()
#叫
def jiao(self):
self.animal.jiao()
#實例化小狗
xiaohei = Dog()
#實例化小貓
miaomiao = Cat()
#實例化小雞
huahua = Chick()
#實例化行爲類對象
a = Action(xiaohei)
#調用行爲對象的方法
a.niao()
a.jiao()
a.la()
#改變行爲類對象中的動物
a.animal = miaomiao
#調用行爲對象的方法
a.niao()
a.jiao()
a.la
#改變行爲類對象中的動物
a.animal = huahua
#調用行爲對象的方法
a.niao()
a.jiao()
a.la()
```