• 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
  • 相关阅读:
    AS3 setChildIndex的bug
    android mediaplayer Should have subtitle controller already set
    添加糢糊视图
    Android Studio Gradle project sync failed
    VS2012 生成可以在XP下运行的exe文件
    JavaScript this的理解
    Adobe AIR 应用程序图标详细描述
    Ubuntu16.04下安装httpd+svn+viewVC
    win10将mongodb加入系统服务,官方源码报错问题记录
    汇图网爬虫
  • 原文地址:https://www.cnblogs.com/feifeidxl/p/5617895.html
Copyright © 2020-2023  润新知