自省是指检查某事物以确定它是什么,它知道什么以及它能够做什么的能力
对于类来说,主要的自省方法有:dir()、__dict__
class A():
name = 'user'
class B(A):
def __init__(self,age):
self.age = age
I = B(12)
print(I.__dict__)
print(B.__dict__)
print(A.__dict__)
# {'age': 12}
# {'__module__': '__main__', '__init__': <function B.__init__ at 0x00000166595F4550>, '__doc__': None}
# {'__module__': '__main__', 'name': 'user', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
print(dir(I))
print(dir(B))
print(dir(A))
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
__dict__属性只能查询属于自己的属性和方法
dir()可以查询一个对象中所有的属性和方法,包括父类
在python中,如果想调用·类的父类的函数,可以:
class A():
def __init__(self):
print('A')
def say(self):
print('hhhh')
class B(A):
def __init__(self):
A.__init__(self)
A.say(self)
print('B')
当具有多继承时,会一步步回溯执行父类__init__函数,所有下面这里执行了两次A的初始化函数,因为A有B,C两个子类
class A():
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
A.__init__(self)
class C(A):
def __init__(self):
print('C')
A.__init__(self)
class D(B,C):
def __init__(self):
print('D')
B.__init__(self)
C.__init__(self)
now = D()
# D
# B
# A
# C
# A
python提供了super函数用于调用父类方法:
class A():
def __init__(self):
print('A')
class B(A):
def __init__(self):
super().__init__()
print('B')
但是事实上,super函数并非简单的调用父类方法,还是上面那个多继承的例子:
class A():
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
super().__init__()
class C(A):
def __init__(self):
print('C')
super().__init__()
class D(B,C):
def __init__(self):
print('D')
super().__init__()
now = D()
D.mro()
# D
# B
# C
# A
# [__main__.D, __main__.B, __main__.C, __main__.A, object]
可以看到,super函数是按照mro的顺序调用父类,保证每个父类只被调用一次
如果改变D的super函数:?
class D(B,C):
def __init__(self):
print('D')
super(B,self).__init__()
now = D()
# D
# C
# A
?????????原因是,super函数在调用时候,会自动查找调用类的上一级(顺序按照mor顺序,也就是DBCA),例如在使用super().__init__()时,默认为调用自己,也就是super(D,self).__init__(),那么会查找D的上一级B,以此类推
????????当调用super(B,self).__init__()时,会查找B的上一级C开始执行
在 Python 中,文件操作,数据库操作,都需要在程序执行完毕进行清理工作,很多时候我们经常忘记手动关闭,因此 Python 集成了一种自动操作,例如文件使用自后,自动释放资源。
上述场景的描述,转换成 Python 语法就是?with...as
?语句,即上下文管理器,它在 Python中实现了自动分配并释放资源
对于调用类来说,会再开始的时候调用__enter__函数,结束的时候调用__exit__函数
class sample():
def __enter__(self):
print('enter')
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
with sample() as one:
print('run')
# enter
# run
# exit
?with...as...语句一般用于文件访问,一般的方式是:
with open("./demo.txt") as file:
data = file.read()
但是不能处理报错问题,这里一般可以搭配try? except语句加上类的使用,用于文件访问:
class sample():
def __enter__(self):
try:
self.file = open('xxx.txt')
except FileNotFoundError:
self.file = None
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file is None:
print('文件不存在')
else:
self.file.close()
with sample() as one:
pass
# 文件不存在