接下来的每一天都希望和大家分享玩python的过程中学到的东西,同时也是督促自己每天进步一点点,大家可以互相监督哇~
今天学习了python的装饰器有关的内容
首先就是装饰器的装饰和调用,直接上代码
'''
1.首先装饰器的装饰顺序是从下往上进行装饰
2.调用的时候要从上往下进行调用
'''
# 举例:
def w1(func):
print("---正在装饰1---")
def inner():
print("---正在调用1---")
func()
return inner
def w2(func):
print("---正在装饰2---")
def inner():
print("---正在调用2---")
func()
return inner
@w1
@w2
def test():
print("---正在调用3---")
test()
运行结果:
---正在装饰2---
---正在装饰1---
---正在调用1---
---正在调用2---
---正在调用3---
从结果可以看出装饰器的装饰顺序还有调用的顺序
接下来是用装饰器装饰无参数和有参数的函数
'''
1.要注意的是有参数的函数进行装饰时,要把参数传进去之后再传出来
2.多个参数用*args(tuple),**kwargs(dictionary)
3.*args和**kwargs在作为实参使用时需要进行解包
'''
# 举例:
def w1(functionName):
def func_in(*args,**kwargs):
print("正在调用1...")
functionName(*args,**kwargs)
print("正在调用2...")
return func_in
@w1
def test1(a,b):
print("a + b = " + str(a + b))
@w1
def test2(a,b,c):
print("a+b+c = " + str(a + b + c))
test1(11,22)
test2(11,22,33)
运行结果:
正在调用1...
a + b = 33
正在调用2...
正在调用1...
a+b+c = 66
正在调用2...
test1和test2在调用的时候会指向func_in函数,而functionName则是指向原来的test1和test2,functionName指向的函数可以永久保存(闭包的特点)
def test1上面的@w1的代码其实就相当于
test1 = w1(test1)
接着是装饰器来装饰有返回值的函数
'''
有返回值的函数和无返回值的函数类似,只是在中间需要通过一个参数来进行传递返回值
'''
# 举例:(偷个懒,直接搬前面的代码进行小小的改动)
def w1(functionName):
def func_in(*args,**kwargs):
print("正在调用1...")
ret = functionName(*args,**kwargs) # 在这里我们需要一个变量进行返回值的接收
print("正在调用2...")
return ret # 在这里没有返回值是不行的,最后结果会出错
return func_in
@w1
def test1(a,b):
return "a + b = " + str(a + b)
@w1
def test2(a,b,c):
return "a+b+c = " + str(a + b + c)
ret1 = test1(11,22)
print(ret1)
ret2 = test2(11,22,33)
print(ret2)
运行结果:
正在调用1...
正在调用2...
a + b = 33
正在调用1...
正在调用2...
a+b+c = 66
还有一点是通用装饰器,通用装饰器与有返回值的装饰器用法相同,所以就不放代码啦。
如果是无返回值得函数,python会返回None
接着是带有参数的装饰器
'''
1.带参数的装饰器特点是可以对不同的函数进行不同的装饰,达到分门别类的效果
2.带参数的装饰器原理是在普通装饰器的外部再定义一个函数来进行传递参数,然后返回内部函数的一个引用进行装饰
'''
# 举例:
def func_external(arg = "hello,world"):
print("---1---") #在装饰器进行装饰时进行调用
def func(functionName):
print("---2---") #在装饰器进行装饰时进行调用
def func_in(*args,**kwargs):
if arg == "hello,world": #这里实现了带参装饰器的作用
print("---3---")
functionName(*args,**kwargs)
functionName(*args,**kwargs)
else:
print("---4---")
functionName(*args,**kwargs)
return func_in
return func
@func_external()
def test1(a,b):
print("a+b= " + str(a+b))
@func_external("what")
def test2(a,b,c):
print("a+b+c= " + str(a+b+c))
test1(11,22)
test2(11,22,33)
运行结果:
---1---
---2---
---1---
---2---
---3---
a+b= 33
a+b= 33
---4---
a+b+c= 66
通过分析就可以看出函数调用的顺序
接下来是变量的作用域的问题
遵循LEGB规则:locals->enclosing function->globals->builtins
从左到右作用域依次变大
python是一门动态语言,即可以在运行的过程中给类添加属性和方法
'''
想要给实例对象添加方法,不可以和添加属性一样,而是要用到types.MethodType(function,instance)来添加
'''
import types
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
p1 = Person("angel",99)
p1.length = "168cm" # 给实例对象添加属性
print("身高:" + p1.length)
def eat(self):
print("%s正在吃..."%self.name)
p1.eat = types.MethodType(eat,p1) # 给实例对象添加方法,在这里等号前面可以是任意名称,但是为了代码的可读性,我们要选择适当的名称
p1.eat()
#直接在类中添加静态方法和类方法
@staticmethod
def PrintOne():
print("One")
@classmethod
def PrintTwo(cls):
print("Two")
Person.One = PrintOne
Person.Two = PrintTwo
Person.One() # 通过类调用此方法
Person.Two()
p1.One() # 通过实例对象来调用此方法
p1.Two()
运行结果:
身高:168cm
angel正在吃...
One
Two
One
Two