1.反射
hasattr getattr delattr setattr
优点:事先定义好接口,接口只有在被完成后才能真正执行,这实现了即插即用,这其实是一种“后期绑定”,即先定义好接口,
然后是再去实现具体的功能
print(hasattr(p, 'age')) # True 是否有属性 判断 print(getattr(p, 'name', '没有找到该参数')) # get属性值 print(getattr(p, 'name1', 'False')) # False setattr(p, 'name', 'sb') # 设置属性 print(p.__dict__) delattr(p, 'name') # 删除属性 print(p.__dict__)
setattr(p, 'func', lambda x: x + 1) setattr(p, 'func1', lambda self: self.name + " sb") print(p.__dict__) print(p.func(100)) # 添加函数属性
setattr(p, 'name', 'wangwu') print(p.func1(p))
# 反射应用场景 class FtpClient: #'ftp客户端,但是还么有实现具体的功能' def __init__(self, addr): print('正在连接服务器[%s]' % addr) self.addr = addr from module import FtpClient f1 = FtpClient('192.168.1.1') if hasattr(f1, 'get'): # 判断f1是否有get方法 如果没有 就执行else语句 func_get = getattr(f1, 'get') func_get() else: print('---->不存在此方法') print('处理其他的逻辑')
2.动态导入模块
# 动态导入模块 module__test = __import__('macboy.wsgi') # 此处就是macboy位置 print(module__test) # <module 'macboy' from 'C:\Disk_D\pycharm_stu\macboy\macboy'> import importlib m = importlib.import_module('macboy.wsgi') # 此处是macboy.wsgi位置 print(m) # <module 'macboy.wsgi' from 'C:\Disk_D\pycharm_stu\macboy\macboy\wsgi.py'>
3.类attr属性 __gerattr__ __setattr__ __delattr__ __getattribute__
# 双下划线开头的类属性 obj.属性 触发 class Foo: def __init__(self, name): self.name = name # 属性不存在时 被触发 比较常用 def __getattr__(self, item): return "%s属性不存在" % (item) # 添加属性时 被触发 def __setattr__(self, key, value): self.__dict__[key] = str(value) # 删除属性时 被触发 def __delattr__(self, item): self.__dict__.pop(item) a = Foo('wangwu') print(a.name) print(a.ww) # ww属性不存在 # print(a.__dict__) a.age = 10 a.gender = 'man' # print(a.__dict__) print(dir(Foo)) # print(Foo.__dict__) print(a.gender) # "man" print(a.age) # 10 # print(a.__dict__) del a.gender del a.age print(a.gender) # gender属性不存在 print(a.age) # age属性不存在
# __getattribute 和 __getarr__ 不管找不找的到,都会执行 先前面执行后面后执行 不管是否有偶异常 __getattribute都执行
# 当__getattribute抛出一异常 小弟__getarr__接受到 处理异常
class Foo:
def __init__(self, name):
self.name = name
def __getattr__(self, item):
return "你找的%s属性不存在" % (item)
def __getattribute__(self, item):
print("执行的是__getattribute")
raise AttributeError("抛出异常")
f1 = Foo('fdsf')
print(f1.fdd)
4.继承方式包装
包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)
# 二次加工标准类型(包装) class List(list): def append(self, item): if isinstance(item, str): super().append(item) else: print("只能加字符串") l = List("helloworld") l.append("111") l.append(111) # 只能加字符串 print(l)
5.组合方式授权
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__getattr__方法
# 组合方式授权 import time class Open: def __init__(self, filename, mode='r', encoding='utf-8'): self.file = open(filename, mode, encoding=encoding) self.mode = mode self.encoding = encoding def write(self, line): t = time.strftime("%Y-%m-%d %X") self.file.write('%s %s' % (t, line)) def __getattr__(self, item): # >>> getattr(list,"append") # <method 'append' of 'list' objects> return getattr(self.file, item) # file中执行item方法 f1 = Open('a.txt', 'w+') print(f1.__dict__) print(dir(f1.file)) f1.write('内存空间不足 ') f1.write('服务器超载 ') f1.seek(0) print(f1.read())