欢迎来到JIA的博客

我的python学习之路-装饰器/property/反射

本节内容:

  一、装饰器

    1.1 装饰器的原型

    1.2 @语法糖的使用

    1.3 装饰器的嵌套

    1.4  带有参数的装饰器

    1.5 带有函数返回值的装饰器

    1.6 类装饰器

    1.7 带有参数的装饰器

    1.8 带有参数的类装饰器

   二、类中的方法

    2.1 类中方法的分类

  三、property

    3.1 应用方式1

    3.2 应用方式2

  四、反射

    1、反射类中对象的成员

      4.1.1 hasattr()

      4.1.2 getattr()

      4.1.3 setattr()

      4.1.4 delattr()

    2、反射模块中的属性

 

 

一、装饰器

1. 装饰器的原型

def kuozhan(_func):
    def newfunc():
        print("有房有车的身份:")
        _func()
        print("到处张扬:")
    return newfunc
    
def func():
    print("我是高富帅")
    
func=kuozhan(func)
func()

2 @语法糖的使用

@符的作用:
(1)自动把@装饰器下面的函数当成参数传递给装饰器
(2)将装饰器返回给新的函数替换旧函数,完成拓展功能

def kuozhan(_func):
    def newfunc():
        print("美丽善良")
        _func()
        print("妆容精致")
        
    return newfunc
    
@kuozhan
def func():
    print("我是白富美")
    
print("------------------")    
func()    # newfunc func = kuozhan(func)= newfunc

3.装饰器的嵌套

def kuozhan1(_func):
    def newfunc():
        print("西装革履1")
        _func()
        print("皮鞋锃亮2")
    return newfunc
    
def kuozhan2(_func):
    def newfunc():
        print("美丽善良3")
        _func()
        print("妆容精致4")
    return newfunc

@kuozhan2
@kuozhan1
def func():
    print("我是屌丝.....5")

func() ## 31524

4. 带有参数的装饰器

原函数有几个参数,新函数就有几个参数;

def kuozhan(_func):
    def newfunc(who,where,do):
        print("结婚之前,一日三餐")
        _func(who,where,do)
        print("结婚之后,一日8碗大米饭,为了家庭,日渐消瘦")
    return newfunc

@kuozhan
def func(who,where,do):
    print("{}在{}吃{}".format(who,where,do))
    
func("李雅琪","电影院","榴莲")
#结婚之前,一日三餐
#李雅琪在电影院吃榴莲
#结婚之后,一日8碗大米饭,为了家庭,日渐消瘦

5、带有函数返回值的装饰器

参数与返回值与原函数保持一致

 1 def kuozhan(_func):
 2     def func(*args,**kwargs):
 3         print("下面是一线城市建筑介绍")
 4         lst=_func(*args,**kwargs)
 5         print("介绍完毕")
 6         return lst
 7     return func
 8 
 9 
10 @kuozhan
11 def func(*args,**kwargs):
12     strvar=""
13     dic={"bj":"北京","sh":"上海","gz":"广州","sz":"深圳"}
14     lst=[]
15     i=0
16     for k,v in kwargs.items():
17         if k=="bj":
18             strvar=dic[k]+"的地标建筑是"+v+""+args[i]
19         elif k=="sh":
20             strvar=dic[k]+"的地标建筑是"+v+""+args[i]
21         elif k=="gz":
22             strvar=dic[k]+"的地标建筑是"+v+""+args[i]
23         elif k=="sz":
24             strvar=dic[k]+"的地标建筑是"+v+"坐落在"+args[i]
25         else:
26             strvar=k+"查无此出"
27         i+=1
28         lst.append(strvar)
29     return lst
30         
31     
32 res=func("皇帝的宫殿","电视信号塔","中国第一","深圳河",bj="故宫",sh="明珠塔",gz="广州塔",sz="地王大厦")
33 
34 print(res)
View Code

6、类装饰器

 1 class KuoZhan():
 2     def kuozhan(_func):
 3         def newfunc():
 4             print("没有女朋友之前 .. 快乐的,无拘无束的,拖拖拉拉,很颓废,很狼狈,很自恋")
 5             _func()
 6             print("有女朋友之后....很怕黑,爱自拍,换个iphone18,照片都是他")
 7         return  newfunc
 8     
 9     def __call__(self,_func):
10         return self.kuozhan1(_func)
11 
12     
13     def kuozhan1(delf,_func):
14         def newfunc():
15             print("没有女朋友之前 .. 快乐的,无拘无束的,拖拖拉拉,很颓废,很狼狈,很自恋")
16             _func()
17             print("有女朋友之后....很怕黑,爱自拍,换个iphone18,照片都是他")
18         return  newfunc
19     
20         
21 ### 方法一
22 @KuoZhan.kuozhan
23 def func():
24     print("单身进行时....")
25 
26 func()
27 
28 ### 方法二
29 @KuoZhan()
30 def func():
31     print("单身进行时....")
32 
33 func()
View Code

@KuoZhan() 先去执行KuoZhan() 返回对象之后,使用@符发动技能
obj = 类() # 实例化对象

@obj
def func():
  pass

@符发送技能
  (1) 把func当成参数传递给obj => obj(func)
  (2) 把返回的新函数替换旧函数

把对象当成函数调用时,自动触发魔术方法__call__

7、带有参数的装饰器

 1 def outer(num):
 2     def kuozhan(_func):
 3         def newfunc1(self):
 4             print("厕所前,蓬头垢面")
 5             _func(self)
 6             print("厕所后,光彩亮丽")
 7         def newfunc2(self):
 8             print("游戏前,疯狂送人头")
 9             _func(self)
10             print("游戏后,大杀特杀..")
11         if num ==1:
12             return newfunc1
13         elif num ==2:
14             return newfunc1
15         elif num==3:
16             return "我是最强王者"
17     return kuozhan
18     
19 class MyClass():
20     @outer(1)
21     def func1(self):
22         print("上厕所,来也匆匆,去也匆匆")
23     @outer(2)
24     def func2(self):
25         print("上厕所,上前一小步,文明一大步")
26     @outer(3)
27     def func3(self):
28         print("尿不到坑里,说明你短")
29 
30         
31 obj =MyClass()
32 obj.func1()
33 obj.func1()
34 ##把方法变属性
35 print(obj.func3)
View Code

8 、带有参数类装饰器

1.当参数为1时,为MyClass 添加属性和方法
2.当参数为2时,为MyClass 中的run方法变成属性

 1 class KuoZhan():
 2     ad="程序员,我们不生产代码,我们只做代码的搬运工"
 3     def money(self):
 4         print("程序员,基本工资12000,一行代码一块钱")
 5     def __init__(self,num):
 6         self.num = num
 7     def __call__(self,cls):
 8         if self.num==1:
 9             return self.kuozhan1(cls)
10         elif self.num==2:
11             return self.kuozhan2(cls)
12     def kuozhan1(self,cls):
13         def newfunc():
14             cls.ad=self.ad
15             cls.money=self.money
16             return cls()
17         return newfunc
18     def kuozhan2(self,cls):
19         def newfunc():
20             if "run" in cls.__dict__:
21                 cls.run=cls.run()                
22                 return cls()
23         
24         return newfunc
25 
26 @KuoZhan(1)
27 class  MyClass():
28     def run():
29         return "亢龙有悔"
30 
31 obj =MyClass()
32 print(obj.ad)
33 obj.money()
34 
35 @KuoZhan(2)
36 class  MyClass():
37     def run():
38         return "亢龙有悔"
39 
40 
41 obj =MyClass()
42 print(obj.run)
View Code

 

二、类中的方法

1、类中的方法的分类

  1. 无参方法:类中的无参方法只能用类来调用
  2. 绑定方法:(1) 绑定到对象,对象调用类中成员方法时,自动传递对象参数
  3. 绑定方法 (2) 绑定到类,对象或者类调用类中的成员方法时,自动传递类参数
  4. 静态方法:无论对象还是参数,系统都不会传递任何参数
 1 class Cat():
 2     ###无参方法:类中的无参方法只能用类来调用
 3     def patree():
 4         print("小猫会爬树")
 5     ### 绑定方法:(1) 绑定到对象,对象调用类中成员方法时,自动传递对象参数
 6     def eatfish(self):
 7         print("小猫喜欢吃鱼")
 8     ### 绑定方法 (2) 绑定到类,对象或者类调用类中的成员方法时,自动传递类参数
 9     @classmethod
10     def sleep(cls):
11         print(cls,type(cls))
12         print("小猫爱睡觉")
13     ## 静态方法:无论对象还是参数,系统都不会传递任何参数
14     @staticmethod
15     def zhualaoshu():
16         print("小猫爱抓老鼠")
17     
18 
19 obj = Cat()
20 
21 ## 无参方法
22 # obj.patree() # error
23 Cat.patree()
24 
25 ###绑定方法: 绑定到对象
26 obj.eatfish()
27 Cat.eatfish(obj)
28 
29 ###绑定方法: 绑定到类
30 obj.sleep() # print(obj.__class__)
31 Cat.sleep() # 推荐
32 
33 ## 静态方法
34 obj.zhualaoshu()
35 Cat.zhualaoshu()
View Code

 

三、property

作用:可以把方法变成属性,动态的控制了该属性的获取,设置,删除三个操作

获取属性时自动触发装饰器@property
设置属性时自动触发装饰器@username.setter
删除属性时自动触发装饰器@username.deleter

要求:使用username时,获取 设置 删除 函数名必须一致
在函数中去做相应操作

1、应用方式1

 1 class MyClass():
 2     def __init__(self,name):
 3         self.name = name
 4 
 5     @property
 6     def username(self):
 7         return self.name
 8     
 9     @username.setter
10     def username(self,val):
11         self.name=val
12         
13     @username.deleter
14     def username(self):
15         pass
16         # del self.name
17             
18         
19 obj = MyClass("张银")
20 
21 # 获取元素
22 print(obj.username)
23 
24 # 设置元素
25 obj.username="家营和"
26 print(obj.name)
27 print(obj.username)
28 
29 ## 删除元素
30 del obj.username
31 print(obj.username)
View Code

2、应用方式2

 1 class MyClass():
 2     def __init__(self,name):
 3         self.name=name
 4     ## 获取元素
 5     def get_username(self):
 6         return self.name
 7         
 8     ## 设置元素
 9     def set_username(self,val):
10         self.name=val
11         
12     ## 删除元素    
13     
14     def del_username(self):
15         del self.name
16     
17     #顺序必须按照:获取方法 -> 设置方法 ->删除方法
18     username= property( get_username,set_username,del_username)    
19         
20     
21 # 实例化对象 
22 obj = MyClass("黄常见")
23 print(obj.name)
24 
25 ### 获取元素username 触发 get_username方法
26 print(obj.username)
27 
28 ### 设置成员usern 触发set_username方法
29 obj.username ="耿泽师"
30 print(obj.username)
31 
32 ### 删除成员username 触发del_username
33 del obj.username
34 # print(obj.username)
View Code

 

四、反射

概念: 通过字符串去操作类对象 或者 模块中的属性方法

1、反射类中对象的成员

class Children():
    age=1
    def __init__(self,name):
        self.name=name
        
    def skin(self):
        print("孩子皮肤的颜色取决于人的父母")
    def eye(self):
        print("小孩眼睛的颜色是血轮眼")
    def weight(self):
        print("小孩的体重不超过一百斤")
    def __eat(self):
        print("小孩只能喝奶")
        
obj= Children("小明")

1)、hasattr() 检测对象/类是否有指定的成员

 判断的依据:查看是否可以被调用,返回True与False

res = hasattr(obj,"name")
res  = hasattr(obj,"skin")
print(res)
res = hasattr(Children,"name") # False
res =hasattr(Children,"skin") # True
print(res)

(2) getattr() 获取对象/类成员的值

res = getattr(obj,"name")
##getattr(类/对象,成员.'默认值防止报错')
res = getattr(obj,"name11","设置友好提示,防止报错")
print(res)
## 通过类来反射[反射出来的是普通函数]
func= getattr(Children,"skin")
print(func,type(func))
func(obj)
### 通过对象反射[反射出来的是绑定方法]
func= getattr(obj,"skin")
print(func,type(func))
func()

(3)setattr() 设置对象/类成员的值

setattr(obj,"sex","男性")
print(obj.sex)

setattr(Children,"school","清华大学")
print(obj.school)
print(Children.school)


setattr(Children,"school", lambda self :print("名牌大学"))
obj.school()
Children.school(obj)

# setattr(obj,"school", lambda :print("名牌大学1"))
# obj.school()

(4) delattr() 删除类/对象的值

delattr(Children,"school")
# obj.school()
delattr(obj,"name")
# print(obj.name)

小例子 : 通过字符串操作对象/类中的成员

strvar= input("请告诉我,你想要调用的方法是:")
if hasattr(obj,strvar):
    func= getattr(obj,strvar)
    func()
    
else:
    print("抱歉 该方法不存在")

 

2、反射模块中的成员

import sys
""" sys.modules 返回的是系统的模块字典"""
# print(sys.modules)
""" 通过__main__ 字典的键,获取的是当前文件的模块对象"""
# print(sys.modules["__main__"])
modules = sys.modules["__main__"]
print(modules)

def func1():
    print("我是func1")
def func2():
    print("我是func2")
def func3():
    print("我是func3")

## 反射模块成员的小例子

while True:
    func_name = input("请输入你要使用的方法名>>>")
    if hasattr(modules,func_name):
        func = getattr(modules,func_name)
        func()
    elif func_name.upper()=="Q":
        break        
    else:
        print("没有该方法")

 

posted @ 2020-12-24 17:41  讷言敏行~  阅读(159)  评论(0编辑  收藏  举报