python学习第17天----接口类/抽象类、多态、封装
分类:
IT文章
•
2022-09-27 00:11:48
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钱
View Code
问题:同样是支付的功能,但是支付的指令不一样,未统一化设计
#第二版:不同的支付方式,调用同样的支付指令,统一化设计
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钱
View Code
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
View Code
#子类重写父类抽象方法
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块
View Code
注:必须要在抽象方法前加上@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
View Code
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
View Code
①私有静态字段:在变量名前加两下划线如【__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'
阿狸
View Code
#类名不能直接访问私有静态变量
class A:
name = "阿狸"
__age = 18
def func(self):
print("In func...")
a1 = A()
print(A.__age)
输出:
AttributeError: 'A' object has no attribute '__age'
View Code
总结:对于私有静态变量,类的外部不能访问
#对于私有静态字段,类的内部可以访问
class A:
name = "阿狸"
__age = 18
def func(self):
print("In func...")
print(A.__age)
a1 = A()
输出:
In func...
18
View Code
#对于私有静态字段,子类不可以访问
总结:对于私有静态字段来说,只能在本类的内部访问,类的外部、派生类都不能访问
备注:实际是可以在类的外部对私有静态字段进行修改的,因为从本质上来说,定义一个类就相当于开辟了一块内存空间,对于私有静态字段如【__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>}
View Code
②私有方法:在方法名前加两个下划线【__方法名】
#对于私有方法,在类外不能访问,类的派生类也不能访问,只能在类的内部访问
class A:
def __func(self):
print("In func...")
def func_2(self):
self.__func()
a1 = A()
a1.func_2()
输出:
In func...
View Code
本质:在开辟内存空间时,把私有方法名改为了【_类名__方法名】
例:写入如下程序的输出
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
View Code