抽象类,接口类,封装,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

静态方法和类方法 都是直接可以使用类名调用
普通方法:对象调用
类能解决的事,没必要搞个实例化对象能弄
 
原文地址:https://www.cnblogs.com/jassin-du/p/7879251.html