python高级编程:类 以及自省机制

2021-01-14 11:35:04 浏览数 (1)

文章目录

    • MRO算法
      • 为什么不单纯使用深度优先或者广度优先
      • C3算法
  • 实例方法 静态方法 类方法
      • 实例方法
      • 静态方法
      • 类方法
      • 对比
  • 私有属性
  • python自省机制

MRO算法

为什么不单纯使用深度优先或者广度优先

  • 深度优先搜寻

查找顺序是A->B->D->C, 但是如果C重载了D的某个方法(B没有重载该方法), 由于深度优先所以将会使用D中的方法, 这是不合理的

  • 广度优先

查找顺序是A->B->C->D->E, 由于优先级关系, B和D的优先级高于C, 但是如果C和D中定义了同一个方法, 由于广度优先所以将会使用C中的方法, 这是不合理的

C3算法

代码语言:javascript复制
class D:
    pass

class E:
    pass

class C(E):
    pass

class B(D):
    pass

class A(B, C):
    pass

print(A.__mro__)
>>> (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)
代码语言:javascript复制
class D:
    pass

class C(D):
    pass

class B(D):
    pass

class A(B, C):
    pass

print(A.__mro__)
>>> (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

实例方法 静态方法 类方法

实例方法

  • 可以访问实例变量和类变量
  • 只能实例对象调用

静态方法

  • @staticmethod
  • 静态方法是不可以访问实例变量或类变量,不会主动传入self,传入什么参数才能获取到什么参数.
  • 可通过实例对象或类对象调用

类方法

  • @classmethod
  • 类方法只能访问类变量,不能访问实例变量
  • 可通过实例对象或类对象调用
  • 需要传入cls参数, cls参数指向的是一开始定义的类对象(不是实例对象)

对比

  1. 类方法无须创建实例对象调用,所以类方法的调用较实例方法更为灵活
  2. 静态方法有点像附属于类对象的“工具”, 将对象的相关处理逻辑“束缚”在对象体内,这样封装得会更好些。
  3. 实例方法只能通过实例对象调用;类方法和静态方法可以通过类对象或者实例对象调用,如果是使用实例对象调用的类方法或静态方法,最终都会转而通过类对象调用。
  4. 实例方法使用最多,可以直接处理实例对象的逻辑;类方法不需要创建实例对象,直接处理类对象的逻辑;静态方法将与类对象相关的某些逻辑抽离出来,不仅可以用于测试,还能便于代码后期维护。
  5. 实例方法和类方法,能够改变实例对象或类对象的状态,而静态方法不能。

私有属性

代码语言:javascript复制
## 私有属性
# 类中所有双下划线开头的名称如__x都会在类定义时自动变形成:_类名__x的形式
class A():
    __N = 0
    _M = 1   # 可以在外部调用, 只是给程序员提示

    def __init__(self):
        self.__N = 10  # _A__N

    def read(self):
        print(self.__N)

    def __write(self): # _A__write
        self.__N = 20
        print(self.__N)

    def write(self):
        self.__write() # 可以在内部调用

print(dir(A))
a = A()
print(a._M)
a.read()
# a.__write() # 无法调用
a.write()
print(a._A__N) # 可以调用
a._A__write() # 可以调用

['_A__N', '_A__write', '_M', '__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__', 'read', 'write']
1
10
20
20
20

python自省机制

  • __dict__返回的是字典, dir返回的是列表
  • __dict__查看对象的所有属性(可写属性), dir查看类本身的所有属性。
代码语言:javascript复制
# -*- coding:utf-8 -*-
# /usr/bin/python

class Person:
    name = "Person_name"

class Student(Person):
    student_name = 'student_name'
    def __init__(self, school_name):
        self.school_name = school_name

if __name__ == "__main__":
    user = Student("慕课网")

    print(user.__dict__) # 通过__dict__查询属性
    print(user.name)

    # 通过user.name可以读取到, 但是通过__dict__无法获取的原因
    # name是属于Person的属性, 并不是Student的属性, 但是使用点的时候会向上查找.
    print(Student.__dict__)
    print(Person.__dict__)
    # 通过__dict__赋值
    user.__dict__["school_addr"] = "北京市"
    print(user.school_addr)

    # 通过__dict__查询属性
    print(user.__dict__)
    # 通过dir查询属性
    print(dir(user))
    print(dir(Student))
    print(dir(Person))

0 人点赞