python类杂项

python类杂项

OOP:Object Oriented Programming (面向对象编程)

oop就是在树中搜索属性和在函数中加入一个特殊的第一位参数self,它特殊在于总是接收作为方法调用隐含主体的实例对象

类树搜索顺序:从下到上,从左到右

使用实例属性时自动将这个实例对象传给参数self,self是进入实例对象命名空间的钩子

当给self赋值或修改时只会在实例内赋值修改,不会爬类树;而引用属性,且当实例中没有这个属性时则会爬类树寻找

python惯例类名以大写字母开头,模块名用小写字母开头

class规则是LEGB只会搜索def,模块和内置定义的变量

#one.py
class A:
    data = 999 #在其他类(非子类)要调用data必须使用A.data
    #类初始化
    def __init__(self,val):
        self.data = val
        self.b = B
    #符号重载
    #加号
    def __add__(self,other):
        return A(self.data+other)  #左加法:self+other(a+3,a传给self,3传给other)
    def __radd__(self,other):
        return A(other+self.data)   #右加法:other+self(3+a)
    def __iadd__(self,other):
        self.data += other    #原位置加法
        return self
    #字符串,打印
    def __str__(self):
        return 'A class: %s'% self.data  
    def __repr__(self):
        return 'A:%s'%self.data  
    #索引和分片
    def __getitem__(self,index):
        return index**2     #当调用X[i]时会将X作为第一个参数传入,将i作为第二个参数传入
        
    #拦截未定义属性的访问,转到B类中查找属性(不拦截赋值运算)
    def __getatrr__(self,attr)
        return getattr(self.b,attr)
    #拦截所有属性赋值并输出错误提示
    def __setattr__(self,attr,value):
        raise AttributeError(attr+'not allow') #所有的a.data = 0形式的语句都会被拦截
    #类方法
    def setdata(self,newdata):
        self.data = newdata
    def show(self):
        print(self.data)
    #当类方法第一个参数不是self是需要直接用类调用
    def display():
        print("class A display") #调用方法:A.display()
        
 #类继承
class B(A):
    #子类中的setdata方法会覆盖父类中的setdata,子类的实例对象可以用父类中的show方法
    def setdata(self,val):
        self.data = val
#two.py
#模块获取类
import one
a = one.A() 
#查看实例可访问的属性
a.__dict__  
#查看实例对象对应的类
x.__class__
#查看父类对象引用的元组,object是根类
A.__bases__
#顶层脚本测试
if __name__ == '__main__':
    #test code
#读取文档
a.__doc__

索引与分片

当调用x[i]时x会 ' [ ] ' 调用 getitem(self,index) 方法,将x传入第一个参数,i 传入第二个参数

当调用x[1:4]时[ ] 会调用getitem(self,index) 方法, ' : ' 会调用slice(index1,index2)方法将1传入index1,4传入index2,再将slice(1,4)传入getitem中的index

#区分index类型
class Indexer:
    def __getitem__(self,index):
        if isinstance(index,int):
            print('indexing')  #若index为整数则打印indexing
        else:
            print('slicing',index.start,index.stop,index.step)  #如果index是分片对象打印slcing,起始位置,结束位置和步长
 
        

可迭代对象

Python中的迭代上下文会先尝试__iter__f方法(将可迭代对象传给iter),再尝试__getitem__. 只要是__iter__方法返回的都将被视为迭代器对象,可通过不断调用next方法产生元素直到Stopiteration异常出现

yield(生成器函数,将生成的数据放到内存中,返回的指针指向第一个数据的位置),返回一个新的生成器对象自动记录局部作用域和代码位置没有next方法,iter返回它本身有next方法

#单重迭代
class Object1:
    def __init__(self,wrapped):
        self. wrapped= wrapped
        self.offset = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.offset >= len(self.wrapped):
            raise StopIteration
        else:
            item = self.wrapped[self.offset]
            self.offset += 1
            return item

 #多重迭代

 class Object2:
    
    def __init__(self,wrapped):
        self.wrapped = wrapped
    def __iter__(self):
        return Iterator(self.wrapped)
 class Iterator:
    
    def __init__(self,wrapped):
        self.wrapped = wrapped
        self.offset = 0
    def __next__(self):
        if self.offset >= len(self.wrapped):
            raise StopIteration
        else:
            item = self.wrapped[self.offset]
            self.offset +=1
            return item
#iter 加 yield 可支持多重迭代 
class Object3:
    def __init__(self,wrapped):
        self.wrapped = wrapped
    def __iter__(self):
        for i in range(len(self.wrapped)):
            yield self.wrapped[i]
        
    

  if __name__ == "__main__":
    str = "abc"
    I1 = Object1(str)
    I2 = Object2(str)
    I3 = Object3(str)
    for x in I1:
        for y in I1:
            print(x+y)   #结果为ab ac
            
    for x in I2:     
        for y in I2:
            print(x+y)   #结果为aa ab ac ba bb bc ca cb cc(iter替迭代器定义了一个新的状态对象)
            
     for x in I3:
        for y in I3:
            print(x+y)   #结果为aa ab ac ba bb bc ca cb cc(iter返回了一个生成器对象)
   
         
     
 
    
上一篇:python闭包与装饰器


下一篇:调用WCF REST服务时,使用JSON