特殊成员
一、特殊成员补充:
- 索引、切片
- 当对象后面加小括号,自动执行call方法
- 当对象后面加中括号,会自动执行 item相关方法
- __getitem__(self,item)
- __setitem__(self, key, value)
- __delitem__(self, key)
- 调用方式:
- [item ] 索引:
- 以“索引”方式进行方法调用,中括号中的item被当做一个str 类型
class Class1:
def __getitem__(self, item):print('getitem , get:{}, type:{}'.format(item, type(item)))
def __setitem__(self, key, value):print('setitem , key:{} value:{}, type:{},type:{}'.format(key, value, type(key), type(value)))
def __delitem__(self, key):print('delitem, key:{}, type:{}'.format(key, type(key)))
# 实例化并调用obj = Class1()obj['test1'] #“对象索引”,自动触发执行__getitem__()方法obj['test2'] = 'value2' #“对象索引”赋值,自动触发执行__setitem(key,value) 方法,并将索引的key和值value传给形参del obj['test3'] # 删除“对象索引”,自动触发执行 __delitem__(self,key) 方法,并自动将索引的key传递给形参
- [star:stop:step] 切片:
- 以“切片”方式进行方法调用,中括号中的内容被当做一个slice对象,并将start,stop,step传递给slice的3个字段,slice.start ,slice.stop,slice.step
class Class1:
def __getitem__(self, item):print(item, type(item))print('item start:{}'.format(item.start))print('item stop:{}'.format(item.stop))print('item step:{}'.format(item.step))
def __setitem__(self, key, value):print(key, type(key), value, type(value))print('key start:{}'.format(key.start))print('key stop:{}'.format(key.stop))print('key step:{}'.format(key.step))print('value:{}'.format(value))
def __delitem__(self, key):print(key, type(key))print('key start:{}'.format(key.start))print('key stop:{}'.format(key.stop))print('key step:{}'.format(key.step))
# 实例化并执行obj = Class1()obj[1:2:3] # 对象切片,会自动执行__getitem__(self, item) 函数,并将[start:stop,step] 传递给 slice 对象obj[1:2:3] = [1, 2, 3, 4, 5] # 切片赋值,会自动执行__setitem__(slef,key,value) 函数,并将 [start:stop,step] 传递给 slice 对象 key; 值赋给 valuedel obj[1:2:3] # 切片删除,会自动执行__delitem__(self, key) 函数,并将[start:stop,step] 传递给 slice 对象
- 有序字典:
-
- 字典没有提供有序的功能,需要在字典类的基础上进行操作
- 实际是字典的key有序,即将key放在列表中
class Mydic(dict):def __init__(self):self.lst = []super(Mydic, self).__init__()
def __setitem__(self, key, value):self.lst.append(key)super(Mydic, self).__setitem__(key, value)
def __str__(self):temp_lst = []for x in self.lst:dic_value = super(Mydic, self).get(x)temp_lst.append('{}:{}'.format(x, dic_value))f_dic = '{' + ','.join(temp_lst) + '}'return f_dic # __str__ 方法 return什么值,就输出什么值
# 实例化并调用obj = Mydict()obj['k1'] = 123obj['k2'] = 456obj['k3'] = 789obj['k4'] = ‘abc’print(obj) # 调用__str__ 方法,此时每次输出的都是有序字典
- 迭代方法:
- __iter__() //一个方法要想能被迭代,就要实现这个方法,且该方法返回一个迭代对象
- 可迭代对象:
- 一个实现了“迭代协议”的对象,迭代协议如下:
- __iter__() :返回iterator对象本身
- __next__(): 每当该函数被调用,返回(return)一个值,并直到StopIteration 异常时停止
- python 的 for 循环遍历过程:
- 先调用__iter__()方法,来获得迭代器
- 调用迭代器的 next()方法,获得数据,直到抛出StopIteration异常
- example:
class Class1:def __init__(self, ):self.number = 0
def __iter__(self):return self # 拥有__iter__方法的对象,就为迭代器,所以自定义迭代器通常返回对象实例自己
def __next__(self):if self.number >= 10:raise StopIterationelse:self.number += 2return self.number# 实例化并执行obj = Class1()for x in obj:print(x)
二、面向对象其它:
- isinstance(obj,Class1)
- 查看对象是否为class1的实例,或其所创建类的父类,当class为obj的父类,或class为obj的父类的父类时,返回True
- issubclass(class2,Class1)
- 返回布尔值,查看class2是否为class1的子类
- super(myclass, self).function(args)
- 调用并执行 myclass父类中的function方法
# 经常用于执行父类中与子类同名的方法:
class C1:def f1(self):print('c1.f1')
class C2(C1):
def f1(self):
# 表示主动执行父类中的f1方法super(C2,self).f1() # 第一中方法print('c2.f1')
obj = C2()
二、扩展:旧框架新增功能
- 不用装饰器原因:装饰器需要在函数上方加@,即会改动源代码
- 使用super:
- 业务场景:
--------------------------------公司代码场景# 老员工NB代码核心逻辑vim backend/commons......nb的代码,其中有个Foo类
# 程序配置文件vim settings.pyPath = 'bakend.commons' // 模块所在路径ClassName = 'Foo' //所需要的目标类
# 老员工NB代码入口vim index.pyfrom settings import Path 类所在模块的路径from settings import ClassName 所需要调用的类名
def excute():module = __import(Path,fromlist=True) # 从路径中找到目标模块cls = getattr(commons, ClassName) # 从目标模块中找到目标类obj = cls()obj.func1() # 领导要求对该功能进行封装 ,该功能存在于核心逻辑中,核心逻辑文件不能修改,该入口文件也不能改,总之什么都不能改
if __nam__ == '__main__':excute()
- 更改:
- 思想:
- 通过继承的方式。来实现在老代码中添加功能
- 即只需要继承老员工的类,对目标方法进行修改后,更改配置文件类的指向即可
- 图示
- 过程:
# 封装功能的文件vim lib.pyfrom backend.commons import Foo # 导入要被封装的类
class my_class(Foo): # 新建一个类,并继承老员工的类def func1(self):print('before')super(my_class, self).func1() //执行老员工Foo类中的原本的功能print('after') // 新增功能# 修改配置文件vim setting.pyPath = 'lib'ClassName = 'my_class'