python面向对象的三个特性
主要内容:
1. 抽像类或者接口类
2. 多态(鸭子模型)
3.封装
1. 抽像类或者接口类
接口类,python是没有接口类的,只是一种规范,强制用户按照这个规范来,如果未按照规范执行,就会报错.
如下示例:
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod ### # 抽象类 接口类 规范和约束 metaclass指定的是一个元类 def pay(self): # 抽象方法 pass class Alipay(Payment): def pay(self,money): print("您使用支付宝支付了%s钱" % money) class QQpay(Payment): def pay(self,money): print("您使用QQ钱包支付了%s钱" % money) class Wechat(Payment): def we_pay(self,money): print("您使用微信支付支付了%s钱" % money) def pay(obj,money): obj.pay(money) a1 = Alipay() q1 = QQpay() w1 = Wechat() pay(a1,100) pay(q1,200) pay(w1,300)
2 多态,或者鸭子模型
用处: 在工作中,如果你要是规定几个类必须有一样的方法.鸭子类型: 它看着像鸭子,那么他就是鸭子.
python中好多不同类但同名的方法不是强制规定,而是约定俗成,像上面这三种类,都同样据有index方法,而且功能相似,
则 他们三个互称为鸭子.
如下示例:
# str list tuple str.index() s1 = 'alex' class Str: def index(self): pass class List: def index(self): pass class tuple: def index(self): pass
3.封装
封装就是将一些属性或者方法(有用的信息)放置在一个空间中.
1)广义的封装,指对象的封装.
class Person: def __init__(self,name,age): self.name = name self.age = age p1 = Person('oldboy',1000) p2 = Person('alex',10000) print(p1.name) print(p2.name)
2)私有的封装
对于私有成员来说,他加载到内存时,都会加上_类名__变量名,所以你在类的外部,或者派生类中都不可访问.
为什么设置私有成员?
答: 有些变量,方法,属性,只在类内部进行使用即可,不便于(不允许)类外部或者派生类去调用.
私有成员主要有三个,分别是:私有属性,私有字段,私有方法.
这些私有成员的特点就是类外部不能访问,派生类不能访问,只能在类内部访问.
如下示例:
# 私有字段 class A : num = 1 __num1 = 2 def fun(self): print(self.__num1) a1 = A() # print(a1.__num1) a1.fun()
#这个在执行结果是2,如果把注释取消,会报错.
这个原理是:当初始化类时,会把类中的__num这种带__的内部变量,自动在内存中存为_A__num的变量.
所以也可以通过
print(a1._A__num1)
来打印的.
如下示例:
是私有对象属性的:
#私有属性 class A: def __init__(self,*args): self.name = args[0] self.sex = args[1] self.__age = args[2] def fun(self): print(self.__age) a1 = A("alex","男",18) # print(a1.__age) a1.fun()
私有方法示例:
class A : def fun(self): self.__fun1() def __fun1(self): print("111") a1 = A() # a1.__fun1() a1.fun()
两个经典的面试题:
class A: def __init__(self): self.__func() def __func(self): print('IN A') class B(A): def __func(self): print('IN B') b1 = B() #问题:初始化A后,打印的是什么?解释一下原理
解答:
这个最后打印的是IN A,原因是初始化对像的时候执行的是init函数,B对象中是没有的,只能去A中找,A里面是找到的,所以传入b1的对像到self里面,self执行的是.self.__fun()
这个如上面所说,__fun()一开始被类初始化为_A__fun()这个变量了,所以找的是b1_A__fun()这个变量,然后开始从B中找,没有,在A中找到了,所有执行A中的函数.
变种问题:
class A: def __init__(self): self.func() def func(self): print('IN A') class B(A): def func(self): print('IN B') b1 = B() # print(b1.name) # print(b1.func) print(b1.func) print(b1.func())
这个结果是IN B,同理因为B中没有init,所以到A中执行,A中执行后需要执行b1.fun(),,然后同理先在B()里面找到了,所以这个先在B里面找到的.
类的结构:
class Person: mind = '有思想...' # 第一部分:所有的公有静态变量,公有静态字段 __level = '高等动物' # 第一部分:私有静态变量,私有静态字段 def __init__(self,name,age,sex): # 构造方法 # 第二部分 动态方法,方法(函数) self.name = name # 公有对象属性 self.age = age self.__sex = sex # 私有对象属性 def func(self): # 第二部分:普通方法 print(666) def __func1(self): # 第二部分:私有方法 print(777) @staticmethod # 静态方法 def f2():pass @classmethod # 类方法 def f2(self): pass @property # 属性 def hex(self):pass