当前位置:   article > 正文

0807Python总结-装饰器,面向对象当中的方法,property_使用对象作为装饰器

使用对象作为装饰器

一.装饰器

"""
装饰器: 为原函数去扩展新功能,用新函数去替换旧函数
作用: 在不改变原代码的前提下,实现功能上的扩展
符号: @(语法糖)
"""
  • 1
  • 2
  • 3
  • 4
  • 5
1.装饰器的基本用法
def kuozhan(func):
	def newfunc():
		print("厕所前,蓬头垢面")
		func()
		print("厕所后,精神抖擞")
	return newfunc

def func():
	print("我是宋云杰")

func = kuozhan(func)  # func = newfunc
func()  # newfunc()
"""
厕所前,蓬头垢面
我是宋云杰
厕所后,精神抖擞
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
2.@符号的使用

@符号作用:
(1)可以自动把@符号下面的函数当成参数传递给装饰器
(2)把新函数返回,让新函数去替换旧函数,以实现功能上的扩展

def kuozhan(func):
	def newfunc():
		print("厕所前,牛头马面")
		func()
		print("厕所后,黑白无常")
	return newfunc

@kuozhan
def func():
	print("我是高雪峰")
func()  # # 厕所前,牛头马面  我是高雪峰  厕所后,黑白无常
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
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("我是葛龙0")

func()  # 31024
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
4.用装饰器扩展带有参数的原函数
print("===========")
def kuozhan(func):
	def newfunc(who, where):
		print("厕所前,萎靡不振")
		func(who, where)
		print("厕所后,兽性大发")

	return newfunc

@kuozhan
def func(who, where):
	print("{}在{}解手".format(who, where))

func("孙致和","鸟窝")  # func("孙致和","鸟窝") <=> newfunc("孙致和","鸟窝")
"""
厕所前,萎靡不振
孙致和在鸟窝接手
厕所后,兽性大发
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
5.用装饰器扩展带有参数和返回值的原函数
print("==========")
def kuozhan(func):
	def newfunc(*args, **kwargs):
		print("厕所前,饥肠辘辘")
		res = func(*args, **kwargs)
		print("厕所后,酒足饭饱")
		return res
	return newfunc

@kuozhan
def func(*args, **kwargs):
	lst = []
	dic = {"gaoxuefeng": "高雪峰", "sunzhihe": "孙致和", "gelong": "戈隆"}

	# 解手的地点遍历出来
	for i in args:
		print("解手的地点:", i)

	for k, v in kwargs.items():
		if k in dic:
			strvar = dic[k] + "留下了" + v + "黄金"
			lst.append(strvar)
	return lst

lst = func("电影院", "水下", gaoxuefeng = "15g", sunzhihe = "15顿", gelong="15斤")
print(lst)
"""
厕所前,饥肠辘辘
解手的地点: 电影院
解手的地点: 水下
厕所后,酒足饭饱
['高雪峰留下了15g黄金', '孙致和留下了15顿黄金', '戈隆留下了15斤黄金']
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
6.用类装饰器类扩展原函数
print("============")
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)  对象 把@下面的函数当作参数传递给装饰器
def func():
	print("厕所进行中....")
func()
"""
厕所前,唯唯诺诺
厕所进行中....
厕所后,重拳出击
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
"""
代码解析:
print("========分割线1========")
Kuozhan()  # =>obj
def func():
	print("厕所进行中....")
@符第一次发动技能:
	func 当成参数传递给obj => obj(func) 这种形式把对象当成函数使用 -> 直接触发__call__魔术方法
	调用结束之后
@符第二次发动技能:
	将返回的新函数 赋值给 旧函数,形成替换的效果
func = newfunc
func() <=> newfunc()
"""
"""
print("========分割线2========")
<==相当于==>
def func():
	print("厕所进行中....")
obj = Kuozhan()
func = obj(func)
func()
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
7.带有参数的函数装饰器
def outer(num):
	def kuozhan(func):
		def newfunc1(self):
			print("厕所前,干净整齐")
			func(self)
			print("厕所后,一片狼藉")

		def newfunc2(self):
			print("厕所前,大腹便便")
			func(self)
			print("厕所后,满口雌黄")

		if num == 1:
			return newfunc1
		elif num == 2:
			return newfunc2
		elif num == 3:
			# 把func3方法变成属性
			return "我是女性"

	return kuozhan

class MyClass():
	@outer(1)  # => (1) kuozhan(func1) => newfunc1  (2)发动技能做替换 func1 = newfunc1
	def func1(self):
		print("向前一小步,文明一大步")

	@outer(2)  # => (1) kuozhan(func2) => newfunc2  (2)发动技能做替换 func2 = newfunc2
	def func2(self):
		print("来也冲冲,去也冲冲")

	@outer(3)  # => (1) kuozhan(func3) => "我是女性"  (2)发动技能做替换 func3 = "我是女性"
	def func3(self):
		print("尿到外面,说明你短")

obj = MyClass()
print("=============")
obj.func1()  # <=> newfun1
"""
厕所前,干净整齐
向前一小步,文明一大步
厕所后,一片狼藉
"""
print("=============")
obj.func2()
"""
厕所前,大腹便便
来也冲冲,去也冲冲
厕所后,满口雌黄
"""
print("=============")
# obj.func3()  error
print(obj.func3)  # 我是女性
print(MyClass.func3)  # 我是女性
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
"""
代码解析:
套上outer这层函数就是为了保留1 2 3 三个参数,可以在闭包函数中使用
调用outer 结束之后,才是返回正常的装饰器kuozhan
此刻,@符第一次发动技能,
	把func1当成参数传递给kuozhan, 返回newfunc1
然后,@符第二次发动技能,
	将返回的newfunc1替换原来func1
obj.func1() => newfunc1(obj)

if num == 1 返回闭包函数newfunc1
if num == 2 返回闭包函数newfunc2
来做替换
obj.func3 在执行时,装饰器已经把func3变成了属性func3 = "我是女性"
所以obj.fun3 或者 MyClass.func3 都是"我是女性" 字符串
obj.func3 => return "我是女性"
MyClass.func3 => return "我是女性"
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
8.带有参数的类装饰器
"""
如果参数是1,就为当前类添加成员属性和方法
如果参数是2,就把原方法run变成属性
"""
class Kuozhan():
	money = "贵族厕所,每小时1000元,贵族厕所欢迎您来,欢迎您再来"

	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 ad(self):
		print("贵族茅厕,茅厕中的百岁山")

	def newfunc1(self, cls):
		def newfunc():
			# 为当前cls这个类,添加属性
			cls.money = Kuozhan.money
			# 为当前cls这个类,添加方法
			cls.ad = Kuozhan.ad
			return cls()
		return newfunc

	def newfunc2(self, cls):
		def newfunc():
			# 判断run成员是否在类中
			if "run" in cls.__dict__:
				# 调用类中的方法,得到对应的返回值
				res = cls.run()
				# 把返回值重新赋值到run属性上
				cls.run = res  # cls.run = "亢龙有悔"

				return cls()
		return newfunc

print("================")
# 参数1
@Kuozhan(1)
class MyClass():
	def run():
		return "亢龙有悔"
obj = MyClass()
print(obj.money)  # 贵族厕所,每小时1000元,贵族厕所欢迎您来,欢迎您再来
obj.ad()  # 贵族茅厕,茅厕中的百岁山
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
"""
参数为1,代码解析:
@Kuozhan(1) => @obj => @符第一次发动技能
	把MyClass当成参数传递给obj => obj(MyClass) => return self.newfunc1(cls) => return newfunc
		@obj => @符第二次发动技能
	实现替换效果,将MyClass = newfunc
	
obj = MyClass() = newfunc() = cls() = 对象
对象.属性 obj.money
对象.方法 obj.ad()
"""
"""
全局范围内类
class Ceshi():
	ad = 10
obj = Ceshi()
print(obj.ad)

def func(cls):
	cls.money = 100
	return cls()
# 把类当成参数传递到函数当中,在局部空间中,形成独立的副本
obj = func(Ceshi)
# 把类变量Ceshi 变成字符串
Ceshi = "你好"
# 发现局部空间中类对象中的成员,并没有受到影响
print(obj.money)  # 100
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
# 参数2
@Kuozhan(2)
class MyClass():
	def run():
		return "亢龙有悔"

obj = MyClass()
print(obj.run)  # 亢龙有悔
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
"""
参数为2,代码解析:
@Kuozhan(2) => @obj => @符第一次发动技能:
	把MyClass当成参数传递给obj => obj(MyClass) => return self.newfunc2(cls) => return newfunc
		@obj => @符第二次发动技能
	实现替换效果,将MyClass = newfunc

obj = MyClass() = newfunc() = cls() = 对象
对象.run = "亢龙有悔"
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

二.面向对象当中的方法

"""
普通方法: 有参或者无参,如果是无参,只能类来调用
绑定方法: (1) 绑定到对象(字自动传递对象参数) (2) 绑定到类(自动传递类参数)
静态方法: 无论是对象还是类,都可以调用此方法,而不会默认传递任何参数
"""
  • 1
  • 2
  • 3
  • 4
  • 5
class Cat():
	name = "tom"

	# 普通方法
	def mai_meng():
		print("小猫会卖萌")

	# 绑定方法(对象)
	def attack(self):
		print("小猫会抓人")

	# 绑定方法(类)
	@classmethod
	def youmi(cls):
		print(cls)
		print("可以放大招,伤害最高")

	# 静态方法
	@staticmethod
	def jump():
		print("小猫会上树,抓老鼠")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
obj = Cat()
# 普通方法(无参方法只能类调用)
Cat.mai_meng()  # 小猫会卖萌
# obj.mai_meng()  error

# 绑定方法(对象)
obj.attack()  # 小猫会抓人
Cat.attack(obj)  # 小猫会抓人

# 绑定方法(类)
"""对象和类都可以调用绑定到类的方法 推荐使用类来调用"""
Cat.youmi()  # 可以放大招,伤害最高
obj.youmi()  # 可以放大招,伤害最高
# print(obj.__class__)

# 静态方法
obj.jump()  # 小猫会上树,抓老鼠
Cat.jump()  # 小猫会上树,抓老鼠
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

三.property

"""
property  可以把方法变成属性使用
作用: 控制属性的获取,修改,删除等操作
变向的增加成员的安全性,可以通过自定义的逻辑进行控制

自动触发: 要求名字相同,同一个名字
	获取@property
	设置@属性名.setter
	删除@属性名.deleter
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
# 写法一
class MyClass():
	def __init__(self, name):
		self.name = name

	@property
	def username(self):
		# return self.name
		pass  # 不获取

	@username.setter
	def username(self, val):
		# 在触发时:val = 朴飘乐 self就是本对象
		# self.name = val
		pass  # 不设置

	@username.deleter
	def username(self):
		# print("删除方法被触发...")
		# del self.name
		pass  # 不删

obj = MyClass("朴一生")
# 获取属性
print(obj.username)
# 设置属性
obj.username = "朴飘乐"
# 获取属性
print(obj.username)

# 删除属性
del obj.username

# 获取属性
print(obj.username)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
# 写法二
class MyClass():
	def __init__(self, naem):
		self.name = naem

	# 获取方法
	def get_username(self):
		return self.name
		# pass  # 不获取

	# 设置方法
	def set_username(self, val):
		self.name = val
		# pass  # 不获取

	# 删除方法
	def del_username(self):
		# del self.name
		pass

	# property(获取方法, 设置方法, 删除方法)
	username = property(get_username, set_username, del_username)

obj = MyClass("朴仁猛")
# 获取操作
print(obj.username)  # 自动触发get_username方法
# 设置操作
obj.username = "pdd"  # 自动触发set_username方法
# 获取操作
print(obj.username)
# 删除操作
del obj.username  # 自动触发el_username方法
# 获取操作
print(obj.username)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/336262
推荐阅读
相关标签
  

闽ICP备14008679号