类的封装

  • super
    在py3的用法

    class A(object):
        def func(self):
            print("A")
    
    
    class B(A):
        def func(self):
            super().func()
            print("B")
    
    
    class C(A):
        def func(self):
            super().func()
            print("C")
    
    
    class D(B, C):
        def func(self):
            super(D, self).func()
            print("D")
    
    
    D().func()
    
    
    class User:
        def __init__(self, name):
            self.name = name
    
    
    class VIPUser(User):
        def __init__(self, name, level, start_date, end_date):
            super().__init__(name)
            self.level = level
            self.start_date = start_date
            self.end_date = end_date
    
    
    太白 = VIPUser('太白', 6, '2019-01-01', '2020-01-01')
    print(太白.__dict__)
    

    在py2中(新式类/经典类)中的用法

    • super是按照mro顺序来寻找当前类的下一个类
    • 在py3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名方法
    • 在py2中的新式类中,需要我们主动传递参数super(子类的名字,子类的对象).函数名()、
    • 在py2的经典类中,并不支持使用super来找下一个类
    • 在D类中找super的func,那么可以这样写 super().func()
    • 也可以这样写 super(D,self).func() (并且在py2的新式类中必须这样写)
  • 封装

    • 广义上的封装 : 把属性和方法装起来,外面不能直接调用了,要通过类的名字来调用

    • 狭义上的封装 : 把属性和方法藏起来,外面不能调用,只能在内部偷偷调用

      • 使用私有属性和方法的三种情况

        • 无法看和改

          class User:
          #     def __init__(self, name, passwd):
          #         self.usr = name
          #         self.__pwd = passwd
          # 
          # alex = User('alex', 'alexsb')
          # 
          # print(alex.__pwd)
          # # AttributeError: 'User' object has no attribute '__pwd'
          # print(alex.pwd)
          # # AttributeError: 'User' object has no attribute '__pwd'
          
          # 给一个名字前面加上了双下划綫的时候,这个名字就变成了一个私有的
          # 所有的私有的内容或者名字都不能在累的外部调用,只能在类的内部使用了
          
        • 可看不可改

          class User:
              def __init__(self, name, passwd):
                  self.user = name
                  self.__pwd = passwd
          
              def get_cwd(self):
                  return self.__pwd
          
          alex = User('alex', 'alexsb')
          print(alex.get_cwd())
          # alexsb
          
          # 私有 + 某个get方法实现的
          
        • 可看可改(需要按照规则来改),

          class User:
          #     def __init__(self, name, passwd):
          #         self.user = name
          #         self.__pwd = passwd
          #         
          #     def get_cwd(self):
          #         return self.__pwd
          #     
          #     def set_pwd(self):
          #         pass
          
          # set_pwd表示用户 必须调用我们自定义的吸怪方式来进行变量的修改 私有 + changge方法实现
          
      • 封装的语法

        • 私有的静态变量

          class User:
              __Country = 'china'
              def func(self):
                  print(User.__Country)
          # print(User.__Country) # 类的外部不能调用
          # AttributeError: type object 'User' has no attribute '__Country'
          User().func()
          # china
          
        • 私有的实例变量

          import hashlib
          
          
          class User:
              def __init__(self, name, passwd):
                  self.user = name
                  self.__pwd = passwd
          
              def __get_md5(self):
                  md5 = hashlib.md5(self.__pwd.encode("utf-8"))
                  return md5.hexdigest()
          
              def getpwd(self):
                  return self.__get_md5()
          
          
          alex = User('alex', 'alexsb')
          print(alex.getpwd())
          
        • 私有的绑定方法

          import hashlib
          
          
          class User:
              def __init__(self, name, passwd):
                  self.user = name
                  self.__pwd = passwd
          
              def __get_md5(self):
                  md5 = hashlib.md5(self.__pwd.encode("utf-8"))
                  return md5.hexdigest()
          
              def getpwd(self):
                  return self.__get_md5()
          
          
          alex = User('alex', 'alexsb')
          print(alex.getpwd())
          
          # 所有的私有化都为了让用户不在外部调用类中的某个名字
          # 如果完全私有化,name这个类的封装读更高了
          # 封装度越高 各种属性和方法的安全性也越高,但是代码越复杂
          
      • 私有的特点

        • 在类的内部使用

          内部可以正常调用

        • 类的外部使用

          无法再外部使用

        • 类的子类中使用

          无法再子类中使用

          # class Foo(object):
          #     def __init__(self):
          #         self.func()
          #
          #     def func(self):
          #         print("in Foo")
          #
          #
          # class Son(Foo):
          #     def func(self):
          #         print("IN SON")
          
          
          # Son()
          # IN SON
          
          
          # class Foo(object):
          #     def __init__(self):
          #         self.__func()
          #
          #     def __func(self):
          #         print("in Foo")
          #
          #
          # class Son(Foo):
          #     def __func(self):
          #         print("in son")
          #
          # Son()
          # in Foo
          
          class Foo(object):
              def __func(self):
                  print("in Foo")
          
          class Son(Foo):
              def __init__(self):
                  self.__func()
          
          Son()
          # AttributeError: 'Son' object has no attribute '_Son__func'
          
      • 原理

        加了双下划线的名字为啥无法从类的外部调用

        class User:
            __Country = 'China'
            __Role = '法师'
        
            def func(self):
                print(self.__Country)
                
        # 在类的内部使用的时候,自动的把当前这句话所在的类的名字拼接在私有变量前完成变形
        
        print(User._User__Country)
        print(User._User__Role)
        # China
        # 法师
        
        # __Country -->'_User__Country': 'China'
        # __Role    -->'_User__Role': '法师'
        # User.__aaa = 'bbb'  # 在类的外部根本不能定义私有的概念
        
      • 类中变量的级别,那些是python支持的,那些是python不支持的

        # public  公有的 类内类外都能用,父类子类都能用         python支持
        # protect 保护的 类内能用,父类子类都能用,类外不能用    python不支持
        # private 私有的 本类的类内部能用,其他地方都不能用     python支持
        
  • 类最终的三个装饰器(内置函数)

    • property

      • 作用 : 把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值

        from math import pi
        
        class Circle:
            def __init__(self, r):
                self.r = r
        
            @property
            def area(self):
                return pi * self.r ** 2
        
        c1 = Circle(5)
        print(c1.r)
        print(c1.area)
        # 5
        # 78.53981633974483
        

        import time
        
        
        class Person:
            def __init__(self, name, birth):
                self.name = name
                self.birth = birth
        
            @property
            def age(self):
                return time.localtime().tm_year - self.birth
        
        太白 = Person('太白', 1998)
        print(太白.age)
        

        property的第二个应用场景 : 和私有的属性合作的

        class User:
            def __init__(self, user, pwd):
                self.user = user
                self.__pwd = pwd
        
            @property
            def pwd(self):
                return self.__pwd
        
        alex = User('alex', 'alexsb')
        print(alex.pwd)
        
        class Goods:
        #     discount = 0.8
        #     def __init__(self, name, origin_price):
        #         self.name = name
        #         self.__price = origin_price
        # 
        #     @property
        #     def price(self):
        #         return self.__price * self.discount
        # 
        # apple = Goods('apple', 5)
        # print(apple.price)
        # # 4.0
        
        
      • setter

        class Goods:
        #     discount = 0.8
        #     def __init__(self, name, origin_pricce):
        #         self.name = name
        #         self.__price = origin_pricce
        # 
        #     @property
        #     def price(self):
        #         return self.__price * self.discount
        # 
        #     @price.setter
        #     def price(self, new_value):
        #         if isinstance(new_value, int):
        #             self.__price = new_value
        # 
        # apple = Goods('apple', 5)
        # print(apple.price)
        # apple.price = 10
        # print(apple.price)
        # 4.0
        # 8.0
        
        
      • delter

        class Goods:
        #     discount = 0.8
        #     def __init__(self, name, origin_price):
        #         self.name = name
        #         self.__price = origin_price
        # 
        #     @property
        #     def price(self):
        #         return self.__price * self.discount
        # 
        #     @price.setter
        #     def price(self, new_value):
        #         if isinstance(new_value, int):
        #             self.__price = new_value
        # 
        #     @price.deleter
        #     def price(self):
        #         del self.__price
        # 
        # apple = Goods('apple', 5)
        # print(apple.price)
        # apple.price = 'asd'
        # del apple.price # 调用对应的被@price.deleter装饰的方法
        # print(apple.price)
        
        
    • classmethod

    • staticmethod

  • 反射

    用字符串数据类型的名字来操作这个名字对应的函数\实例变量\绑定方法\各种方法

    • .反射对象的 实例变量

      class  Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def qqxing(self):
              print("qqxing")
      
      alex = Person('alex', 83)
      wusir = Person('wusir', 74)
      ret = getattr(alex, 'name')
      print(ret)
      ret = getattr(wusir, 'name')
      print(ret)
      ret = getattr(wusir, 'qqxing')
      ret()
      # alex
      # wusir
      # qqxing
      
    • 反射类的 静态变量/绑定方法/其他方法

      class A:
      #     Role = '治疗'
      # 
      #     def __init__(self):
      #         self.name = 'alex'
      #         self.age = 84
      # 
      #     def func(self):
      #         print("wahaha")
      #         return 666
      # 
      # a = A()
      # print(getattr(a, 'name'))
      # print(getattr(a, 'func')())
      # print(getattr(A, 'Role'))
      # # alex
      # # wahaha
      # # 666
      # # 治疗
      
    • 模块中的 所有变量

      • 被导入的模块

        import a
        print(a.Wechat)
        print(a.Alipay)
        # <class 'a.Wechat'>
        # <class 'a.Alipay'>
        # # 对象名.属性名 ==> getattr(对象名,'属性名')
        # # a.Alipay ==> getattr(a,'Alipay')
        print(getattr(a, 'Alipay'))
        print(getattr(a, 'Wechat'))
        # <class 'a.Alipay'>
        # <class 'a.Wechat'>
        
        
      • 当前执行的py文件 - 脚本

        import a
        import sys
        # print(sys.modules)
        # print(sys.modules['a'].Alipay)
        # print(a.Alipay)
        # <class 'a.Alipay'>
        # <class 'a.Alipay'>
        
        print(getattr(a, 'Alipay'))
        print(getattr(sys.modules['a'], 'Alipay'))
        # <class 'a.Alipay'>
        # <class 'a.Alipay'>
        
        wahaha = 'hahaha'
        print(getattr(sys.modules['__main__'], 'wahaha'))
        # hahaha
        
    • 反射实现归一化思想

      class Payment:pass
      class Alipay(Payment):
          def __init__(self,name):
              self.name = name
          def pay(self,money):
              dic = {'uname':self.name,'price':money}
              print('%s通过支付宝支付%s钱成功'%(self.name,money))
      
      class WeChat(Payment):
          def __init__(self,name):
              self.name = name
          def pay(self,money):
              dic = {'username':self.name,'money':money}
              print('%s通过微信支付%s钱成功'%(self.name,money))
      
      class Apple(Payment):
          def __init__(self,name):
              self.name = name
          def pay(self,money):
              dic = {'name': self.name, 'number': money}
              print('%s通过苹果支付%s钱成功' % (self.name, money))
      
      class QQpay:
          def __init__(self,name):
              self.name = name
          def pay(self,money):
              print('%s通过qq支付%s钱成功' % (self.name, money))
      import sys
      def pay(name,price,kind):
          class_name = getattr(sys.modules['__main__'],kind)
          obj = class_name(name)
          obj.pay(price)
          # if kind == 'Wechat':
          #     obj = WeChat(name)
          # elif kind == 'Alipay':
          #     obj = Alipay(name)
          # elif kind == 'Apple':
          #     obj = Apple(name)
          # obj.pay(price)
      
      pay('alex',400,'WeChat')
      pay('alex',400,'Alipay')
      pay('alex',400,'Apple')
      pay('alex',400,'QQpay')
      

    • 反射一个函数

      class A:
          Role = '治疗'
          def __init__(self):
              self.name = 'alex'
              self.age = 84
          def func(self):
              print('wahaha')
              return 666
      
      a = A()
      if hasattr(a, 'func'):
          if callable(getattr(a, 'func')):
              getattr(a, 'func')()
              
      # wahaha
      
posted @ 2019-06-09 22:32  Pyter  阅读(102)  评论(0编辑  收藏  举报