一、超类
1.1 什么时候用到超类?
如果子类需要复用父类的代码(属性、代码)时,需要通过超类实现
class A: class_name = "A" # 类的属性 def __init__(self, name, age): self.name = name # 实例的属性 self.age = age # 实例的属性 def show_me(self): print(f"Hello,我的name是 {self.name}") print(f"Hello,我的age是 {self.age}") a = A("austin", 18) a.show_me() # 类A 进行【扩展】:增加一个 国家 属性 class B(A): # 继承实现扩展 class_name = "B" def __init__(self, country, *args, **kwargs): self.country = country super().__init__(*args, **kwargs) # 通过超类,实现对父类代码复用 b= B(country='China', name="sunny", age=18) b.show_me()
- super 不是代表父类;
- super 是一个内置函数,返回了超类;
- 沿着继承关系,从祖上一系列类中,寻找成员;
class C(B): class_name = "C" def show_class_name(self): print("自己class_name属性", self.class_name) print("继承来的class_name属性", super().class_name) # 超类的class_name # print("继承来的class_name属性", super(B,self).class_name) c= C(country='China', name="sunny", age=18) c.show_class_name()
>>>
自己class_name属性 C
继承来的class_name属性 B
1.2 super 可以接收参数:
- 从哪个类的祖先中找成员
- 传递实例对象
class C(B): class_name = "C" def show_class_name(self): print("自己class_name属性", self.class_name) # print("继承来的class_name属性", super().class_name) # 超类的class_name print("继承来的class_name属性", super(B,self).class_name) c= C(country='China', name="sunny", age=18) c.show_class_name()
>>>
自己class_name属性 C
继承来的class_name属性 A
1.3 类继承关系
print(C.__mro__)
>>>
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
二、反射
反射:允许使用变量的值(而不是变量的名),对成员进行访问
1. 设置属性
setattr(A, attr_name, "B") #设置属性
2.读取属性
print(getattr(A, attr_name)) # 读取属性
3.删除属性
delattr(A,attr_name) #删除属性
4. 判断属性
f hasattr(A,attr_name): #属性是否存在
举例:
class A: class_name='A' #类属性 age=18 attr_name="class_name" # attr_name="age" print(getattr(A,attr_name)) #通过变量值访问属性 setattr(A,attr_name,'B') #通过变量值设置属性 print(getattr(A,attr_name)) #获取属性值 delattr(A,attr_name) #删除属性 if hasattr(A,attr_name): #属性是否存在 print(A.class_name) else: print(f"属性:{attr_name},不存在")
三、装饰器
3.1 装饰器的原理
- 是一个函数,参数是函数,返回值是函数
from datetime import datetime
def logs(func): # 装饰器 def f(): print(datetime.now(), func.__name__, "开始调用") func() print(datetime.now(), func.__name__, "调用结束") return f @logs # 装饰 def add(): # 被装饰函数 print("add is calling") add()
>>>
2022-08-16 23:22:43.221348 add 开始调用
add is calling
2022-08-16 23:22:43.221348 add 调用结束
规则的原因(装饰器的装饰过程)
@logs # 装饰 def add(): # 被装饰函数 print("add is calling")
等同于
def add(): # 被装饰函数 print("add is calling") # 装饰的过程,被装饰函数作为参数,传递给装饰器,并且将返回值覆盖原函数 add = logs(add)
3.2 被装饰函数有参数
装饰器的返回值,接收参数,并传递给【被装饰函数】
from datetime import datetime def logs(func): # 装饰器 def f(*args, **kwargs): print(datetime.now(), func.__name__, "开始调用") func(*args, **kwargs) print(datetime.now(), func.__name__, "调用结束") return f @logs def add(x, y): # 被装饰函数 print("add is calling:", f"{x=}, {y=}") add(x=2, y=2)
3.3 装饰器怎么接收自己的参数
创建一个函数来接收参数,然后返回原来的装饰器
from datetime import datetime def logs(level): def _logs(func): # 装饰器 def f(*args, **kwargs): print(level,datetime.now(), func.__name__, "开始调用") func(*args, **kwargs) print(level,datetime.now(), func.__name__, "调用结束") return f return _logs @logs(level="debug") def add(x, y): # 被装饰函数 print("add is calling:", f"{x=}, {y=}") add(x=2, y=2)
@logs(level="debug") def add(x, y): # 被装饰函数 print("add is calling:", f"{x=}, {y=}")
等同于
def add(x, y): # 被装饰函数 print("add is calling:", f"{x=}, {y=}") add = logs(level="debug")(add)
四 生成器
如果函数中有yield关键字,其调用结果,则返回一个生成器
生成器是一个可迭代对象,可以被for循环遍历使用
在遍历时才执行,并计算返回值
def add(a, b): c = a + b print(c) yield c c = add(1, 2) print(c) # c是生成器 for i in c: # 生成器:在使用数据时,才产生数据 print(f"{i=}")
>>>
3
i=3
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/281022.html