python_learn 装饰器

# ### 反射 (针对于类对象,模块)
"""概念: 通过字符串去操作类对象 或者 模块当中的成员(属性方法)"""


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) 反射类对象中的成员
# hasattr() 检测对象/类是否有指定的成员
# 对象
res = hasattr(obj, "eye")
print(res)

# 类
res = hasattr(Children, "skylight")
res = hasattr(Children, "__makebaby")
print(res)

# getattr() 获取对象/类成员的值
# 对象
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()
"""

# 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(obj.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("没有这个方法")

# ### 装饰器
"""
装饰器: 为原函数扩展新功能,用新功能去替代旧功能
作用  : 在不改变原有代码的基础上,实现功能上的扩展
符号  : @(语法糖)
"""

# 1.装饰器的基本用法
def kuozhan(func):
	def newfunc():
		print("厕所前,蓬头垢面")
		func()
		print("厕所后,精神气爽")
	return newfunc

def func():
	print("我叫高富帅")
	
func = kuozhan(func) # func = newfunc  <=>   func() = newfunc()
func()

print("<=================>")
# 2.@符号的使用
"""
@符号作用: 
	(1) 可以自动把@符号下面的函数当成参数传递给装饰器
	(2) 把新函数进行返回,让新函数去替换旧函数,以实现功能的扩展.
	 # func = newfunc  <=>   func() = newfunc()
"""
def kuozhan(func):
	def newfunc():
		print("厕所前,蓬头垢面")
		func()
		print("厕所后,精神气爽")
	return newfunc

@kuozhan
def func():
	print("我叫高富帅")

func() 
print("<=================>")
# 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()

print("<=================>")
# 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("朱胜","电影院")

print("<=================>")
# 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)

print("<=================>")
# 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()

print("<=================>")
# 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)

# TypeError: newfunc1() takes 0 positional arguments but 1 was given
# TypeError: 'NoneType' object is not callable


# 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()


# ### 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(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 被删掉了
			
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值