文章目录
闭包
使用闭包可以调用私有变量,同时可以在该私有变量基础上添加想要的参数。
def father(fatherName):
def son(sonName):
print("{}是{}的爸爸".format(fatherName, sonName))
return son
test = father("老王")
test("小明")
test("小李")
输出
老王是小明的爸爸
老王是小李的爸爸
装饰器
- 装饰器可以嵌入函数中
- 装饰器使用@装饰语法,相同的函数名只出现一次,可读性更高。
- 装饰器可以加入参数
- 装饰对象可以是函数、类
基本原理
python的装饰器使用闭包来实现了,基本原理如下
def myDecorator(func):
print("I am a decorator!")
def warp_func():
func()
print("Hello, warp funcation!")
return warp_func
def require_func():
print("I am require function!")
require_func = myDecorator(require_func)
require_func()
输出
I am a decorator!
I am require function!
Hello, warp funcation!
用法
不带参数的修饰器
def myDecorator(func):
print("I am a decorator!")
def warp_func():
func()
print("Hello, warp function!")
return warp_func
@myDecorator
def require_func():
print("I am require function!")
require_func()
#名字输出存在缺陷
print(require_func.__name__)
输出
I am a decorator!
I am require function!
Hello, warp funcation!
warp_fun
打印函数require_func名字时输出不对,为解决该问题可使用warp包装解决,即
def myDecorator(func):
from functools import wraps
print("I am a decorator!")
@wraps(func)
def warp_func():
func()
print("Hello, warp function!")
return warp_func
@myDecorator
def require_func():
print("I am require function!")
require_func()
#名字输出不存在缺陷
print(require_func.__name__)
带参数的装饰器
def outer(args):
print(args)
def myDecorator(func):
print("I am a decorator!")
def warp_func():
func()
print("Hello, warp funcation!")
return warp_func
return myDecorator
@outer("outer: 我是outer装饰器传入的")
def require_func():
print("I am require function!")
require_func()
输出
outer: 我是outer装饰器传入的
I am a decorator!
I am require function!
Hello, warp funcation!
类装饰器
可以用来设置类的属性等
def decorator(enabled=True):
def warp_func(cls):
cls.__pd_type__ ='test'
cls.__enabled__ = enabled
return cls
return tracer
#报错,显示没有该属性
#class TestCases(object):
# pass
#print(TestCases.__dict__['__pd_type__'])
#print(TestCases.__dict__['__enabled__'])
@TestClass()
class TestCases(object):
pass
print(TestCases.__dict__['__pd_type__'])
print(TestCases.__dict__['__enabled__'])
输出
test
true
python内置装饰器
@staticmethod
- 声明方法为静态方法,可直接通过类或者实例调用。
- 其修饰的方法,不需要self参数,可传入自定义的任何参数,其使用方法与直接调用函数相同。
@classmethod
- 声明方法为类方法,可直接通过类或实例调用。
- 其修饰的方法,不需要self参数,需要一个标识类本身的cls参数。
比较
class Test:
def __init__(self, name):
self.name = name
@staticmethod
def static_func(*args):
print("这是一个静态方法")
@classmethod
def class_func(cls):
print("这是一个类的静态方法")
print("类的名字为%s"%cls.__name__)
def func(self):
print("这是一个类的普通方法")
print(self.name)
测试该类
[In 1]: Test.static_func()
[Out 1]: 这是一个静态方法
[In 2]: Test.class_func()
[Out 2]: 这是一个类的静态方法
类的名字为Test
[In 3]: Test.func()
[Out 3]:
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: func() missing 1 required positional argument: 'self'
[In 4]: test = Test("test")
[Out 4]: 这是一个类的普通方法
test
[In 5]: test.static_func()
[Out 5]: 这是一个静态方法
[In 6]: test.class_func()
[Out 6]: 这是一个类的静态方法
Test
描述器
- 描述器是一个类
- 可以定义
__get__, __set__, __delete__
方法,来控制属性的访问、赋值和删除操作 - 当某个类定义了一个描述器对象的类属性,调用这个类对象的此属性,会触发相应描述器的
__get__, ___set___, __delete__
方法。
#定义描述器————info类,为其设置相应的方法
class info:
def __init__(self, name):
self.name = name
def __set__(self, instance, value):
print("触发set方法")
instance.__dict__[self.name] = value
print(instance.__dict__)
def __get__(self, instance, owner):
print("触发get方法")
return instance.__dict__[self.name]
def __del__(self):
print("触发del方法")
class user:
info = info("money")
def __init__(self, name):
self.name = name
xiaoMing = user("xiaoMing")
print("=="*20)
xiaoMing.info = 5
print("=="*20)
print(xiaoMing.info)
print("=="*20)
xiaoMing.info
'''output
==================================
触发set方法
{'name': 'xiaoMing', 'money': 5}
==================================
触发get方法
5
==================================
触发get方法
触发del方法
'''
@property
该描述符可在类中把一个方法变成属性调用
定义只读属性
名字开头为双下划线的私有属性也可访问,而@property可定义真正意义上的私有属性,无法被实例调用。
class Person():
def __init__(self, name):
self.name = name
self.__age = 12
@property
def age(self):
print(self.__age)
return self.__age
xm = Person('xiaoMing')
print(xm.age) #结果为12
xm.age() #报错
类似描述器的实现
class Person():
def __init__(self, name):
self.name = name
self.__age = 18
@property
def age(self):
return self.__age
@age.setter
def age(self, age):
print("触发set方法")
@age.getter
def age(self):
print("触发get方法")
return self.__age
@age.deleter
def age(self):
print("触发delete方法")
xm = Person('xiaoming')
print('='*30)
print(xm.age)
print('='*30)
xm.age = 10
print('='*30)
del xm.age
'''output
==============================
触发get方法
18
==============================
触发set方法
==============================
触发delete方法
'''