特殊成员

一、特殊成员补充:
  • 索引、切片
    • 当对象后面加小括号,自动执行call方法
    • 当对象后面加中括号,会自动执行 item相关方法
      1. __getitem__(self,item)    
      2. __setitem__(self, key, value)
      3. __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; 值赋给 value
del 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'] = 123
    obj['k2'] = 456
    obj['k3'] = 789
    obj['k4'] = ‘abc’
    print(obj)   # 调用__str__ 方法,此时每次输出的都是有序字典

  • 迭代方法:
    • __iter__()   //一个方法要想能被迭代,就要实现这个方法,且该方法返回一个迭代对象
      • 可迭代对象:
        • 一个实现了“迭代协议”的对象,迭代协议如下:
          • __iter__() :返回iterator对象本身
          • __next__(): 每当该函数被调用,返回(return)一个值,并直到StopIteration 异常时停止
      • python 的 for 循环遍历过程:
        1. 先调用__iter__()方法,来获得迭代器
        2. 调用迭代器的 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 StopIteration
else:
self.number += 2
return 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.py
Path = 'bakend.commons' // 模块所在路径
ClassName = 'Foo'          //所需要的目标类

# 老员工NB代码入口
vim index.py       
from 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.py       
from backend.commons import Foo  # 导入要被封装的类

class my_class(Foo):         # 新建一个类,并继承老员工的类
def func1(self):
print('before')
super(my_class, self).func1()     //执行老员工Foo类中的原本的功能
print('after')  // 新增功能
# 修改配置文件
vim setting.py
Path = 'lib'
ClassName = 'my_class'





















原文地址:https://www.cnblogs.com/qiaogy/p/5818668.html