一、超类
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/tech/python/280994.html