8.自省反射 和 类内置方法

2018-08-17  本文已影响18人  芝麻酱的简书

反射四个方法的使用:

hasattr(result, "name")

getattr(result, "name", "bill")

setattr(result, "name", "bill")

delattr(result, "name")

反射的用处:

  1. 动态增加属性,包括数据属性和方法属性
# 声明方
class Dad(metaclass=abc.ABCMeta):
    def __init__(self, name):
        self.name = name



# 模拟外部使用方

dad1 = Dad("bill")

if hasattr(dad1, "eatFood"):
    eatFood_func = getattr(dad1,"eatFood")
    eatFood_func()

else:
    pass
  1. 动态导入模块
    方式1:__import__("sys")
    方式2:
import importlib

m = importlib.import_module("m1.t")
m.test()

使用super继承包装父类方法:

# 继承自系统类list  重写系统类的方法
class NewList(list):

    def append(self, obj):
        if type(obj) is str:
            super().append(obj)


list1 = NewList()
list1.append("adf") # 添加成功
list1.append(123)   # 添加失败

类内置方法:

🎈类内置__getattribute__方法:
访问类属性,就是访问__getattribute__方法,如果没有找到访问的属性,则抛出异常,执行__getattr__方法

    def __getattribute__(self, item):
        raise AttributeError("抛出异常 去执行__getattr__")

    def __getattr__(self, item):
        pass

🎈类内置__getattr__方法:
访问类属性的时候,如果有该属性,则不触发__getattr__方法,如果没有该属性,则触发__getattr__方法

🎈类内置__delattr__方法:
只要访问属性就会触发

🎈类内置__setattr__方法只要访问属性就会触发,可以使用设置属性字典__dict__的方法来防止递归死循环

🎈类内置__getitem__ __setitem__等方法,是通过字典resuslt["name"]这种方式取、设置、删除属性等操作触发

🎈使用__str__来改变对象的打印信息:

class Foo:
    def __str__(self):
        return "这是"

print(Foo())

🎈使用__repr__来改变对象在解释器中的打印信息:
优先找__str__,没有会找__repr__

🎈使用__format__来格式化定制打印信息

🎈使用__slots__来节省内存,只能使用声明的属性

class Foo:
    __slots__ = ["name", "age"]

🎈使用__module____class__查看对象所在的模块和类

🎈__del__析构方法

🎈使用__call__定义call方法Foo()


迭代器:

🎈使用__next____iter__实现迭代器协议

迭代器协议:对象必须提供一个next方法,执行该方法返回迭代中的下一项,或者 到最后一项后抛出StopIteration异常,以终止迭代。

可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义了一个__iter__方法)

调用for in循环,实际就是调用对象的iter(obj)方法,也即obj.__iter__方法,装换成迭代器对象,然后执行对象的__next__方法。

对于一个自定义类,想要实现迭代器协议,可以重写如下方法:

def __iter__(self):
      return self

def __next__(self):
      if xxx:
            raise StopIteration("终止")
      return xxx

访问优先级:
1. 类属性
2. 数据描述符
3. 实例属性
4. 非数据描述符
5. 找不到属性触发__getattr__()


上下文管理协议with as

使用__enter____exit__方法
如果执行with as过程中程序异常,会直接执行__exit__并抛出异常,如果__exit__中返回True,则会忽略掉异常继续执行

上一篇下一篇

猜你喜欢

热点阅读