反射,装饰器,类当中的方法,property---day24
1.反射
# ### 反射(针对于类对象 模块)
'''概念:通过字符串去操作类对象或者模块当中的成员(属性方法)''' class Man():
pass class Woman():
pass class Children(Man,Woman):
'''
成员属性:eye
成员方法:skylight moonread __makebaby
完成的功能:描述小孩天生神力
'''
eye = "血轮眼" def skylight(self):
print("一下生,直接使用天照,让世界变得混乱") def moonread(self,func):
print("一下生,使出了武功绝学,月度,世界都黑暗了")
print(func.__name__,type(func.__name__)) def __makebaby(self):
print("这一手招数,只能我自己用")
obj = Children() #(1) 反射类对象中的成员
# hasattr() 检测对象/类是否有指定的成员
#对象
res = hasattr(obj,"eye")
print(res) #True #类
res = hasattr(Children,"skylight") #True
res = hasattr(Children,"__makebaby") #False
print(res) # getattr() 获取对象/类成员的值
#对象
func = getattr(obj,"skylight")
func = getattr(obj,"__makebaby") #报错
func() # =>skylight() 通过对象反射出来的方法是绑定方法 #类
func = getattr(Children,"skylight")
func(1) #通过类反射出来的是一个普通方法 #当类对象中的成员不存在时,可以设置默认值(第三个参数是默认参数)
func = getattr(obj,"moonread123","对不起,该成员不存在")
print(func) #综合案例
'''
strvar = input("请输入你要调用的方法")
if hasattr(obj,strvar): #判断obj对象是否有这个属性
func = getattr(obj,strvar) #获取对象的这个属性
func()
''' #setattr() 设置对象/类成员的值
#对象
setattr(obj,"eye","白眼")
print(obj.eye)
#类
setattr(Children,"tcut",lambda : print("小孩一下生就能使用雷切"))
Children.tcut()
#obj.tcut() #tcut是一个无参普通方法,只能类调用 #delattr() 删除对象/类成员的值 #对象
delattr(obj,"eye")
print(obj.eye) #类
delattr(Children,'eye')
print(Children.eye) #(2)反射模块中的成员
'''sys.modules返回一个系统的字典,加载系统模块展现出来'''
import sys
print(sys.modules) #获取本模块的对象
print(sys.modules["__main__"])
selfmodule = sys.modules["__main__"] def func1():
print("我是func1方法") def func2():
print("我是func2方法") def func3():
print("我是func3方法") #综合案例
while True:
strvar = input("请输入你要反射的方法")
if hasattr(selfmodule,strvar)
func = getattr(selfmodule,strvar)
func()
elif strvar.upper() == "Q":
break
else:
print("没有这个方法")
2.装饰器
# ### 装饰器
'''
装饰器:为原函数扩展新功能,用新功能去替代旧功能
作用:在不改变原有代码的基础上,实现功能上的扩展
符号:@(语法糖)
''' # 1.装饰器的基本使用
def outer(f):# f = func
def inner():
print("测试前")
f()
print("测试后")
return inner
def func():
print("我叫高富帅") func = outer(func)
func() #func() = inner() #2. @符号的使用
'''
@符号使用:
(1)可以自动把@符号下面的函数当成参数传递给装饰器
(2)把新函数进行返回,让新函数去替换旧函数,以实现功能的扩展
# func = inner <==> func() = inner()
'''
def outer(f): #f = func
def inner():
print("测试前")
f() #真正执行函数的调用 =func
print("测试后")
return inner
@outer #先调用outer,并把下面函数名传给参数f,即func = outer(func)
def func(): #被调用的真正函数
print("我叫高富帅") func() #func() = inner() #3.装饰器的嵌套
def outer1(f):
def inner():
print("测试前1")
f()
print("测试后2")
return inner def outer2(f):
def inner():
print("测试前3")
f()
print("测试后4")
return inner
@outer2 #3 1 5 2 4
@outer1 #调用outer1并把func传给f 1 5 2
def func():
print("我是白富美5")
func() #31524
'''
解析
1.调用outer1并把func传给f,返回inner,执行func()想当于执行inner()
outer1的打印顺序为 1 5 2
2.然后再调用outer2把func传给f,返回inner,执行func()想当于执行inner()
outer2的打印顺序为3 1 5 2 4
''' #4.用装饰器修饰带有参数的函数
'''拓展的新功能和原函数的功能,在参数和返回值上,要保持一致性'''
def outer(f):
def inner(who,where):
print("测试前")
f(who,where)
print("测试后")
return inner
@outer # func = outer(func)
def func(who,where):
print("{who}在{where}吃饭".format(who=who,where=where)) func("小白","餐厅") #5.用装饰器修饰带有参数返回值的函数
def outer(f):
def inner(*args,**kwargs): # 函数的定义处, *号的打包操作
print("测试前")
res = f(*args,**kwargs) # 函数的调用处,*号解包操作
print("测试后")
return res
return inner @outer #func = outer(func)
def func(*args,**kwargs):
dic = {"wz":"王振","xb":"小白","ww":"伟伟"}
lst = []
strvar = "" #遍历玩耍的地点
for i in args:
print("玩耍的地点",i)
#print(args)
#print(kwargs)
'''
正常写法
for k,v in kwargs.items():
if k in dic:
strvar = dic[k] + "留下" + v + "黄金"
lst.append(strvar)
return lst
'''
#推导式
return [dic[k] + "留下" + v + "黄金" for k,v in kwargs.items() if k in dic]
#谁留下多少黄金
res = func("电影院",'水里',wz="18斤",xb="18吨",ww="18克",zzz = "19k")
print(res) #6. 用装饰器来拓展原函数
class outer():
def __call__(self,func): #第二步 #触发call方法,把func传给func
return self.outer1(func) #第三步 #调用outer1并把func传给func def outer1(self,func): #第四步
def inner(): #第七步 #执行第六步相当于执行这一步func()=inner()
print("测试前1") #第八步 打印
func() #第九步 #真正函数调用打印测试进行时
print("测试后2") #第十二步
return inner #第五步 #func = inner def outer2(func):
def inner():
print("测试前3")
func() #真正函数调用打印测试进行时
print("测试后4")
return inner
#方法一
'''
@outer.outer2 outer(func).outer2
def func():
print("测试进行时...")
func()
''' #方法二
'''
@outer() => @obj<=>对象 => obj(func) <=>把对象当成函数进行使用了,自动触发__call__魔术方法
把新函数inner返回了 => @发动第二个既能,将新函数去替换旧函数,func = inner
func() = inner() def func():
print("测试进行时...")
func()
'''
@outer() #第一步 #outer() = > obj对象,然后@obj => func = obj(func),把obj对象当做函数调用会自动触发call方法
def func(): #第十步 执行第九步 就相当于执行真正的函数调用
print("测试进行时") #第十一步
func() #第六步 func() = inner() #7. 带有参数的函数装饰器
def outer(num):
def kuozhan(func): #第二步 #func = func1
def inner1(self): #第五步 调用func1相当于调inner1
print("测试前1")#第六步
res = func(self) #第七步
print("测试后2") #第十步
return res def inner2(self):
print("测试前3")
res = func(self)
print("测试后4")
return res if num == 1:
return inner1 #第三步 #func1 = inner1
elif num == 2:
return inner2
elif num == 3:
#把方法变成属性
return "我是男性"
return kuozhan class MyClass():
@outer(1)#第一步 outer(1)=>返回kuozhan,@kuozhan=> func1=kuozhan(func1)[@符号第一次发动技能] <=> func2 = newfunc2 [@符号第二次发动技能]
def func1(self): #第八步,第七步执行的真正函数是这个
print("试一试") #第九步 @outer(2)#outer(2)=>返回kuozhan ,@kuozhan <==> func2=kuozhan(func2) [@符号第一次发动技能] <=> func2 = newfunc2 [@符号第二次发动技能]
def func2(self):
print("拼一拼") @outer(3)
def func3():# outer(3)=>kuozhan , @kuozhan <=> func3=kuozhan(func3) [@符号第一次发动技能] <=> func3 = "我是男性"
print("搏一搏")
obj = MyClass()
obj.func1() #第四步
obj.func2() #func2() <==> newfunc2()
#把方法变成属性
print(obj.func3) #func3=kuozhan(func3) => func3 = "我是男性" #8.带有参数的类装饰器
'''
如果参数是1,就为当前类添加成员属性和方法
如果参数是2,就把原方法run变成属性
'''
class outer():
ad = "贵族茅房,每小时100元,贵族茅房,欢迎您来,欢迎您再来"
def __init__(self,num):
self.num = num def __call__(self,cls): #第二步 把MyClass传入 cls接收
if self.num == 1:
return self.inner1(cls) #第三步 执行inner1函数
elif self.num == 2:
return self.inner2(cls) def money(self):
print("茅中贵族,百岁山") #参数为1的情况
def inner1(self,cls): #第四步 cls接收MyClass
def inner(): #第七步
#为当前cls这个类,添加属性(为MyClass)
cls.ad = outer.ad #第八步
#为当前cls这个类,添加方法(为MyClass)
cls.money = outer.money #第九步
return cls() #第十步 #对象obj = cls()
return inner # 第五步 返回 MyClass = inner #参数为2的情况
def inner2(self,cls):
def inner():
if "run" in cls.__dict__:
#调用类中的方法,拿到返回值
res = cls.run()
#把返回值重新赋值给run属性,后者覆盖了前者,方法变成了属性
cls.run = res #再把值赋值给MyClass的run属性
return cls() #返回对象 return inner
#obj = outer(1)
'''
@obj [@符号第一次发动技能] <==>obj(MyClass) 把对象当成函数使用了,触发__call__魔术方法
self.inner1(cls) <==> return inner
<==> [@符号第二次发动技能] 将新函数替换旧函数 MyClass = inner
obj = MyClass() <==> inner() => cls() => obj对象 情况一
@outer(1) #第一步 @obj => MyClass = obj(MyClass) 对象obj当成函数调用触发call方法
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass() #第六步 MyClass() = inner() = cls()
print(obj.ad) #第十一步
obj.money()
''' '''
@obj [@符号第一次发动技能] <==> obj(MyClass) 把对象当成函数使用了,触发__call__魔术方法
self.inner2(cls) <==> return inner
<==> [@符号第二次发动技能] 将新函数替换旧函数 MyClass = inner
obj = MyClass() <==> inner() => cls() => obj对象
'''
#情况二
@outer(2) # outer(2) => obj对象,@obj => MyClass = obj(MyClass),obj(MyClass) 把对象当成函数使用了,触发__call__魔术方法
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass() # MyClass() => inner()返回cls() => obj
print(obj.run) #亢龙有悔 '''
obj = MyClass()的解释
#第一部分 定义一个类
class Ceshi():
c = 100
obj = Ceshi()
print(obj.c) #第二部分,定义两个函数
def func22():
print(111) def func(cls):
cls.aabbcc = 200
obj = cls()
return obj #第三部分,把类当成参数传递给func,类在func函数中形成了一个独立的副本
obj= func(Ceshi) #第四部分,把这个类做替换,变成函数,那么现在在全局空间的Ceshi已经变成了函数,不再是类
Ceshi = func22 #第五部分,调用局部空间obj,还是可以得到原来类中的成员属性和方法
print(obj.c)
print(obj.aabbcc)
'''
3.类当中的方法
# ### 面向对象中的方法
'''
普通方法:可以有参数,或者无参数,当成正常的函数调用
绑定方法:(1)绑定到对象(自动传递参数为对象)(2)绑定到类(自动传递参数为类)
静态方法:无论是对象还是类,都可以调用,默认不用传递任何参数
''' class Dog():
name = "旺财" #普通方法
def jiao():
print("小狗哇哇哇的叫唤") #绑定方法(对象)
def eat(self):
print("小狗喜欢吃骨头") #绑定方法(类) 类方法
@classmethod
def tail(cls):
print(cls)
print("小狗看到主人喜欢摇尾巴") #静态方法
@staticmethod
def jump(num):
print("小狗喜欢接飞盘")
obj = Dog()
#普通方法(无参方法只能类调用)
#obj.jiao() error
Dog.jiao() #绑定self方法(一般用对象调用)
obj.eat() #推荐
Dog.eat(123) #类调用绑定方法 不推荐 #绑定类方法(classmethod类的专属方法推荐用类调用)
'''系统自己把类当成参数进行传递'''
Dog.tail() #类调用方法 推荐
obj.tail() #静态方法(staticmethod不会默认传递任何参数,如果有参数,当成普通方法调用自己)
obj.jump(1)
Dog.jump(2) ### 在类外,为对象添加成员方法,默认皆是静态方法
obj.func = lambda : print(123)
obj.func()
4.property装饰器
# ### property
'''
property 可以把方法变成属性使用
作用:控制属性的获取 设置 删除操作
变相的增加成员的安全性,可以通过自定义逻辑对成员进行控制 自动触发:要求是同一个名字
获取 @property
设置@属性名.setter
删除@属性名.deleter
''' #方法一
class MyClass():
def __init__(self,name):
self.name = name @property
def username(self):
return self.name
#pass @username.setter
def username(self,val):
print(2131231)
val = "朴仁猛"
self.name = val @username.deleter
def username(self):
#如果发现有删除行为,可以在这个方法中拒绝删除
#pass
del self.name
obj = MyClass("小芳") #获取属性(自动触发获取方法@property)
#print(obj.username())#TypeError: 'str' object is not callable
print(obj.username) #把方法当做属性 #设置属性(自动触发设置方法)val形参自动接收设置的值
obj.username = "朴仁猛"
print(obj.username) #删除属性
del obj.username
#print(obj.username) error #方法二
class MyClass():
def __init__(self,name):
self.name = name #获取
def get_username(self):
return self.name #设置
def set_username(self,val):
# val = "朴仁猛"
self.name = val #删除
def del_username(self):
#如果发现有删除行为,可以在这个方法中拒绝删除
del self.name #顺序必须按照 获取 ->设置 ->删除的参数进行传递
username = property(get_username,set_username,del_username) obj = MyClass("朴飘乐")
#获取
print(obj.username)
#设置
obj.username = "朴一辈"
print(obj.username)
#删除
del obj.username
print(obj.username) #error 被删掉了
总结:
今天主要讲了反射 装饰器,类当中的方法普通方法,类方法,静态方法,property装饰
反射就是通过字符串去操作对象或者模块中的成员(属性或者方法)
可以反射类或者对象中的成员
主要有
hasattr 检测类或者对象中是否有该成员 返回True或者False
getattr 获取类或者对象中的成员 存在则获取到,不存在则报错,可以设置第三个参数防止报错
setattr 设置类或者对象成员的值
delattr 删除类或者对象成员 装饰器函数
为原函数拓展新功能,用新功能去替代旧功能
作用:在不改变原有代码的基础上,实现功能上的拓展
符号:@符号
@符号的作用
自动把@符号下面的函数当成参数传递给装饰器
把新函数进行返回,让新函数去替换旧函数,以实现功能的拓展 装饰器的嵌套
用装饰器修饰带有参数的函数
用装饰器修饰带有参数返回值的函数
装饰器拓展原函数
带有参数的函数装饰器
带有参数的类装饰器 面向对象中的方法
普通方法:可以有参数,或者无参数,当成正常的函数调用
绑定方法:绑定到对象(自动传递参数为对象)self方法(2)绑定到类(自动传递参数为类)类方法,需要用@classmethod装饰,参数至少为一个cls
静态方法:@staticmethod 无论对象还是类,都可以调用,默认不用传递任何参数 property装饰器
可以把方法变成属性使用
作用控制属性的获取 设置 删除操作
变相的增加成员的安全性,可以通过自定义逻辑对成员进行控制 自动触发的时候,要求是用一个名字
获取 @property
设置 @属性名.setter
删除 @属性名.deleter
反射,装饰器,类当中的方法,property---day24的更多相关文章
- day26:装饰器&面向对象当中的方法&property
目录 1.装饰器 1.1 装饰器的基本用法 1.2 @符号的使用 1.3 装饰器的嵌套 1.4 用装饰器扩展带有参数的原函数 1.5 用装饰器扩展带有参数和返回值的原函数 1.6 用类装饰器扩展原函数 ...
- day20-Python运维开发基础(装饰器 / 类中的方法 / 类的方法变属性)
1. 装饰器 / 类中的方法 / 类的方法变属性 # ### 装饰器 """ 定义:装饰器用于拓展原来函数功能的一种语法,返回新函数替换旧函数 优点:在不更改原函数代码的 ...
- 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解
第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一. 引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...
- Python使用property函数和使用@property装饰器定义属性访问方法的异同点分析
Python使用property函数和使用@property装饰器都能定义属性的get.set及delete的访问方法,他们的相同点主要如下三点: 1.定义这些方法后,代码中对相关属性的访问实际上都会 ...
- [转载]Python使用@property装饰器--getter和setter方法变成属性
原贴:为什么Python不需要getter和setter getter 和 setter在java中被广泛使用.一个好的java编程准则为:将所有属性设置为私有的,同时为属性写getter和sette ...
- 第7.27节 Python案例详解: @property装饰器定义属性访问方法getter、setter、deleter
上节详细介绍了利用@property装饰器定义属性的语法,本节通过具体案例来进一步说明. 一. 案例说明 本节的案例是定义Rectangle(长方形)类,为了说明问题,除构造函数外,其他方法都只 ...
- django class类即视图类添加装饰器的几种方法
根据别人发布整理,个人爱好收集(原文:https://blog.csdn.net/mydistance/article/details/83958655 ) 第一种:定义函数装饰器,在函数,类中使用函 ...
- java反射 顺序输出类中的方法
java反射可以获取一个类中的所有方法,但是这些方法的输出顺序,并非代码的编写顺序. 我们可以通过自定义一个注解来实现顺序输出类中的方法. 首先,先写一个类,定义增删改查4个方法 public cla ...
- python_如何定义装饰器类?
案例: 实现一个能将函数调用信息记录到日志的装饰器 需求: 把每次函数的调用时间,执行时间,调用次数写入日志 可以对被装饰函数分组,调用信息记录到不同日志 动态修改参数,比如日志格式 动态打开关闭日志 ...
- python locust_TaskSet声明任务的典型方法是使用task装饰器的两种方法
为TaskSet声明任务的典型方法是使用task装饰器.该min_wait和MAX_WAIT属性也可以在使用taskset类中重写. from locust import Locust, TaskSe ...
随机推荐
- [转帖]Linux性能分析:理解系统平均负载
Linux系统中,平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数.它不仅包括了正在使用CPU的进程,也包括处于不可打断的睡眠状态的进程-它们是在等待其它系统资源如磁盘 I/O 等的进程. ...
- [转帖]CentOS 7 下用 firewall-cmd / iptables 实现 NAT 转发供内网服务器联网
https://www.cnblogs.com/hope250/p/8033818.html 自从用 HAProxy 对服务器做了负载均衡以后,感觉后端服务器真的没必要再配置并占用公网IP资源.而且由 ...
- [转帖]Linux中最全shell命令&常用注意事项
在编辑linux脚本中不断的会用到复杂的脚本编辑,写文章记录. Linux命令大全(手册) – 真正好用的Linux命令在线查询网站 目录 推荐书籍: Linux常用命令 Linux 常用命令 在li ...
- [转帖]016 Linux 卧槽,看懂进程信息也不难嘛?top、ps
016 Linux 卧槽,看懂进程信息也不难嘛?top.pshttps://my.oschina.net/u/3113381/blog/5455267 1 扒开看看 top 命令参数详情 Linux ...
- [转帖]2022年 SRE、DevOps技能图谱
https://zhuanlan.zhihu.com/p/568752990 在过去一段时间,我面试过一些 DevOps 相关从业者,并且曾经收到过一些知乎小伙伴的提问,针对于 DevOps 以及相关 ...
- vue动画进入-完整的动画/有进入离开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 学到一个编码技巧:用重复写入代替if判断,减少程序分支
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 近期阅读了rust标准库的hashbrown库(也就是一个 ...
- python安装与python、pip的环境变量配置
进入官网 在你常用的搜索引擎中输入 python官网 然后进入. 可直接点击本链接 python官网进入: 也可在浏览器地址栏输入www.python.org回车进入官网. 下载 将鼠标放到菜单栏中的 ...
- Apache Typecho框架启用地址重写
地址重写有利于SEO优化,开启地址重写可以去掉Typecho框架中的index.php后缀,该后缀如下. 第一步,进到apache配置文件目录下cat /etc/httpd/conf/httpd.co ...
- pymysql基本使用规则
1.执行SQL #!/usr/bin/env python # -*- coding:utf-8 -*- import pymysql # 创建连接 conn = pymysql.connect(ho ...