python-面向对象-25-特殊属性特殊方法

    技术2024-08-14  64

    1.类相关属性

    1.1 类相关属性整理

    特殊方法含义obj.__class__对象所属的类class.__bases__类的基类元组class.__base__类的基类class.__mro__类层次结构class.__subclass__()子类类表

    1.2 类相关属性操作

    示例代码:

    class A: class_attr1 = "class_val1" def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 class B(A): pass class C(A): pass class D(B, C): pass a1 = A("val_a_1", "val_a_2") print("所属的类") print(a1.__class__) print("--" * 20) print("基类元组,针对多继承的情况") print(D.__bases__) print("--" * 20) print("类的基类") print(D.__base__) print("--" * 20) print("类完整层次结构") print(D.__mro__) print('--' * 20) print("直接子类列表") print(A.__subclasses__())

    运行结果:

    所属的类 <class '__main__.A'> ---------------------------------------- 基类元组,针对多继承的情况 (<class '__main__.B'>, <class '__main__.C'>) ---------------------------------------- 类的基类 <class '__main__.B'> ---------------------------------------- 类完整层次结构 (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) ---------------------------------------- 直接子类列表 [<class '__main__.B'>, <class '__main__.C'>]

    代码说明:

    按照上面类继承关系示意图创建类A、类B、类C、类D__class__代表对象所属的类,对象a1是类A的实例,所以a1.__class__对应的结果是:<class '__main__.A'>因为python支持多继承,__bases__只返回直接继承父类的元组,定义类D过程中指定D(B, C),所以对应结果为:(<class '__main__.B'>, <class '__main__.C'>)__base__返回直接父类,可以使用在单继承和多继承中,对于多继承情况下是不准确的,只会返回第一个继承的类,定义类D过程中指定D(B, C),其中第一个类为B,所以返回:<class '__main__.B'>__mro__属性用于返回从当前类到类object的完整继承关系,对应结果的类型是tuple。对于多继承多分支情况,有兴趣的同学可以测试一下,采用什么规则__subclasses__()用于返回直接子类列表,在程序中,类B继承类A, 类C继承类A,所以对应的子类列表为:[<class '__main__.B'>, <class '__main__.C'>]

    2.普通实例属性相关操作

    实例属性相关特殊方法和特殊属性

    方法说明例子__dict__对象的属性字典a.__dict____getattr__获取属性a.attr_name__setattr__属性赋值a.attr_name = value__getattribute__获取属性a.attr_namehasattr()判断属性是否存在hasattr(a, ‘name’)getattr()获取属性getattr(a, ‘name’)setattr()设置属性setattr(a, ‘name’) = ‘niefajun’

    正常情况下,对于对象的实例属性可以直接操作,以上的属性或者方法是对操作

    示例代码:

    class Person: def __init__(self, name, age): self.name = name self.age = age def __setattr__(self, key, value): print('__setattr__:key={0},value={1}'.format(key, value)) super(Person, self).__setattr__(key, value) def __getattr__(self, item): print('__getattr__') print("获取的属性不存在") def __getattribute__(self, item): print("__getattribute__") return super(Person, self).__getattribute__(item) p1 = Person("聂发俊", 100) print('--' * 20) print("属性字典") print(p1.__dict__) print('--' * 20) print("判断属性是否存在") has_flag = hasattr(p1, "name") print(has_flag) print('--' * 20) print("设置属性1-直接设置") p1.age = 101 print('--' * 20) print('设置属性2-setattr函数') setattr(p1, 'age', 102) print('--' * 20) print("设置属性3-__setattr__()方法") p1.__setattr__('age', 103) print('--' * 20) print("获取属性1-直接获取") print(p1.age) print('--' * 20) print("获取属性2-getattr函数") print(getattr(p1, 'age')) print('--' * 20) print("获取属性3-__getattribute__方法") print(p1.__getattribute__('age')) print('--' * 20) print("获取不存在的属性") print(p1.name1)

    运行结果:

    __setattr__:key=name,value=聂发俊 __setattr__:key=age,value=100 ---------------------------------------- 属性字典 __getattribute__ {'name': '聂发俊', 'age': 100} ---------------------------------------- 判断属性是否存在 __getattribute__ True ---------------------------------------- 设置属性1-直接设置 __setattr__:key=age,value=101 ---------------------------------------- 设置属性2-setattr函数 __setattr__:key=age,value=102 ---------------------------------------- 设置属性3-__setattr__()方法 __getattribute__ __setattr__:key=age,value=103 ---------------------------------------- 获取属性1-直接获取 __getattribute__ 103 ---------------------------------------- 获取属性2-getattr函数 __getattribute__ 103 ---------------------------------------- 获取属性3-__getattribute__方法 __getattribute__ __getattribute__ 103 ---------------------------------------- 获取不存在的属性 __getattribute__ __getattr__ 获取的属性不存在 None

    程序说明: 1.实例化过程中输出__setattr__:key=name和__setattr__:key=age,这个是因为在__init__()方法中设置了这两个属性,都会经过__setattr__()方法,所以会执行两次。 2.属性字典中,本质上还是通过__getattribute__,所以也会输出__getattribute__的提示信息。 3.三种设置属性方法,比较特殊的是第三次,相比其他两次增加了__getattribute__输出,因为有一次判断属性是否存在的过程。 4.三种获取属性值,比较特殊的也是第三次,多了一次__getattribute__,和__setattr__()方法一样,增加了一次属性是否存在的过程,所以看起来比较特殊。 5.当获取一个不存在的属性,首先调用__getattribute__(self, item),如果属性存在则直接返回,不存在时,判断__getattr__(self)是否存在,存在的话,则执行__getattr__(self)方法,作为获取不存在属性的一种兜底操作。如果没有存在__getattr__(self),则直接提示属性异常。

    __getattribute__(self, item) VS __getattr__(self, item): 相同点:都是用于属性获取 不同点:__getattribute__()无论属性是否存在都会首先访问,获取对应值;__getattr__()只有当属性不存在的时候,才会调用,作为兜底(异常)处理。

    注意事项:对于__setattr__()和__getattribute__()不要在函数里面直接赋值和返回属性,这样操作的话,又会调用__setattr__()和__getattribute__(),构成死循环。 错误代码:

    class Person: def __init__(self, name, age): self.name = name self.age = age def __setattr__(self, key, value): """错误操作""" # 等效操作: self.__setattr__(key, value), 自己调用自己,造成死循环 self.key = value def __getattribute__(self, item): """错误操作""" # 等效操作: self.__getattribute__(item), 自己调用自己,造成死循环 return self.item

    3.对象操作

    对象操作整理:

    方法说明例子__getitem__通过索引获取a[key_index]__setitem__通过索引设置a[key_index] = value

    在日常的开发过程中,使用的比较少

    示例代码:

    class Animal: def __init__(self, animal_li): self.animals_name = animal_li def __getitem__(self, item): return self.animals_name[item] animals = Animal(['cat', 'dog', 'tiger']) for animal in animals: print(animal)

    执行结构:

    cat dog tiger

    注:使用的很少,等后面有具体使用场景在补充完善。


    备注: 更多精彩博客,请访问:聂发俊的技术博客 对应视频教程,请访问:python400 完整markdown笔记,请访问: python400_learn_github

    Processed: 0.012, SQL: 9