1.接口类
python是没有接口这个概念的
1)引:归一化设计
#第一版:写一个两种支付功能的程序
class Alipay: def __init__(self,money): self.money = money def pay(self): print("用支付宝支付了%s钱"% self.money) class JDpay: def __init__(self,money): self.money = money def pay(self): print("用京东支付了%s钱" % self.money) a1 = Alipay(100) a1.pay() j1 = JDpay(200) j1.pay() #同样是支付的功能,但是支付的指令不一样,未统一化设计 输出: 用支付宝支付了100钱 用京东支付了200钱
问题:同样是支付的功能,但是支付的指令不一样,未统一化设计
#第二版:不同的支付方式,调用同样的支付指令,统一化设计
class Alipay: def __init__(self,money): self.money = money def pay(self): print("用支付宝支付了%s钱"% self.money) class JDpay: def __init__(self,money): self.money = money def pay(self): print("用京东支付了%s钱" % self.money) def pay(obj): obj.pay() a1 = Alipay(100) j1 = JDpay(200) pay(a1) pay(j1) #归一化设计 输出: 用支付宝支付了100钱 用京东支付了200钱
2)接口类/抽象类:
1)定义:制定一个规范,所有继承基类的子类,必须要有基类的抽象方法 ,如果没有基类的抽象方法,子类在实例化对象的时候就会报错
#如果子类继承父类,为重写父类的抽象方法,可强制程序报错
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self): pass class Alipay(Payment): def __init__(self,money): self.money = money def pay(self): print("用支付宝支付了%s钱"% self.money) class JDpay(Payment): def __init__(self,money): self.money = money def pay(self): print("用京东支付了%s钱" % self.money) class Wechat(Payment): def __init__(self,money): self.money = money def wechat_pay(self): #未在子类重写父类抽象方法 print("用微信支付了%s块" % self.money) def pay(obj): obj.pay() a1 = Alipay(100) pay(a1) j1 = JDpay(200) pay(j1) w1 = Wechat(300) w1.wechat_pay() 报错如下: TypeError: Can't instantiate abstract class Wechat with abstract methods pay
#子类重写父类抽象方法
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self): pass class Alipay(Payment): def __init__(self,money): self.money = money def pay(self): print("用支付宝支付了%s钱"% self.money) class JDpay(Payment): def __init__(self,money): self.money = money def pay(self): print("用京东支付了%s钱" % self.money) class Wechat(Payment): def __init__(self,money): self.money = money def pay(self): print("用微信支付了%s块" % self.money) def pay(obj): obj.pay() a1 = Alipay(100) pay(a1) j1 = JDpay(200) pay(j1) w1 = Wechat(300) w1.pay() 输出: 用支付宝支付了100钱 用京东支付了200钱 用微信支付了300块
注:必须要在抽象方法前加上@abstractmethod装饰器,否则子类有无重写父类抽象方法都不影响程序,即程序不会报错
2.多态、封装
1)python多态:python是没有多态这个感念的(没有多态的示例),因为python中处处是多态;因为不管是什么数据类型,传入函数,封装到对象中都可以,python是可以多继承的,其他语言不可以
2)python没有多态,但是它又有鸭子类型
#多个类,每一个类中都有同名的方法,且这些方法功能类似;这些类,都互称为鸭子
class Str: def index(self): pass class List: def index(self): pass class Tuple: def index(self): pass
3.封装
1)广义封装:实例化一个对象,给对象空间封装一些属性、给类中封装静态字段
2)狭义的封装:私有制,只有某些对象可以调用
3)私有成员:分为私有静态字段、私有方法、私有对象属性
#python中各变量和方法
class A: company_name = '百度' # 静态变量(静态字段) __iphone = '1353333xxxx' # 私有静态变量(私有静态字段) def __init__(self,name,age): #特殊方法 self.name = name #对象属性(普通字段) self.__age = age # 私有对象属性(私有普通字段) def func1(self): # 普通方法 pass def __func(self): #私有方法 print(666) @classmethod # 类方法 def class_func(cls): """ 定义类方法,至少有一个cls参数 """ print('类方法') @staticmethod #静态方法 def static_func(): """ 定义静态方法 ,无默认参数""" print('静态方法') @property # 属性 def prop(self): pass 转自:https://www.cnblogs.com/jin-xin/articles/9214247.html
①私有静态字段:在变量名前加两下划线如【__name】
#实例化对象不能直接访问私有静态字段
class A: name = "阿狸" __age = 18 def func(self): print("In func...") a1 = A() print(a1.name) print(a1.__age) #实例化对象不能直接访问私有静态字段 报错: AttributeError: 'A' object has no attribute '__age' 阿狸
#类名不能直接访问私有静态变量
class A: name = "阿狸" __age = 18 def func(self): print("In func...") a1 = A() print(A.__age) 输出: AttributeError: 'A' object has no attribute '__age'
总结:对于私有静态变量,类的外部不能访问
#对于私有静态字段,类的内部可以访问
class A: name = "阿狸" __age = 18 def func(self): print("In func...") print(A.__age) a1 = A() 输出: In func... 18
#对于私有静态字段,子类不可以访问
总结:对于私有静态字段来说,只能在本类的内部访问,类的外部、派生类都不能访问
备注:实际是可以在类的外部对私有静态字段进行修改的,因为从本质上来说,定义一个类就相当于开辟了一块内存空间,对于私有静态字段如【__name】,实际在内存空间中存的是【_A_name】,所以可在类外直接通过_A__name改变私有静态字段,但是非常不建议这么做
class A: name = "阿狸" __age = 18 def func(self): print("In func...") print(A._A__age) print(A.__dict__) 输出: 18 {'_A__age': 18, 'name': '阿狸', 'func': <function A.func at 0x000001504A05A048>, '__module__': '__main__', '__doc__': None, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>}
②私有方法:在方法名前加两个下划线【__方法名】
#对于私有方法,在类外不能访问,类的派生类也不能访问,只能在类的内部访问
class A: def __func(self): print("In func...") def func_2(self): self.__func() a1 = A() a1.func_2() 输出: In func...
本质:在开辟内存空间时,把私有方法名改为了【_类名__方法名】
例:写入如下程序的输出
class Parent: def __func(self): print('in Parent func') def __init__(self): self.__func() class Son(Parent): def __func(self): print('in Son func') son1 = Son() 输出: in Parent func