Python面向对象编程(三)自省机制、super函数、with...as...语句

发布时间:2024年01月17日

自省机制

自省是指检查某事物以确定它是什么,它知道什么以及它能够做什么的能力

对于类来说,主要的自省方法有: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()可以查询一个对象中所有的属性和方法,包括父类

Super函数

在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开始执行

with...as...语句

在 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
# 文件不存在

文章来源:https://blog.csdn.net/qq_54517101/article/details/135552155
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。