zoukankan      html  css  js  c++  java
  • 抽象类,接口类,封装,property,classmetod,statimethod

    抽象类,接口类,封装,property,classmetod,statimethod(类方法,静态方法)

    一丶抽象类和接口类

     接口类(不崇尚用)

        接口类:是规范子类的一个模板,只要接口类中定义的,就应该在子类中实现
        接口类不能被实例化,只能被继承
        支持多继承,父类不实现

        python 本身支持多继承,没有接口专用的语法。但是得知道接口的概念

    例子:

    class Alipay:
        '''
        支付宝支付
        '''
        def pay(self,money):
            print('支付宝支付了%s元'%money)
    
    class Applepay:
        '''
        apple pay支付
        '''
        def pay(self,money):
            print('apple pay支付了%s元'%money)
    
    class Wechatpay:
        def fuqian(self,money):
            '''
            实现了pay的功能,但是名字不一样
            '''
            print('微信支付了%s元'%money)
    
    def pay(payment,money):
        '''
        支付函数,总体负责支付
        对应支付的对象和要支付的金额
        '''
        payment.pay(money)
    
    
    p = Wechatpay()
    pay(p,200)   #执行会报错

    第一种解决方式(比较low)

    class Payment:
        def pay(self):
            raise NotImplementedError
    
    class Wechatpay(Payment):
        def fuqian(self,money):
            print('微信支付了%s元'%money)
    
    
    p = Wechatpay()  #这里不报错
    pay(p,200)      #这里报错了

    第二种(高级方式)

    from abc import ABCMeta,abstractmethod
    # 接口类:
    # 是规范子类的一个模板,
    # 只要接口类中定义的,就应该在子类中实现(
    规范所有支付功能必须实现pay方法 # 接口类不能被实例化,它只能被继承 # 支持多继承 class Payment(metaclass=ABCMeta): #模板,接口类 @abstractmethod #装饰接口类中方法的,加上这个装饰器,自动检测子类中的方法名 def pay(self,money):pass @abstractmethod def get(self):pass # 收钱功能 class Apple_Pay(Payment): def pay(self,money): print('您使用苹果支付支付了%s元'%money) class Ali_Pay(Payment): def pay(self, money): print('您使用支付宝支付了%s元' % money) class WeChat_Pay(Payment): def pay(self,money): print('您使用微信支付了%s元' % money) def pay(obj,money): return obj.pay(money)

      

    #接口类 : 多继承,父类不实现
    from abc import ABCMeta,abstractmethod
    class Fly_Animal(metaclass=ABCMeta):   #规范
        @abstractmethod
        def fly(self):pass
    
    class Swim_Animal(metaclass=ABCMeta):
        @abstractmethod
        def swim(self): pass
    
    class Walk_Animal(metaclass=ABCMeta):
        @abstractmethod
        def walk(self): pass
    
    class Frog(Walk_Animal,Swim_Animal):
        def walk(self):
            print('自己实现walk功能')
    
        def swim(self): pass
    
    class Swan(Walk_Animal,Swim_Animal,Fly_Animal):
        pass
    
    class Bird(Walk_Animal,Fly_Animal):
        pass
    接口隔离原则: 使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。

      抽象类

      抽象类可以实现一些子类共有的功能和属性抽象类不鼓励多继承

      python 没有接口的概念  

      只能借助抽象类的模块 来实现接口类  

      接口 —— java : 没有多继承 —— Interface

    from abc import ABCMeta,abstractmethod
    class Base(metaclass=ABCMeta):
        def __init__(self,filename):
            self.filename = filename
        @abstractmethod #抽象方法
        def open(self):
            return 'file_handler'
    
        @abstractmethod
        def close(self):pass
    
        @abstractmethod
        def read(self):pass
    
        @abstractmethod
        def write(self):pass
    
    
    class File(Base):
        def open(self):pass
        def close(self):pass
        def read(self):pass
        def write(self):pass
    
    # 抽象类不能被实例化
    # 这个抽象类可以规范子类必须实现抽象类中的抽象方法

    二、封装(重要)

         封装: 隐藏对象的属性和实现细节,仅对外提供公共访问方式

        把一些属性和方法放到类里 这本身就是一种封装(广义上的封装)
        面对对象里的封装 : 把属性和方法藏在类里 我只能在类内部调用,不能再外部使用(实际意义)

       好处: 

        1. 将变化隔离; 2. 便于使用;3. 提高复用性; 4. 提高安全性;

        原则

              1. 将不需要对外提供的内容都隐藏起来;

              2. 把属性都隐藏,提供公共方法对其访问。

    加__藏起来
    class Dog:
        __role = 'dog'  # 私有的静态属性,在语法上是可以把类的数据属性设置成私有的如__N,会变形为_Dog__N
        def func(self): # 内部使用
            print(Dog.__role)  # _Dog__role 私有方法
    # print(Dog.role)
    print(Dog.__dict__)  # 查看名字空间
    print(Dog._Dog__role)# 不鼓励这样调用私有变量 dog  查私有静态属性
    从类的外面不能直接调用,在类内的使用加上了一层密码:_类名
    
    d = Dog() #能实例化
    d.func()  
    私有动态方法
    class Dog:
        __role = 'dog'  # 私有的静态属性
        def __discount(self):
            print('in __func') # 私有方法 (动态)
    
        def price(self):
            self.__discount()
    
    print(Dog.__dict__)
    print(Dog._Dog__discount)
    定义一个私有变量属性方法:__名字
    在类的内部可以直接使用: __名字
    在类的外部不能直接使用,如果一定要用,在私有方法之前加上:_类名,变成_类名__名字  # 不推荐使用
    在类外的名字 通过__dict__就可以查看
    
    
    私有的
    私有的静态属性、方法、对象属性
    使用__名字的方式调用,保证在类内部可以调用,外部不行

    class
    Room: def __init__(self,name,price,length,width): self.name = name self.price = print self.__length = length # 私有的对象属性 self.__width = width def area(self): return self.__length*self.__width house = Room('天空之镜',100000,200,1) print(house.area())
    私有属性能否被继承: 不能
    私有的 不能被继承
    当有一个名字,不想被外部使用也不想被子类继承,只想内部使用的时候就定义私有的

    class
    A: def __func(self): print('__a_func') _A__func class B(A): def __init__(self): self.__func()    _B__func b= B() # 报错

    三、property内置(会使代码变整洁)

            property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值 

    例子:1、

    @property 把一个方法 伪装成一个属性
    1 属性的值 是这个方法的返回值
    2 这个方法不能有参数
    class
    Person: def __init__(self,name,height,weight): self.name = name self.height = height self.weight = weight # @property 加了方法变属性 def bmi(self): #bmi人的一个属性 self.weight/(self.height ** 2) li = Person('lishi',1.65,50) print(li.bmi) # 属性 print(li.bmi()) # 方法
    2、
    圆形类
    from math import pi
    class Circle:
        def __init__(self, r):
            self.radius = r
    
        @property
        def perimeter(self):
            return 2 * pi * self.radius
    
        @property
        def area(self):
            return pi * (self.radius ** 2)
    
    c1 = Circle(5)
    print(c1.area)
    
    
    
    class Goods:
        discount = 0.8 # 静态属性
        def __init__(self,name,price):
            self.name = name
            self.__price = price # 原价
    
        @property
        def price(self): # 折后价
            return self.__price * Goods.discount
    
    
    apple = Goods('榴莲',10)
    print(apple.price)  # 8.0
    banana = Goods('香蕉',2.5)
    print(banana.price)  2.0
    
    
    apple.price = 6 # 修改不了原价
    print(apple.price) # 报错

    解决:setter

    class Goods:
        discount = 0.8 # 静态属性 全部打8折
        def __init__(self,name,price):
            self.name = name
            self.__price = price # 原价
    
        @property
        def price(self): # 折后价
            return self.__price * Goods.discount
    
        @price.setter # 加红的名字必须一样的才会有效果
        def price(self,new_price):  # 修改原价
         # if type(new_price) is int: # 加了,可以增加安全性,使用setter的优势
    self.__price = new_price         # self.__price = new_price apple = Goods('苹果',20) # 原价
    apple.price = 10 # 修改原价(只能传一个参数) setter
    print(apple.price) # property
    封装
    __私有+property
    让对象的属性变得更安全了
    获取到的对象的值可以进行一些加工
    修改对象的值的同时可以进行一些验证  setter

    一个静态属性property本质就是实现了get,set,delete三种方法

    
    
    class Foo:
        @property  # 把AAA伪装成一个属性
        def AAA(self):
            print('get的时候运行我啊')
    
        @AAA.setter # 修改值
        def AAA(self,value):
            print('set的时候运行我啊')
    
        @AAA.deleter # 删除
        def AAA(self):
            print('delete的时候运行我啊')
    
    #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
    
    
    class Foo:
        def get_AAA(self):
            print('get的时候运行我啊')
    
        def set_AAA(self,value):
            print('set的时候运行我啊')
    
        def delete_AAA(self):
            print('delete的时候运行我啊')
        AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
    
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
    
    

    使用:

    
    
    class Goods:
        __discount = 0.8   #静态属性
        def __init__(self,name,price):
            self.__name = name
            self.__price = price  #原价
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self,new_name):
            self.__name = new_name
    
        @name.deleter
        def name(self):
            del self.__name
    
        @property
        def price(self):   #折后价
            return self.__price * Goods.__discount
    
        @price.setter
        def price(self,new_price):   #修改原价
            if type(new_price) is int:
                self.__price = new_price
    
    
    apple = Goods('苹果',10)
    del apple.name
    print(apple.name) # 报错,已删除
    
    

    四、classmethod和staticmthod(类方法、静态方法)

    问题:定义一个类类里面的方法并没有用到self
    例如:
    # 与apple无关,所以def change_discount(self,new_discount)在这里不适合
    # 需实例化 class Goods: __discount = 0.8 def change_discount(self,new_discount): Goods.__discount = new_discount apple = Goods() # 实例化 apple.change_discount(0.75)

    修改版

    类方法:

    class Goods:
        __discount = 0.8
        @classmethod   #类方法
        def change_discount(cls,new_discount):
            cls.__discount = new_discount
        @classmethod
        def get_discount(cls):
            return cls.__discount
    # apple = Goods()
    Goods.change_discount(0.75)
    print(Goods.get_discount())

    类方法好处:
      调用:不需要实例化 直接用类名调用就好
      定义:不用接受self参数,默认传cls,cls就代表当前方法所在的类

    什么时候用类方法?
    需要使用静态变量 且 不需要和对象相关的任何操作的时候

    静态方法:
      如果这个方法 既不需要操作静态变量也不需要使用对象相关的操作,就使用静态方法

    class A:
        @staticmethod
        def func(name):  #静态方法
            print(123)
    A.func('alex')
    class A:
        @staticmethod
        def func():  #静态方法
            print(123)
    A.func()
    面向对象编程:专门为面向对象编程提供的一个方法——staticmethod
    它完全可以当做普通函数去用,只不过这个函数要通过类名.函数名调用
    其他 传参 返回值 完全没有区别

    类里面,一共可以定义这三种方法:
    普通方法 self
    类方法 cls @classmrthod
    静态方法 @staticmethod


    绑定方法 和 非绑定方法
    
    class A:
        @staticmethod
        def func1(name):  #静态方法
            print(123)
    
        @classmethod
        def func2(cls):  # 静态方法
            print(123)
    
        def func3(self):pass
    a = A()
    print(a.func1)  #静态方法
    print(a.func2)  #类方法 : 绑定到A类的func
    print(a.func3)  #普通方法:绑定到A类对象的func
    
    
    静态方法和类方法 都是直接可以使用类名调用
    普通方法:对象调用
    类能解决的事,没必要搞个实例化对象能弄
     
  • 相关阅读:
    vue项目锚点定位+滚动定位
    elementUI 弹出框添加可自定义拖拽和拉伸功能,并处理边界问题
    密码检验规则(字母数字和特殊字符组成的混合体)
    分布式版本控制系统git
    自动生成滚动条
    jq中append(),appendTo(),after(),before(),prepend(),prependTo()的用法
    清除浮动的几种方式
    王者荣耀周年福利活动绕过微信屏蔽
    看不懂源码?先来恶补一波Object原型吧
    Vue组件化开发
  • 原文地址:https://www.cnblogs.com/jassin-du/p/7879251.html
Copyright © 2011-2022 走看看