object_funs.py

#__init__ 构造方法,双下划线
#__del__ 析构方法,在对象就要被垃圾回收前调用。但发生调用
#的具体时间是不可知的。所以建议尽量避免使用__del__
print('-------example1')
class A:
    def __init__(self):
        self.a='a'
    def printA(self):
        print(self.a)
class B(A):
    def __init__(self):
        #A.__init__(self)   未绑定方法,自由提供self参数
                #super(B, self).__init__()
        self.b='b'
    def printB(self):
        print(self.b)
b=B()
try:
        b.printA()      #注释后,没有.a属性
except Exception as e:
        print(e)
#B继承A后,构造方法覆盖了A的构造方法,所以b.printA()没有self.a的属性。
#旧版python 方法:加上注释的未绑定方法就好
#新式类方法:注释的super 方法。先继承会覆盖后继承
print('-------example2')
class A:
    def __init__(self):
        self.chr='a'
    def printA(self):
        print(self.chr)
class AA:       #继承没有
    def __init__(self):
        A.__init__(self)    #未绑定方法
    def printAA(self):
        print(self.chr)
aa=AA()
aa.printAA()    #得到 a (不继承A也可以调用A的构造函数?要用printA就要继承)
print('-------example3')
#super 的多继承
#即使类已经继承多个超类,它也只需要使用一次super函数(但要保证所有的超类的构造方法都使用了super)
#super(TYPE, self).method调用的是mro列表中第一个,也即继承列表第一个类的方法。这个没有举例
class A:
    def __init__(self):
        self.a='a'
    def printA(self):
        print(self.a)
class B:
    def __init__(self):
        self.b='b'
    def printB(self):
        print(self.b)
class C(A,B):
    def __init__(self):
        super(C,self).__init__()
        self.c='c'
    def printC(self):
        print(self.c)

c=C()
c.printA()
try:
        c.printB()  #报错,没有.b属性
except Exception as e:
        print(e)
#解决方法,在所有超类里使用super。只在B中使用super还是不行
class A:
    def __init__(self):
        super(A, self).__init__()
        self.a='a'
    def printA(self):
        print(self.a)
class B:
    def __init__(self):
        super(B, self).__init__()
        self.b='b'
    def printB(self):
        print(self.b)
class C(A,B):
    def __init__(self):
        super(C,self).__init__()
        self.c='c'
    def printC(self):
        print(self.c)

print('-------example4')
#实现序列,映射
#__len__(self), __getitem__(self,key), __setitem__(self,key,value), __delitem__(self,key)
#定义后相应用len(obj),obj[key],obj[key]=value,del obj[key]
#当为一个序列,key键应该是一个整数(自己写函数检查)。对映射,可以使用任何种类的键。例子P144
#继承标准库的UserList,UserString,UserDict的上面方法
class CountList(list):
        def __init__(self,*args):
                super(CountList,self).__init__(*args)
                self.count=0
        def __getitem__(self,index):
                self.count+=1
                return super(CountList,self).__getitem__(index)

c=CountList(range(10))
c.reverse()
print(c)
del c[3:5]
print(c)
print(c.count)
print(c[2]+c[5])
print(c.count)

print('-------example5')
#property函数,统一处理类的多个属性,实现get,set,del操作。不需要为每一个属性写一个处理方法了
#绑定del 函数,可以使用 del t.all 语句
class Test:
    def __init__(self):
        self.a=0
        self.b=0
    def setAll(self, size):
        self.a, self.b=size
    def getAll(self):
        return self.a, self.b
    all=property(getAll,setAll)     #property中函数setAll的参数size
                                        #要与property返回的all一样是一个元组
t=Test()
t.all=1,2       #只有property 中绑定了setAll函数才可以赋值
print(t.all)
print(t.a)

print('-------example6')
#静态方法staticmethod,类成员方法classmethod
class A:
        @staticmethod
        def smethod():
                print('smethod')
        def cmethod(cls):
                print('classmethod')
A.smethod()
A.cmethod(A)      #这里有问题, 需要有时间查资料

print('-------example7')
#__getattribute__(self,name) __getattr__(self,name)__
#__setattr__(self,name,value) __delattr__(self,name)__ P151
#__getattribute__特殊方法,用于查询任意属性。
#__getattr__只能用来查询不在__dict__系统中的属性
#定义__getattribute__后,命令行输入a.后,不会有a的属性、方法的提示了
#定义__getattr__ 不会有这种情况
#当我们查询一个属性时,如果通过__dict__方法无法找到该属性,
#那么Python会调用对象的__getattr__方法,来即时生成该属性
class A:
    def __init__(self):
        self.a=0
        self.b=0
    def __setattr__(self,name,value):
        if name=='size':
            self.a,self.b=value
        else:
                        #这里换成self.name=value时,a=A()为什么会死循环
            self.__dict__[name]=value 
    def __getattr__(self,name):
        if name=='size':
            return self.a,self.b
        else:
            raise AttributeError
a=A()
a.size=1,2
a.size
try:
        a.c
except Exception as e:
        print(e)
#拓展1
setattr(a,'d',3)
print(a.__dict__)       #多了变量d
delattr(a,'d')
print(a.__dict__)       #少了变量d
print('-------example8')
#拓展2
class C(object):  
    a = 'abc'  
    def __getattribute__(self, *args, **kwargs):  
        print("__getattribute__() is called")  
        return object.__getattribute__(self, *args, **kwargs)  
    def __getattr__(self, name):  
        print("__getattr__() is called ")  
        return name + " from getattr"  
      
    def __get__(self, instance, owner):  
        print("__get__() is called", instance, owner)  
        return self  
      
    def foo(self, x):  
        print(x)
class C2(object):  
    d = C()
c = C()    
c2 = C2()
c.a     #__getattribute__() is called
c.zzzzzz        #__getattribute__() is called, __getattr__() is called
c2.d    #__get__() is called <__main__.C2 object at 0x026AAB30> <class '__main__.C2'>
        #<__main__.C object at 0x026AAAB0>
c2.d.a  #__get__() is called <__main__.C2 object at 0x026AAB30> <class '__main__.C2'>
        #__getattribute__() is called
#每次通过实例访问属性,都会经过__getattribute__函数。而当属性不存在时,
#仍然需要访问__getattribute__,不过接着要访问__getattr__。这就好像是一个异常处理函数。 
#每次访问descriptor(即实现了__get__的类),都会先经过__get__函数。
#object.__get__(self, instance, owner) 
#如果class定义了它,则这个class就可以称为descriptor。
#owner是所有者的类,instance是访问descriptor的实例,如果不是通过实例访问,
#而是通过类访问的话,instance则为None。
#(descriptor的实例自己访问自己是不会触发__get__,而会触发__call__,
#只有descriptor作为其它类的属性才有意义。)(所以下文的d是作为C2的一个属性被调用)
print('-------example9')
        
#自己问题例子
class Test:
    def __init__(self):
        self.a=0
        self.b=0
    def setAll(self, size):
        self.a, self.b=size
    def getAll(self):
        return self.a, self.b
    def __getattribute__(self,name):
        if name=='size1':
            return self.a,self.b
        elif name=='a':
                        #return self.a  #加上这句,调用t.a 就会死循环,这个一直进入自己
                        #return self.__dict__['a'] #报'NoneType' object is not subscriptable
            print('a visited')
            return object.__getattribute__(self,name)#加这句可以
        elif name=='b':
            print('b visited')
    def __getattr__(self,name):
        if name=='size2':
            print('size2 visited')
            return self.a,self.b
        else:
            raise AttributeError
    def __setattr__(self, name, value):
        if name=='a':
            print('a is changed')
        elif name=='b':
            print('b is changed')
        elif name=='all':
            print('all changed')
    all=property(getAll,setAll)
t=Test()
try:
    t.getAll() #出错,NoneType object is not callable, setAll也是这个错。
                #__getattribute__加上return后不会有问题
except Exception as e:
    print(e)

try:
    t.size1 #为什么返回None, None。因为__getattribute__在访问a,b时没有返回a,b的值
except Exception as e:
    print(e)
print('-------example10')

#__dict__属性
#__dict__分层存储属性。每一层的__dict__只存储该层新增的属性。
#子类不需要重复存储父类中的属性。
class bird(object):
        '__doc__ test'
        feather = True
class chicken(bird):
    fly = False
    def __init__(self, age):
        self.age = age
summer=chicken(2)
print(bird.__dict__)
print(chicken.__dict__)
print(summer.__dict__)
print(summer.__dict__['age'])
b=bird()
print(b.__dict__)      #这个是空{} feather属性存储在bird.__dict__中

print('-------example11')
#迭代器,实现__iter__(返回一个迭代器)和__next__方法
#如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常
class Fibs:
        def __init__(self):
                self.a=0
                self.b=1
        def __next__(self):
                self.a,self.b=self.b,self.a+self.b
                return self.a
        def __iter__(self):
                return self
fibs=Fibs()
for f in fibs:
        if f>1000:
                print(f)
                break
        
#从可迭代对象中获得迭代器
it=iter([1,2])
print(it.__next__())   #1
print(it.__next__())   #2
try:
    print(it.__next__())   #StopIteration
except Exception as e:
    print(e)

#把迭代器转换成序列
class Test():
        value=0
        def __next__(self):
                self.value+=1
                if self.value>10:raise StopIteration #
                return self.value
        def __iter__(self):
                return self
t=Test()
print(list(t)) #
                
        
print('-------example12')
#生成器,用函数语法定义的迭代器。任何包含yield语句的函数称为生成器
#他不是像return那样返回值,而是每次产生多个值
#生成器方法:send,throw,close
#在生成器close方法被调用后再通过生成器生成一个值会导致RuntimeError
def repe(value):
    for i in value:
        yield i
value=[i*2 for i in range(10)]
print(value) #0~18
r=repe(value)
try:
    print(r.send('a')) #TypeError: can't send non-None value to a just-started generator
except Exception as e:
    print(e)
print(r.__next__()) #r.send(None)      返回0,第一个数
print(r.send('a'))     #返回2,第2个数
for i in r:
    print(i)        #从第3个数4开始到结束
try    :
    print(r.send('a')) #报错,StopIteration
except Exception as e:
    print(e)

#生成器推导式,返回的不是列表而是生成器
g=(i*2 for i in range(2,10))    #圆括号,不是方括号
print(g.__next__())    #4

#send方法
#只有在生成器挂起后才有意义(也就是说在yield第一次被执行后)。即调用一次next__后
#如果真想对刚刚启动的生成器使用send方法,可以将None作为参数进行调用
def repe(value):
    while True:
        yield value
r=repe(4)
print(r.send(None))    #返回4
print(r.send('a'))     #返回4

def repe(value):
    while True:
        new=yield value
        print('new:',new,'value:',value)
        if new is not None:value=new
r=repe(4)
print(r.send(None))    #返回4
print(r.send('a'))     #返回a    new=a,value=4
print(r.send('aa'))    #返回aa   new=aa,value=a
原文地址:https://www.cnblogs.com/feifeidxl/p/5617895.html