python学习第24天
一.装饰器
装饰器:为原函数扩展新功能,用新功能去替代旧功能
作用: 在不改变原有代码的基础上,实现功能上的扩展
符号: @(语法糖)
(1) 装饰器的基本用法
def kuozhan(func):
def newfunc():
print("厕所前,蓬头垢面")
func()
print("厕所后,精神气爽")
return newfunc
def func():
print("我叫高富帅")
func = kuozhan(func) # func = newfunc <=> func() = newfunc()
func()
(2)@符号的作用
1)可以自动把@符号下面的函数当成参数传递给装饰器
2)把新函数进行返回,让新函数去替换旧函数,以实现功能的扩展
# func = newfunc <=> func() = newfunc()
def kuozhan(func):
def newfunc():
print("厕所前,蓬头垢面")
func()
print("厕所后,精神气爽")
return newfunc
@kuozhan
def func():
print("我叫高富帅")
func()
(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()
(4)用装饰器修饰带有参数的函数
扩展的新功能和原函数的功能,在参数和返回值上,要保持一致性
def kuozhan(func):
def newfunc(who,where):
print("厕所前,萎靡不振")
func(who,where)
print("厕所后,兽性大发")
return newfunc
@kuozhan
def func(who,where):
print("{who}在{where}解手".format(who=who,where=where))
func("朱胜","电影院")
(5)用装饰器修饰带有参数返回值的函数
def kuozhan(func):
def newfunc(*args,**kwargs): # 函数的定义处, *号的打包操作
print("厕所前,饥肠辘辘")
lst = func(*args,**kwargs) # 函数的调用处,*号解包操作
print("厕所后,酒足饭饱")
return lst
return newfunc
@kuozhan
def func(*args,**kwargs):
dic = {"wz":"王振" , "wyl":"尉翼麟" , "yc":"云超"}
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斤",wyl="18吨",yc="18克",zzz = "19k")
print(res)
(6)用类装饰器来扩展原函数
class Kuozhan():
def __call__(self,func):
return self.kuozhan2(func)
def kuozhan1(func):
def newfunc():
print("厕所前,老实巴交")
func()
print("厕所后,咋咋呼呼")
return newfunc
def kuozhan2(self,func):
def newfunc():
print("厕所前,唯唯诺诺")
func()
print("厕所后,重拳出击")
return newfunc
"""
# 方法一
@Kuozhan.kuozhan1
def func():
print("厕所进行时...")
func()
"""
# 方法二
"""
@Kuozhan() => @obj<=>对象 => obj(func) <=> 把对象当成函数进行使用了,自动触发__call__魔术方法.
=> 把新函数newfunc 返回了 => @ 发动第二个技能,将新函数去替换旧函数, func = newfunc
func() <==> newfunc()
def func():
print("厕所进行时...")
func()
"""
@Kuozhan()
def func():
print("厕所进行时...")
func()
(7)带有参数的函数装饰器
def outer(num):
def kuozhan(func):
def newfunc1(self):
print("厕所前,干净整齐")
res = func(self)
print("厕所后,臭气熏天")
return res
def newfunc2(self):
print("厕所前,饥肠辘辘")
res = func(self)
print("厕所后,满口雌黄")
return res
if num == 1 :
return newfunc1
elif num == 2:
return newfunc2
elif num == 3:
# 把方法变成属性
return "我是男性"
return kuozhan
class MyClass():
@outer(1) # outer(1) => kuozhan , @kuozhan <=> kuozhan(func1) [@符号第一次发动技能] <=> func1 = newfunc1 [@符号第二次发动技能]
def func1(self):
print("先前一小步,文明一大步")
@outer(2) # outer(1) => kuozhan , @kuozhan <=> kuozhan(func2) [@符号第一次发动技能] <=> func2 = newfunc2 [@符号第二次发动技能]
def func2(self):
print("来也匆匆,去也匆匆")
@outer(3) # outer(3) => kuozhan , @kuozhan <=> kuozhan(func3) [@符号第一次发动技能] <=> func3 = "我是男性"
def func3():
print("尿到外面,说明你短!")
obj = MyClass()
obj.func1() # func1 <=> newfunc1
obj.func2()
# 把方法变成属性
print(obj.func3)
(8)带有参数的类装饰器
"""
如果参数是1,就为当前类添加成员属性和方法
如果参数是2,就把原方法run变成属性
"""
class Kuozhan():
ad = "贵族茅房,每小时100元,贵族茅房,欢迎您来,欢迎您再来"
def __init__(self,num):
self.num = num
def __call__(self,cls):
if self.num == 1:
return self.newfunc1(cls)
elif self.num == 2:
return self.newfunc2(cls)
def money(self):
print("茅中贵族,百岁山")
# 参数为1的情况
def newfunc1(self,cls):
def newfunc():
# 为当前cls这个类,添加属性
cls.ad = Kuozhan.ad
# 为当前cls这个类,添加方法
cls.money = Kuozhan.money
return cls() # 对象
return newfunc
# 参数为2的情况
def newfunc2(self,cls):
def newfunc():
if "run" in cls.__dict__:
# 调用类中的方法,拿到返回值
res = cls.run()
# 把返回值重新赋值给run属性.后者覆盖了前者,方法变成了属性
cls.run = res
return cls()
return newfunc
# obj = Kuozhan(1)
"""
# @obj [@符号第一次发动技能] <=> obj(MyClass) 把对象当成函数使用了,触发__call__魔术方法
self.newfunc1(cls) <=> return newfunc
=> [@符号第二次发动技能] 将新函数替换旧函数 MyClass = newfunc
obj = MyClass() <=> newfunc() => cls() => obj对象
"""
# 情况一
"""
@Kuozhan(1)
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass()
print(obj.ad)
obj.money()
"""
print("<=============>")
"""
# @obj [@符号第一次发动技能] <=> obj(MyClass) 把对象当成函数使用了,触发__call__魔术方法
self.newfunc2(cls) <=> return newfunc
=> [@符号第二次发动技能] 将新函数替换旧函数 MyClass = newfunc
obj = MyClass() <=> newfunc() => cls() => obj对象
"""
# 情况二
@Kuozhan(2)
class MyClass():
def run():
return "亢龙有悔"
obj = MyClass()
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)
"""
二.面向对象中的方法
普通方法: 可以有参数,或者无参数,当场正常的函数调用
绑定方法: (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()
# 绑定方法 (一般用对象调用)
obj.eat() #(推荐)
Dog.eat(12356)
# 绑定方法(类)
"""系统自己把类当成参数进行传递"""
Dog.tail() #(推荐)
obj.tail()
# 静态方法 (不会默认传递任何参数,如果有参数,当成普通方法调用即可.)
obj.jump(1)
Dog.jump(2)
### 在类外,为对象添加成员方法,默认皆是静态方法.
obj.func = lambda : print(123)
obj.func()
绑定方法(类) : @classmethod
静态方法: @staticmethod
1.1property装饰器
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(112233)
val = "朴仁猛"
self.name = val
# pass
@username.deleter
def username(self):
# 如果发现有删除行为,可以在这个方法中拒绝删除
pass
#del self.name
obj = MyClass("小芳")
# 获取属性 (自动触发获取方法 @property)
# print(obj.username())
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 被删掉了
三.反射
概念:通过字符串去操作类,对象或者模块当中的成员(属性,方法)
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__ )) # earth_boom
def __makebaby(self):
print("这一手招数,只能我自己用")
obj = Children()
(1)反射类对象中的成员
hasatter() 检测对象/类是否有指定的成员
# 对象
res = hasattr(obj,"eye")
print(res)
# 类
res = hasattr(Children,"skylight")
res = hasattr(Children,"__makebaby")
print(res)
getatter() 获取对象/类成员的值
# 对象
func = getattr(obj,"skylight")
func() # 通过对象反射出来的方法是绑定方法
# 类
func = getattr(Children,"skylight")
func(1) # 通过类反射出来的是一个普通方法
# 当类对象中的成员不存在时,可以设置默认值(第三个参数是默认值参数)
func = getattr(obj,"moonread123345","对不起,该成员不存在")
print(func)
# 综合案例
"""
strvar = input("请输入你要调用的方法")
if hasattr(obj,strvar):
func = getattr(obj,strvar)
func()
"""
setatter() 设置对象/类成员的值
# 对象
setattr(obj,"eye","白眼")
print(obj.eye)
# 类
setattr(Children,"tcut",lambda : print("小孩一下生就能用雷切战术"))
Children.tcut()
# obj.tcut() #tcut 是一个无参普通方法,只能是类来调用;
delatter() 删除对象/类成员的值
# 对象
delattr(obj,"eye")
print(obj.eye)
# 类
delattr(Children,"eye")
# print(obj.eye)
(2)反射模块中的成员
sys.modules 返回一个系统的字典,加载系统模块展现出来
import sys
print(sys.modules)
"""
{
'builtins': <module 'builtins' (built-in)>,
'sys': <module 'sys' (built-in)>,
'_frozen_importlib': <module '_frozen_importlib' (frozen)>,
'_imp': <module '_imp' (built-in)>,
'_warnings': <module '_warnings' (built-in)>,
'_thread': <module '_thread' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 'encodings': <module 'encodings' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\__init__.py'>, 'codecs': <module 'codecs' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\codecs.py'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\aliases.py'>,
'encodings.utf_8': <module 'encodings.utf_8' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\utf_8.py'>, '_signal': <module '_signal' (built-in)>,
'__main__': <module '__main__' from 'E:/python30/day24/1.py'>, 'encodings.latin_1': <module 'encodings.latin_1' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\latin_1.py'>, 'io': <module 'io' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\io.py'>, 'abc': <module 'abc' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\abc.py'>, '_weakrefset': <module '_weakrefset' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_weakrefset.py'>, 'site': <module 'site' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site.py'>, 'os': <module 'os' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\os.py'>, 'errno': <module 'errno' (built-in)>, 'stat': <module 'stat' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\stat.py'>,
'_stat': <module '_stat' (built-in)>, 'ntpath': <module 'ntpath' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\ntpath.py'>, 'genericpath': <module 'genericpath' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\genericpath.py'>, 'os.path': <module 'ntpath' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\ntpath.py'>, '_collections_abc': <module '_collections_abc' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_collections_abc.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_sitebuiltins.py'>, '_bootlocale': <module '_bootlocale' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_bootlocale.py'>, '_locale': <module '_locale' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\gbk.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'sysconfig': <module 'sysconfig' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\sysconfig.py'>,
'encodings.cp437': <module 'encodings.cp437' from 'C:\\Users\\wangwen\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\cp437.py'>}
"""
# 获取本模块的对象
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("没有这个方法")