Python--面向对象编程

  • 面向对象入门
    •   一款简单自动运行的小游戏模拟;在一维的地图上,有一只虫子和一直蚂蚁。每一次他们都走过一个-3,-2,2,3个随机单位的举例(选定走法,若达到地图边界则放弃移动)。当蚂蚁和虫子处于同一个位置的时候蚂蚁吃掉虫子,游戏结束
      •   PO(面向过程):虫子的初始位置,蚂蚁的初始位置,进入循环,按照规则,蚂蚁和虫子移动位置,直到蚂蚁虫子在同一位置游戏结束
        #coding=gbk
        
        import random
        
        ant_point=random.randint(0,20)#位置初始化
        worm_point=random.randint(0,20)
        print('ant_point:',ant_point,'worm_point:',worm_point)#打印初始位置
        
        step=[-2,+2,-3,+3]#只能移动的步数
        
        while ant_point!=worm_point:
            astep=random.choice(step)#调用函数随机选择移动的步数
            if 0<ant_point+astep<=20:
                ant_point+=astep
                
            astep=random.choice(step)
            if 0<worm_point+astep<=20:
                worm_point+=astep
        print('ant_point:',ant_point,'worm_point:',worm_point)#打印走动之后的位置
      •   OO(面向对象):对象:地图,虫子,蚂蚁;地图是唯一的只需要记录蚂蚁虫子的位置;蚂蚁和虫子直到自己的位置;蚂蚁虫子按规则移动;定义蚂蚁虫子地图三个类;主程序中实例化
        #coding=gbk
        import random
        
        class Sprite:
            step=[-2,2,-3,3]
            def __init__(self,gm,point=None):#默认构造参数
                self.gm=gm
                if point is None:
                    self.point=random.randint(0,20)
                else:
                    self.point=point
            def jump(self):
                astep=random.choice(Sprite.step)
                if 0 <= self.point + astep<= 20:
                    self.point+=astep
                
        class Ant(Sprite):
            def __init__(self,gm,point=None):
                super().__init__(gm, point)
                self.gm.set_point('ant',self.point)
                
            def jump(self):
                super().jump()
                self.gm.set_point('ant',self.point)
               
        class Worm(Sprite):
            def __init__(self,gm,point=None):
                super().__init__(gm, point)
                self.gm.set_point('worm',self.point)
                
            def jump(self):
                super().jump()
                self.gm.set_point('worm',self.point)
                 
        class gamemap:
            def __init__(self):  
                self.ant_point=None
                self.worm_point=None
            def catched(self):
                print('ant:',self.ant_point,'worm :',self.worm_point)
                if self.ant_point is not None and self.worm_point is not None and self.ant_point==self.worm_point:
                    return True
            def set_point(self,src,point):
                if src=='ant':
                    self.ant_point=point
                if src=='worm':
                    self.worm_point=point
                    
        if __name__=='__main__':
            gm=gamemap()
            worm=Worm(gm)
            ant=Ant(gm)
            while not gm.catched():
                worm.jump()
                ant.jump()
                
    •   简单的类
      • #coding=gbk
        class TestClass:#定义一个空类
            pass
        tc=TestClass()#类的实例化
        print(tc)
        
        class TestClass_a:
            def db(self):
                self.height=20
                print(self.height)
        
        tc=TestClass_a()
        print(tc)#打印出了类的地址
        
        #类的说明   查看方式    类名.__doc__或者help(类名)
        class tss: 
            '''    #类的说明是在类名下面用'''  '''   包围起来的内容
            这是一个类的说明
            '''
            pass
        print(tss.__doc__)  #打印类的说明
        print(help(tss))
        
        #新式类和经典类
        #①python3.x版本中都是新式类,不用继承Object
        #②python2.x版本中都是经典类,继承object为新式类
        #③区别:经典类为深度优先,新式类为广度优先
    •   类的属性
      •   私有属性
        •   单下划线
          #私有属性:使用__(双下划线)开头的变量名加以标志,只有类对象自己能访问;使用_(单下划线)开头的变量名加以标识,只有类对象和其子类能够访问
          class A:
              def __init__(self):
                  self._ab=0 #__ab表示的是私有属性   ,python对__ab进行名称修改,在外部无法看见
              def info(self):
                  print(self._ab)
          a=A()
          a.info()
          a._ab=3  #私有属性在类的外部不能对他修改     创建了一个新的实例化属性
          a.info()  #单下划线开头的私有属性在外部可以访问,可以进行属性值的修改
          print(a._ab)
        • 双下滑线
        • #私有属性:使用__(双下划线)开头的变量名加以标志,只有类对象自己能访问;使用_(单下划线)开头的变量名加以标识,只有类对象和其子类能够访问
          class A:
              def __init__(self):
                  self.__ab=0 #__ab表示的是私有属性   ,python对__ab进行名称修改,在外部无法看见
              def info(self):
                  print(self.__ab)
          a=A()
          a.info()
          a.__ab=3  #私有属性在类的外部不能对他修改     创建了一个新的实例化属性
          a.info()
          print(a.__ab)
      •   实例化属性
      • #coding=gbk
        class testcss:
            cssa='class-attribe'    #定义类属性    不同类实例中类属性都是一样的
            #一般不建议在__init__方法之外去创建和初始化实例属性
            #一般也不建议在类外定义和修改实例属性,修改可以定义单独的方法进行修改
            def __init__(self):
                self.a=0  #a,b都是实例属性
                self.b=0
                
            def info(self):
                print('a is :'+str(self.a),'b is ;',self.b,'cssa is :',self.cssa)
                
        if __name__=='__main__':
            tc=testcss()
            tcc=testcss()
            tc.info()
            tcc.info()
            testcss.cssa='woshileishuxing'
            tc.info()
            tcc.info()
            tc.color='red' #在类外定义实例属性
            print(tc.color)
      • __doc__   __name__    __dict__    __module__   __base__   这些特殊属性
      • 类的能动性(方法)
      • #coding=gbk
        
        #类的方法调用
        #在内部调用:self.方法名.参数列表                    在外部调用  对象名.方法名.参数列表
        class washer:
            def __init__(self,water=10,scout=2):#构造方法名称是不变的,   默认参数值
                self.water=water
                self.scout=scout
            def set_water(self,water):
                self.water=water
            def set_scout(self,scout):
                self.scout=scout
            
            def add_water(self,):
                print('add water :',self.water)
        #         self.water=water
            def add_scout(self,):
        #         self.scout=scout
                print('add scout :',self.scout)
            def start_wash(self):
                self.add_scout()
                self.add_water()
                print('start wash...')
        if __name__=='__main__':
            a=washer()
            a.start_wash()#默认构造函数产生
            b=washer(100,8)#自主构造产生
            b.start_wash()
            
    •   深入类的属性
      •   同名的类属性和实例属性
        • #coding=gbk
          
          #一个类中存在同名的类属性:①当以实例名.属性名引用时,优先引用实例属性;②以类名.属性名引用时,只能引用类属性
          # class A:
          #     a=0
          #     def __init__(self):
          #         self.a=1
          #         self.b=1
          # a=A()
          # print(a.a)
          # print(a.b)
          # print(A.a)
          # # print(A.b)#不存在类属性b,报错
          # 
          # #反射    hasattr(obj_bame,'属性名')测试是否有这个属性名     setattr(obj-name,'属性名',值)  设置属性值      getattr(obj_name,'属性名')  得到属性值
          # print(getattr(a, 'a'))
          # print(setattr(a, 'a', 20))
          # print(a.a)
          # print(hasattr(a, 'a'))
          
          #属性包装--将方法包装成属性,以隐藏相关实现
          #可读:@property     可写:@<property-name>.setter      可删:@<property-name>.deleter
      •   属性的包装
        • #coding=gbk
          
          
          #属性包装--将方法包装成属性,以隐藏相关实现,我们可以通过将方法包装成一个属性,然后通过调用这个属性相当于调用这个方法
          #可读:@property     可写:@<property-name>.setter      可删:@<property-name>.deleter
          class washer:
              def __init__(self,water=10,scout=2):#构造方法名称是不变的,   默认参数值
                  self._water=water
                  self.scout=scout
                  self.year=2010
                  
              #将water方法变成了属性,可以读取的属性
              #属性包装,使用实例.属性名调用可以去使用这种方式写
              @property
              def water(self):
                  return self._water
              
              #将方法变成属性,可以修改的属性
              @water.setter
              def water(self,water):
                  if 0<water<=500:
                      self._water=water
                  else :
                      print('set water wrong,water is low')
                      
              @property
              def total_year(self):
                  return 2015-self.year
              
              def set_water(self,water):
                  self.water=water
              def set_scout(self,scout):
                  self.scout=scout
              
              def add_water(self,):
                  print('add water :',self.water)
          #         self.water=water
              def add_scout(self,):
          #         self.scout=scout
                  print('add scout :',self.scout)
              def start_wash(self):
                  self.add_scout()
                  self.add_water()
                  print('start wash...')
                  
          if __name__=='__main__':
              w=washer()
              print(w.water)
              w.water=123
              print(w.water)
              print(w.total_year)
              
        • 描述符
        • #coding=gbk
          
          #描述符:将实现特殊协议方法的类作为另一个类的类属性,用来拦截和控制属性访问并且可以重复使用
          #  协议方法:__get__()
          #         __set__()
          #         __delete__()
          #以上三种协议都实现的:数据描述符
          #部分实现的称为非数据描述符,所有的类成员函数都是非数据描述符(都可能实现一个或多个协议方法)
          class NonNeg:
          #协议方法
              def __init__(self,default=0):
                  self.default = default
          #这三种协议配套使用
              def __get__(self,instance,owner):
                  return self.default
          
              def __set__(self,instance,val):
                  if val > 0:
                      self.default = val
                  else:
                      print("The value must be NonNegative!")
          
              def __delete__(self,instance):
                  pass
          
          class Movie:
              rating = NonNeg()
              score = NonNeg()
          
          if __name__ == '__main__':
              m = Movie()
              print('rating:',m.rating)
              print('score:',m.score)
              m.rating = 80
              print('rating:',m.rating)
              m.score = -3
              print('score:',m.score)
              
        • __call__()让类的实例和函数一样可以调用
        • >>> class tst:
              def __call__(self):
                  print('call')
          
                  
          >>> t=tst()
          >>> t()
          call
          >>> 
    •   类方法和静态方法
      •   静态方法
        • ①用 staticmethod装饰器装饰  ②参数不用self  ③不能引用或者访问实例属性 ④可以通过 类.类变量 访问类属性 ⑤可以用类或者类实例来调用静态法
      •   类方法
        •   ①装饰器@classmethod  必须提供参数cls(这个参数可以是类名)②不能引用或者访问实例属性(因为实例属性在没有实例化之前是不存在的)③可以用类实例,类调用
        • #coding=gbk
          
          class Washer:
              company = "Le Xi" #类属性
              def __init__(self,water=10,scour=2):
                  self._water = water
                  self.scour = scour
                  self.year = 2010
          
              @staticmethod   #静态方法的装饰器
              def spins_ml(spins): #静态方法可以没有参数,一定没有self参数
                  # print("company:",Washer.company)  调用类.类属性可以
                  # print('year:',self.year) 静态方法中不能引用实例属性
                  return spins * 0.4
          
              @classmethod   #类方法装饰器  必须提供参数cls,
              def get_washer(cls,water,scour):  #这里的cls可以换成类名字
                  print("company:",Washer.company)
                  #不能引用或者访问实例属性
          #       print('year:',self.year)
          
                  return cls(water,cls.spins_ml(scour))
          
          
              @property
              def water(self):
                  return self._water
          
              @water.setter
              def water(self,water):
                  if 0 < water <=500:
                      self._water = water
                  else:
                      print("set Failure!")
          
              @property
              def total_year(self):
                  return 2015 - self.year
              
          
              def set_water(self,water):
                  self.water = water
          
              def set_scour(self,scour):
                  self.scour = scour
          
              def add_water(self):
                  print('Add water:',self.water)
          
              def add_scour(self):
                  print('Add scour:',self.scour)
          
              def start_wash(self):
                  self.add_water()
                  self.add_scour()
                  print('Start wash...')
          
          if __name__ == '__main__':
              # print(Washer.spins_ml(8)) 通过类.类方法调用静态方法
              # w = Washer()  用类的实例调用静态方法
              # print(w.spins_ml(8))
              # w = Washer(200,Washer.spins_ml(9)) 在实例化的手去调用静态方法
              # w.start_wash()
              w = Washer.get_washer(100,9) #类调用类方法
              w.start_wash()
    •   类继承
      •   类继承方式
      • >>> class A:
            pass
        
        >>> A.__base__     类A的父类:默认为Object
        <class 'object'>
        >>> class B(A):    B继承A
            pass
        
        >>> B.__base__
        <class '__main__.A'>
        >>> class C:
            pass
        
        >>> class D(A,C):  D继承A,C
            pass
        D.__bases__
        (<class '__main__.A'>, <class '__main__.C'>)
      • 单继承
      •  1 #coding=gbk
         2 class Washer:
         3     company = "Le Xi"
         4     def __init__(self,water=10,scour=2):
         5         self._water = water
         6         self.scour = scour
         7 
         8     @staticmethod
         9     def spins_ml(spins):
        10         return spins * 0.4
        11 
        12     @classmethod
        13     def get_washer(cls,water,scour):
        14         return cls(water,cls.spins_ml(scour))
        15 
        16     @property
        17     def water(self):
        18         return self._water
        19 
        20     @water.setter
        21     def water(self,water):
        22         if 0 < water <=500:
        23             self._water = water
        24         else:
        25             print("set Failure!")
        26 
        27     def set_scour(self,scour):
        28         self.scour = scour
        29 
        30     def add_water(self):
        31         print('Add water:',self.water)
        32 
        33     def add_scour(self):
        34         print('Add scour:',self.scour)
        35 
        36     def start_wash(self):
        37         self.add_water()
        38         self.add_scour()
        39         print('Start wash...')
        40         
        41 class washerdry(Washer): #继承类
        42     
        43     #这是单继承先是在子类中寻找方法,找不到再依次向上查找方法。
        44     #在多重继承的时候,查找方法会采用广度优先的查找方式进行查找
        45     def dry(self):
        46         print('dry clothes...')
        47     
        48     def start_wash(self):#重载父类的方法
        49         print('...')
        50         super().start_wash()#在子类中调用父类的方法
        51         print('...')
        52     
        53 if __name__=='__main__':
        54     w=washerdry()
        55     w.start_wash()
        56     print(w.scour,w.company)
        57     w.dry()
        View Code
      • 多重继承:查找调用函数的方式,广度优先的方式,从最近的开始进行查找调用
      • >>> class A:
            def foo(self):
                print('aaa')
        
                
        >>> class B:
            def foo(self):
                print('B bbb')
        
                
        >>> class C(A,B):
            pass
        
        >>> c=C()
        >>> c.foo()
        aaa
        >>> class D(B,A):
            pass
        
        >>> D().foo()
        B bbb
        >>> 
    •   类的特殊方法
      •   深入理解类
      • >>> class Empty:
            pass
        
        >>> ept=Empty   类和一个变量进行绑定
        >>> ept()
        <__main__.Empty object at 0x0000023235576320>
        >>> ept.foo='foo'   为类增加属性
        >>> ept.foo
        'foo'
        >>> def use_class(mc):   把类作为函数的参数传递
            return mc()
        
        >>> use_class(Empty)   类作为一个对象
        <__main__.Empty object at 0x0000023235569940>
        >>> 
      • 元类:类的创建者和管理者,所有的类都是元类的实例
      • >>> class A:
            pass
        #通过isinstance方法可以得出每个类都是元类的实例
        >>> isinstance(A,type)
        True

         类的实例化过程

        #coding=gbk
        
        #实例化时:先调用__new__()方法,返回类的实例,然后再调用__init__方法进行初始化
        class Custom:
            def __init__(self):
                print('init method.')
            def __new__(cls,*args,**kwargs):
                print('new instance.')
                return object.__new__(cls,*args,**kwargs)
        if __name__=='__main__':
            Custom();
        #coding=gbk
        
        #定义自定义元类
        #步骤;继承type类,新建__new__(),调用__init__()方法
        class MyMeta(type):
            def __init__(self,name,bases,dicts):#为每一个使用该类的类添加一个方法和属性
                print('Init Instance.')
            #为字典添加键的方式来为使用这个元类的类创建一个方法
            def __new__(cls,name,bases,dicts):
                dicts['info'] = lambda self:print('Djx.')#匿名函数lambda
                res = type.__new__(cls,name,bases,dicts)#用type创建类
                res.company = 'MaiZi'#外部添加一个类属性
                return res#返回类
        
        class custom(metaclass=MyMeta):
            pass
        
        if __name__ == '__main__':
            cus = custom()
            cus.info()
            print(cus.company)
        
        class cus:
            __metaclass__ = MyMeta
            pass
        
        __metaclass__ = MyMeta

         类的一些方法

        #coding=gbk
        
        #构造序列
        class myseq:
            def __init__(self):
                self.lseq=['I','II','III','IIII']
            def __len__(self):
                return len(self.lseq)
            def __getitem__(self,key):
                if 0 < key < 4:
                    return self.lseq[key]
                
        if __name__=='__main__':
            m=myseq()
            for i in range(4):
                print(m[i])
        #构造迭代器  
        class myiter:
            def __init__(self,start,end):
                self.count=start
                self.end=end
                
            def __iter__(self):
                return self
            def __next__(self):
                if self.count < self.end:
                    r=self.count
                    self.count+=1
                    return  r
                else:
                    raise StopIteration
                
        if __name__=='__main__':
            for i in myiter(1,10):
                print(i)
         #构造可比较类      
        class Point:
            def __init__(self,x,y):
                self.x = x
                self.y = y
        
            def __lt__(self,oth):
                return self.x < oth.x
        
            def __gt__(self,oth):
                return self.y > oth.y
        
        if __name__ == '__main__':
            pa = Point(0,1)
            pb = Point(1,0)
            print(pa < pb)
            print(pa > pb)
        View Code
    •   鸭子类型
      •   多态:一种类型具有多种类型的能力,允许不同的对象对同一消息做出灵活的反应,以一种通用的方式对待可使用的对象,非动态语言必须通过继承和接口实现
      •   通过继承实现多态,子类通过重载父类的方法实现多态
        • #对于继承了同一个类的子类,当父类可以在函数中最为参数调用时,子类也是同样可以的,这就是通过继承实现多态
          >>> class  animal:
              def move(self):
                  print('aaa')
          
                  
          >>> class dog(animal):
              pass
          
          >>> def move(obj):
              obj.move()
          
              
          >>> a=animal()
          >>> move(a)
          aaa
          >>> d=dog()
          >>> move(d)
          aaa

          通过重载父类的方法实现多态

          >>> class cat(animal):
          def move(self):
          print('aaaaaaa')


          >>> class sheep(animal):
          def move(self):
          print('aaaa')


          >>> move(sheep())
          aaaa
          >>> move(cat())
          aaaaaaa

           
      •   动态类型语言与鸭子类型::变量绑定的类型具有不确定性,函数和方法可以接受任何类型的单数,调用方式是不检查提供的参数类型,调用是否成功由参数的方法和属性确定
      • #coding=gbk
        
        class Point:
            def __init__(self,x,y):
                self.x = x
                self.y = y
        
            def __add__(self,oth):
                return Point(self.x + oth.x , self.y + oth.y)
        
            def info(self):
                print(self.x,self.y)
        
        # class D3Point(Point):
        #     def __init__(self,x,y,z):
        #         super().__init__(x,y)
        #         self.z = z
        
        #     def __add__(self,oth):
        #         return D3Point(self.x + oth.x , self.y + oth.y , self.z + oth.z)
        
        #     def info(self):
        #         print(self.x,self.y,self.z)
        
        class D3Point:#动态类型绑定:鸭子动态
            def __init__(self,x,y,z):
                self.x = x
                self.y = y
                self.z = z
        
            def __add__(self,oth):
                return D3Point(self.x + oth.x , self.y + oth.y , self.z + oth.z)
        
            def info(self):
                print(self.x,self.y,self.z)
        
        
        def myadd(a,b):#只要函数的类型可以调用a+b功能,就能传递参数实例
            return a + b
        
        if __name__ == '__main__':
            myadd(Point(1,2),Point(3,4)).info()
            myadd(D3Point(1,2,3),D3Point(4,5,6)).info()
        View Code
    •   设计模式:用来提高代码复用和可维护性的方式,很好的指导软件设计过程,是成功的软件设计模式和体系结构,用于解决特定类型的问题的面向对象编程模型
      •   python与设计模式
        •   有的模式已经在语言中内置了,比如迭代器模式;单例模式可以直接用模块级变量来实现;普通工厂模式可以直接通过传入类名作为参数实现
        •   单例设计
        • #coding=gbk
          #普通的单例设计模式
          # class singleclass:
          #     def __init__(self,x=0):
          #         self.x=0
          #         
          # sc=singleclass()  #模块级变量sc,在其他的程序中使用sc,无论什么时候使用,都是指向singleclass这个单一的实例对象
          # 
          # def tsc():
          #     print(sc.x)
          #     sc.x=10
          #     print(sc.x)
          #     
          # 
          # def tsc_2():
          #     print(sc.x)
          #     sc.x=9
          #     print(sc.x)
          #     
          # if __name__=='__main__':
          #     tsc()
          #     tsc_2()
          
          #通过修改类的父类的__new__()方法来实现单例模式
          class singleton:
              def __new__(cls,*args,**kwargs):
                  if not hasattr(cls,'_sgl'):  #用类的类属性指定一个类的单实例 ,测试这个类是否有一个类属性
                      cls._sgl=super().__new__(cls,*args,**kwargs)   #调用父类的new方法来实例化一个类,赋值给类属性cls。sgl
                  return cls._sgl
              
          if __name__=='__main__':
              sa=singleton()
              sb=singleton()
              print(id(sa))#两个类的实例化是一个单一的实例
              print(id(sb))
          View Code
        •   工厂模式
        • #coding=gbk
          class ab:
              a=3
          class ac:
              a=0
          class myfactory:  #建立工厂类
              def get_instance(self,ins):
                  return ins()#对这个变量代表的类进行实例化
              
          if __name__=='__main__':
              mf=myfactory()
              print(type(mf.get_instance(ab)))
              print(type(mf.get_instance(ac)))
          View Code
        •   策略模式:让一个对象的某个方法可以随时改变。不用更改对象代码;对于动态类型的python不需要定义接口,基本的实现方法:用类作为参数传递;最简单的实现方法:函数最为参数传递
        • #coding=gbk
          class moveable:
              def move(self):
                  print('move...')
                  
          class moveonfeet(moveable):
              def move(self):
                  print('feet move...')
          
          class moveonwheels(moveable):
              def move(self):
                  print('move on wheels move,,,')
                  
          class moveobj:
              def set_move(self,moveable):#通过set——move修改move方法
                  self.moveable=moveable()#实例化
              def move(self):
                  self.moveable.move()
              
          if __name__=='__main__':
              m=moveobj()
              m.set_move(moveable)
              m.move()
              m.set_move(moveonfeet)
              m.move()
              m.set_move(moveonwheels)
              m.move()
          View Code
        • #coding=gbk
          def movea():
              print('a moveing...')
          def moveb():
              print('b moving...')
                  
              #传递的参数是一个函数
          class moveobj:
              def set_move(self,moveable):#动态类型邦迪
                  self.moveable=moveable     #函数不需要实例化
              def move(self):
                  self.moveable()
              
          if __name__=='__main__':
              m=moveobj()
              m.set_move(movea)
              m.move()
              m.set_move(moveb)
              m.move()
              m.set_move(moveb)
              m.move()
          View Code
    •   设计模式2
      •   装饰模式:通过继承可以获得父类的属性,可以通过重载修改其方法;装饰模式可以不以继承的方式而动态的修改类的方法;装饰模式可以不以继承的方式而返回一个呗修改的类
      • #coding=gbk
        class BeDeco:#装饰类
            def be_edit_fun(self):
                print('Source fun.')
        
            def be_keep_fun(self):
                print('Keep fun.')
        
        class Decorater:#装饰类
            def __init__(self,dec):#传入修改的类的名称
                self._dec = dec()#实例化传入类
        
            def be_edit_fun(self):#定义和被装饰类的同样的方法
                print('Start...')
                self._dec.be_edit_fun()#修改的方法
        
            def be_keep_fun(self):
                self._dec.be_keep_fun()#保留的方法
        
        if __name__ == '__main__':
            bd = BeDeco()
            bd.be_edit_fun()
            bd.be_keep_fun()
        
            dr = Decorater(BeDeco)#传入被修饰的类
            dr.be_edit_fun()
            dr.be_keep_fun()
        View Code
      • #coding=gbk
        class Water:
            def __init__(self):
                self.name = 'Water'
        
            def show(self):
                print(self.name)
        
        class Deco:  #要被装饰类
            def show(self):
                print(self.name)
        
        class Sugar(Deco):
            def __init__(self,water):
                self.name = 'Sugar'
                self.water = water
        
            def show(self):
                print(self.name)
                print(self.water.name)
        
        class Salt(Deco):
            def __init__(self,water):
                self.name = 'Salt'
                self.water = water
        
            def show(self):
                print(self.name)
                print(self.water.name)
        
        if __name__ == '__main__':
            w  = Water()
            s = Sugar(w)#利用sugar装饰了water
            s.show()
        
            s = Salt(w)#利用salt装饰了water
            s.show()
        View Code
      • #coding=gbk
        def deco(a_class): #类装饰器
            class NewClass:
                def __init__(self,age,color):
                    self.wrapped = a_class(age)
                    self.color = color
                def display(self):
                    print(self.color)
                    print(self.wrapped.age)
            return NewClass
        
        @deco   #装饰器语法  将cat类传入上述deco函数,包装完以后返回新的包装的类
        class Cat:
            def __init__(self,age):
                self.age = age
        
            def display(self):
                print(self.age)
        
        if __name__ == '__main__':
            c = Cat(12,'black')
            c. display()
        View Code
    •   通过组合来构建复杂的对象
      •   组合:零件:基础类;机器:包含其他类的类。组合:零件+机器;体现自下而上的编程方法
      •   组合案例--雪人:
      • #coding=gbk
        class Shape:#shape  不带角度的基类
            def __init__(self,cvns,points):#cvns  绘制图形的画布参数     points坐标参数
                self.cvns = cvns
                self.points = points
                self.pid = None    #在画布当中的id号
        
            def delete(self):  #将当前的图形删除
                if self.pid:
                    self.cvns.delete(self.pid)
        
        class ShapeAngles(Shape):#带角度的基类
            def __init__(self,cvns,points,angles=(10,170)):#angles  是角度   图形角度
                super().__init__(cvns,points)
                self.angles = {'start':angles[0],'extent':angles[1]}
        
        class HatTop(Shape):#无角度类
        
            def draw(self):#绘制函数
                self.pid = self.cvns.create_oval(*self.points)#绘制圆形的方法,返回id
        
        class HatBottom(Shape):
                
            def draw(self):
                self.pid = self.cvns.create_polygon(*self.points)
        
        class Hat:#帽子组合类
            def __init__(self,cvns,start_point,w,h):
                self.cvns = cvns
                self.start_point = start_point
                self.w = w
                self.h = h
                self.ht = HatTop(self.cvns,self.ht_cacu())#实例化帽子顶部
                self.hb = HatBottom(self.cvns,self.hb_cacu())#实例化帽子底部
        
            def draw(self):
                self.ht.draw()
                self.hb.draw()
        
            def delete(self):
                self.ht.delete()
                self.hb.delete()
            
            def ht_cacu(self):#计算位置
                r = self.h / 3 / 2
                x1 = self.start_point[0] + self.w /2 - r
                y1 = self.start_point[1]
                x2 = x1 + 2 * r
                y2 = y1 + 2 * r
                return x1,y1,x2,y2
        
            def hb_cacu(self):
                x1 = self.start_point[0] + self.w / 2
                y1 = self.start_point[1] + self.h / 3
                x2 = self.start_point[0] + self.w / 3
                y2 = self.start_point[1] + self.h
                x3 = self.start_point[0] + self.w / 3 * 2
                y3 = y2
                return x1,y1,x2,y2,x3,y3
        
        class Sense(ShapeAngles):
            def draw(self):
                self.pid = self.cvns.create_arc(*self.points,**self.angles)#绘制一条弧线
        
        class Face(HatTop):#圆和帽子顶部类似
            pass
        
        class Head:
            def __init__(self,cvns,start_point,w,h):
                self.cvns = cvns
                self.start_point = start_point
                self.w = w
                self.h = h
                eye0_points = self.eye0_cacu()
                dx = self.h / 3 + self.h / 9
                eye1_points = (eye0_points[0] + dx,eye0_points[1],
                               eye0_points[2] + dx,eye0_points[3])
                self.face = Face(self.cvns,self.face_cacu())
                self.eye0 = Sense(self.cvns,eye0_points)
                self.eye1 = Sense(self.cvns,eye1_points)
                self.mouth = Sense(self.cvns,self.mouth_cacu(),(-10,-170))
        
            def draw(self):
                self.face.draw()
                self.eye0.draw()
                self.eye1.draw()
                self.mouth.draw()
        
            def face_cacu(self):
                x1 = self.start_point[0] + (self.w - self.h) / 2
                y1 = self.start_point[1]
                x2 = x1 + self.h
                y2 = y1 + self.h
                return x1,y1,x2,y2
        
            def eye0_cacu(self):
                left_point = (self.start_point[0] + (self.w - self.h) / 2,self.start_point[1])
                x1 = left_point[0] + self.h / 6
                y1 = left_point[1] + self.h / 3
                x2 = x1 + self.h / 3
                y2 = left_point[1] + self.h / 2
                return x1,y1,x2,y2
        
            def mouth_cacu(self):
                left_point = (self.start_point[0] + (self.w - self.h) / 2,self.start_point[1])
                x1 = left_point[0] + self.h / 3
                y1 = left_point[1] + 2 * self.h / 3
                x2 = x1 + self.h / 3
                y2 = y1 + self.h / 3 / 2
                return x1,y1,x2,y2
        
        class BodyOutline(HatTop):#
            pass
        
        class Button(HatTop):#
            pass
        
        class Body:
        
            def __init__(self,cvns,start_point,w,h):
                self.cvns = cvns
                self.start_point = start_point
                self.w = w
                self.h = h
                self._button_size = 10
                self.buttons = []
                self.bo = BodyOutline(self.cvns,self.body_cacu())
                for pnts in self.all_button_points():
                    self.buttons.append(Button(self.cvns,pnts))
        
            def draw(self):
                self.bo.draw()
                for bttn in self.buttons:
                    bttn.draw()
        
            def body_cacu(self):
                x1,y1 = self.start_point
                x2 = x1 + self.w
                y2 = y1 + self.h
                return x1,y1,x2,y2
        
            def button0_cacu(self):
                x1 = self.start_point[0] + self.w / 2 - self._button_size
                y1 = self.start_point[1] + self.h / 5 - self._button_size
                x2 = x1 + 2 * self._button_size
                y2 = y1 + 2 * self._button_size
                return x1,y1,x2,y2
        
            def move_dy(self,points,size):
                y1 = points[1] + size
                y2 = points[3] + size
                return points[0],y1,points[2],y2
        
            def all_button_points(self):
                b0_points = self.button0_cacu()
                size = self.h / 5
                points = []
                for i in range(4):
                    points.append(self.move_dy(b0_points,i * size))
                return points
        
            def set_button_size(self,size):
                self._button_size = size
        
        class Snow:
        
            def __init__(self,cvns,points,w=150,h=450):
                self.cvns = cvns
                self.points = points
                self.w = w
                self.h = h
                self.hat = Hat(self.cvns,self.points,self.w,self.h / 6)
                self.head = Head(self.cvns,(self.points[0],self.points[1] + self.h / 6),self.w,self.h / 3)
                self.body = Body(self.cvns,(self.points[0],self.points[1] + self.h / 2),self.w,self.h / 2)
        
            def draw(self):
                self.hat.draw()
                self.head.draw()
                self.body.draw()
        
        if __name__ == '__main__':
            import tkinter
            root = tkinter.Tk()
            cvns = tkinter.Canvas(root,width=600,height=665,bg='white')
            cvns.pack()
            snow = Snow(cvns,(10,5),300,660)
            snow = snow.draw()
            root.mainloop()
        View Code

  

原文地址:https://www.cnblogs.com/Kobe10/p/5708393.html