一.怎么为类添加装饰器
为类添加装饰器时,就是在装饰器后加一个cls,代码:
def some_func(cls):
return cls
@some_func
class A(object):
pass
if __name__ == '__main__':
a = A()
二.用类装饰某个函数
import time
class A(object):
def __init__(self, func):
self.func = func
print('-------')
def __call__(self, *args, **kwargs): # __call__当对一个对象加()进行调用时,此方法会自动执行
# 当对一个对象加()进行调用时,此方法会自动执行
print(f"{self.func.__name__}函数运行前")
start = time.time()
result = self.func(*args, **kwargs)
print(f"{self.func.__name__}函数运行后")
end = time.time()
print(f"{self.func.__name__}执行时间为{start - end}")
return result
@A
def f(a, b):
time.sleep(1)
print('123')
pass
@A
def q(w):
time.sleep(1)
print(w)
if __name__ == '__main__':
# 因为类和函数可以直接加括号,但是由类创建的对象一般是不能加括号的,所以要在类里加一个__call__属性,否则会报错
f(1, 2)
q(1)
三.带参数的装饰器
带参数的装饰器,就是装饰器会接受一个或多个变量,例如在log中,传入文件名称
def log(filename: str):
print(filename)
def inner(func):
print(f'{func.__name__}')
def wrapper(*args, **kwargs):
print(args)
func(*args, **kwargs)
return wrapper
return inner
@log(filename='info.log')
def add(a, b):
return a + b
add(1, 2)
四.callable
callable 属性:一个函数或类里的元素包含此属性的话,可以直接加括号用
def add(x, y):
return x + y
class MyClass(object):
pass
class MyClass2(object):
def __call__(self, *args, **kwargs):
pass
print(callable(add)) # True
print(callable(MyClass())) # False
print(callable(MyClass2())) # True
五._ new 和 init _的区别
class Person(object):
def __init__(self, name):
self.name = name
print('初始化对象的值')
def __new__(cls, *args, **kwargs):
print('开始创建对象并分配内存')
return super().__new__(cls)
class Student(Person):
def __init__(self, name, stu):
super(Student, self).__init__(name)
def study(self):
pass
class Teacher(Person):
pass
if __name__ == '__main__':
xiaomimg = Person('小明')
六.单例模式
"""
单例模式: 只有一个实例
实现方法:
1.import
2.单例模式
3.装饰器
"""
class Person(object):
obj = None
def __init__(self, name):
# self.name = name
pass
def __new__(cls, *args, **kwargs):
# 如果对象已经创建,就直接把创建好的对象返回
# 如果对象没有创建,就创建对象并返回
if cls.obj is None:
cls.obj = super().__new__(cls) # 分配内存
return cls.obj
if __name__ == '__main__':
xiaoming = Person('小明')
xiaohong = Person('小红')
print(xiaohong is xiaoming) # False
print(id(xiaohong), id(xiaoming))
七.总结
1.什么是单例模式(使用场景)
单例模式某个类就是只会创建一个对象,再此创建时,会把创建好的对象返回。使某个类只有一个实例。
应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
2.什么是装饰器,带参数的装饰器的调用过程
所谓的装饰器,其实就是通过装饰器函数,来修改原函数的一些功能,使得原函数不需要修改
因为带参数的装饰器基本都是三层封装,拿下面的代码举例:
先将@log(filename='info.log')传给def log(),
执行下面的代码后,就可以看成下面代码的装饰器是@inner,
然后就是不带参数的装饰器的执行过程。
def log(filename: str):
print(filename)
def inner(func):
print(f'{func.__name__}')
def wrapper(*args, **kwargs):
print(args)
func(*args, **kwargs)
return wrapper
return inner
@log(filename='info.log')
def add(a, b):
return a + b
3.__new__和__init__的区别和联系
1. __new__是构造方法,__init__是初始化函数。
2.__new__通常不需要手动定义,一般在元类编程中使用,控制类的生成过程。
3.__new__第一个被执行,然后执行__init__绑定实例变量。
4.__new__必须有返回值,返回值是该类的实例,它会被__init__函数接收,通常叫做self变量
4.super是什么
super,名为超类,可以简单的理解为执行父类的__init__函数
我们可以把python中类的继承理解成这样的一个过程:
当我们在括号中明确了父类时,其实已经引用了父类的成员函数,但是并没有执行父类的初始化函数。
在执行子类的初始化函数的同时,会检查是否重载了父类的成员函数,如果重载则会直接覆盖。
而只有在执行了super之后,才相当于执行了父类的初始化函数,此时才可以访问父类的成员变量。