Python 裝飾器、抽象類

一、裝飾器的執行

裝飾器本質就是函數,功能是爲其他函數添加附加功能。
實現原則:
不修改被修飾函數的源代碼。
不修改被修飾函數的調用方法。

 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()
```
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章