加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python:类的基本特征------继承、多态与封装

发布时间:2020-12-17 00:00:59 所属栏目:Python 来源:网络整理
导读:h2 style="text-align: left" 一、继承 1,什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类python中类的继承分为:单继承和多继承 ParentClass1: span style="color:

<h2 style="text-align: left">一、继承

1,什么是继承

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类python中类的继承分为:单继承和多继承
ParentClass1:

<span style="color: #0000ff">class ParentClass2: <span style="color: #008000">#<span style="color: #008000">定义父类
<span style="color: #0000ff">pass

<span style="color: #0000ff">class SubClass1(ParentClass1): <span style="color: #008000">#<span style="color: #008000">单继承,基类是ParentClass1,派生类是SubClass
<span style="color: #0000ff">pass

<span style="color: #0000ff">class SubClass2(ParentClass1,ParentClass2): <span style="color: #008000">#<span style="color: #008000">python支持多继承,用逗号分隔开多个继承的类,SubClass2就是多继承

 

2,查看继承

>>> SubClass1. (< >>>> SubClass2.< >,< >)

提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。

>>> ParentClass1.< >>>> ParentClass2.< >,)

?3,继承与抽象(先抽象再继承)

抽象即抽取类似或者说比较像的部分。

抽象分成两个层次:?

1.将奥巴马和梅西这俩对象比较像的部分抽取成类;?

2.将人,猪,狗这三个类比较像的部分抽取成父类。

继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

4,继承与重用性

==========================  猫可以:喵喵叫、吃、喝、拉、撒

  狗可以:汪汪叫、吃、喝、拉、撒

如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,伪代码如下:

<span style="color: #008000">#<span style="color: #008000">猫和狗有大量相同的内容
<span style="color: #0000ff">class<span style="color: #000000"> 猫:

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 喵喵叫(self):
    </span><span style="color: #0000ff"&gt;print</span> <span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;喵喵叫</span><span style="color: #800000"&gt;'</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 吃(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 喝(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 拉(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 撒(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff">class<span style="color: #000000"> 狗:

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 汪汪叫(self):
    </span><span style="color: #0000ff"&gt;print</span> <span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;汪汪叫</span><span style="color: #800000"&gt;'</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 吃(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 喝(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 拉(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 撒(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

==========================<span style="color: #000000">第二部分
上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:

  动物:吃、喝、拉、撒

   猫:喵喵叫(猫继承动物的功能)

   狗:汪汪叫(狗继承动物的功能)

伪代码如下:
<span style="color: #0000ff">class<span style="color: #000000"> 动物:

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 吃(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 喝(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 拉(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 撒(self):
    </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; do something</span>

<span style="color: #008000">#<span style="color: #008000"> 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
<span style="color: #0000ff">class<span style="color: #000000"> 猫(动物):

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 喵喵叫(self):
    </span><span style="color: #0000ff"&gt;print</span> <span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;喵喵叫</span><span style="color: #800000"&gt;'</span>

<span style="color: #008000">#<span style="color: #008000"> 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
<span style="color: #0000ff">class<span style="color: #000000"> 狗(动物):

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; 汪汪叫(self):
    </span><span style="color: #0000ff"&gt;print</span> <span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;汪汪叫</span><span style="color: #800000"&gt;'</span>

==========================<span style="color: #000000">第三部分
<span style="color: #008000">#<span style="color: #008000">继承的代码实现
<span style="color: #0000ff">class<span style="color: #000000"> Animal:

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; eat(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;%s 吃 </span><span style="color: #800000"&gt;"</span> %<span style="color: #000000"&gt;self.name)

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; drink(self):
    </span><span style="color: #0000ff"&gt;print</span> (<span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;%s 喝 </span><span style="color: #800000"&gt;"</span> %<span style="color: #000000"&gt;self.name)

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; shit(self):
    </span><span style="color: #0000ff"&gt;print</span> (<span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;%s 拉 </span><span style="color: #800000"&gt;"</span> %<span style="color: #000000"&gt;self.name)

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; pee(self):
    </span><span style="color: #0000ff"&gt;print</span> (<span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;%s 撒 </span><span style="color: #800000"&gt;"</span> %<span style="color: #000000"&gt;self.name)

<span style="color: #0000ff">class<span style="color: #000000"> Cat(Animal):

</span><span style="color: #0000ff"&gt;def</span> <span style="color: #800080"&gt;__init__</span><span style="color: #000000"&gt;(self,name):
    self.name </span>=<span style="color: #000000"&gt; name
    self.breed </span>= <span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;猫</span><span style="color: #800000"&gt;'</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; cry(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;喵喵叫</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;)

<span style="color: #0000ff">class<span style="color: #000000"> Dog(Animal):

</span><span style="color: #0000ff"&gt;def</span> <span style="color: #800080"&gt;__init__</span><span style="color: #000000"&gt;(self,name):
    self.name </span>=<span style="color: #000000"&gt; name
    self.breed</span>=<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;狗</span><span style="color: #800000"&gt;'</span>

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; cry(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;汪汪叫</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;)

<span style="color: #008000">#<span style="color: #008000"> ######### 执行 #########
<span style="color: #000000">
c1 = Cat(<span style="color: #800000">'<span style="color: #800000">小白家的小黑猫<span style="color: #800000">'<span style="color: #000000">)
c1.eat()

c2 = Cat(<span style="color: #800000">'<span style="color: #800000">小黑的小白猫<span style="color: #800000">'<span style="color: #000000">)
c2.drink()

d1 = Dog(<span style="color: #800000">'<span style="color: #800000">胖子家的小瘦狗<span style="color: #800000">'<span style="color: #000000">)
d1.eat()

使用继承来重用代码比较好的例子

使用继承来解决代码重用的例子

在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时

我们不可能从头开始写一个类B,这就用到了类的继承的概念。

通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用

= name self.aggressivity = aggressivity self.life_value = life_value
<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; eat(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;%s is eating</span><span style="color: #800000"&gt;'</span>%<span style="color: #000000"&gt;self.name)

<span style="color: #0000ff">class<span style="color: #000000"> Dog(Animal):
<span style="color: #0000ff">pass

<span style="color: #0000ff">class<span style="color: #000000"> Person(Animal):
<span style="color: #0000ff">pass<span style="color: #000000">

egg = Person(<span style="color: #800000">'<span style="color: #800000">egon<span style="color: #800000">',10,1000<span style="color: #000000">)
ha2 = Dog(<span style="color: #800000">'<span style="color: #800000">二愣子<span style="color: #800000">',50,1000<span style="color: #000000">)
egg.eat()
ha2.eat()

5,派生

当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

= name self.aggressivity = aggressivity self.life_value = life_value
<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; eat(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;%s is eating</span><span style="color: #800000"&gt;'</span>%<span style="color: #000000"&gt;self.name)

<span style="color: #0000ff">class<span style="color: #000000"> Dog(Animal):
<span style="color: #800000">'''<span style="color: #800000">
狗类,继承Animal类
<span style="color: #800000">'''
<span style="color: #0000ff">def<span style="color: #000000"> bite(self,people):
<span style="color: #800000">'''<span style="color: #800000">
派生:狗有咬人的技能
:param people:
<span style="color: #800000">'''<span style="color: #000000">
people.life_value -=<span style="color: #000000"> self.aggressivity

<span style="color: #0000ff">class<span style="color: #000000"> Person(Animal):
<span style="color: #800000">'''<span style="color: #800000">
人类,继承Animal
<span style="color: #800000">'''
<span style="color: #0000ff">def<span style="color: #000000"> attack(self,dog):
<span style="color: #800000">'''<span style="color: #800000">
派生:人有攻击的技能
:param dog:
<span style="color: #800000">'''<span style="color: #000000">
dog.life_value -=<span style="color: #000000"> self.aggressivity

egg = Person(<span style="color: #800000">'<span style="color: #800000">egon<span style="color: #800000">',1000<span style="color: #000000">)
<span style="color: #0000ff">print<span style="color: #000000">(ha2.life_value)
<span style="color: #0000ff">print<span style="color: #000000">(egg.attack(ha2))
<span style="color: #0000ff">print(ha2.life_value)

在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值.

6,super

(<span style="color: #0000ff">class<span style="color: #000000"> B(A):
<span style="color: #0000ff">def
<span style="color: #000000"> hahaha(self):
super().hahaha()
<span style="color: #008000">#
<span style="color: #008000">super(B,self).hahaha()

<span style="color: #008000">#
<span style="color: #008000">A.hahaha(self)

<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">B<span style="color: #800000">'<span style="color: #000000">)

a =<span style="color: #000000"> A()
b =<span style="color: #000000"> B()
b.hahaha()
super(B,b).hahaha()

(<span style="color: #0000ff">class<span style="color: #000000"> B(A):
<span style="color: #0000ff">def
<span style="color: #000000"> hahaha(self):
super().hahaha()
<span style="color: #008000">#
<span style="color: #008000">super(B,b).hahaha()

帮你了解super

通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。

当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师

>>> ==(>>> >>> >>> p1=Professor(,>>>

7,钻石继承

继承顺序

当类是经典类时,多继承情况下,会按照深度优先方式查找

当类是新式类时,多继承情况下,会按照广度优先方式查找

经典类和新式类:

从写法上类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

(<span style="color: #0000ff">class<span style="color: #000000"> B(A):
<span style="color: #0000ff">def
<span style="color: #000000"> test(self):
<span style="color: #0000ff">print
(<span style="color: #800000">'
<span style="color: #800000">from B
<span style="color: #800000">'
<span style="color: #000000">)

<span style="color: #0000ff">class<span style="color: #000000"> C(A):
<span style="color: #0000ff">def<span style="color: #000000"> test(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">from C<span style="color: #800000">'<span style="color: #000000">)

<span style="color: #0000ff">class<span style="color: #000000"> D(B):
<span style="color: #0000ff">def<span style="color: #000000"> test(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">from D<span style="color: #800000">'<span style="color: #000000">)

<span style="color: #0000ff">class<span style="color: #000000"> E(C):
<span style="color: #0000ff">def<span style="color: #000000"> test(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">from E<span style="color: #800000">'<span style="color: #000000">)

<span style="color: #0000ff">class<span style="color: #000000"> F(D,E):
<span style="color: #008000">#<span style="color: #008000"> def test(self):
<span style="color: #008000">#<span style="color: #008000"> print('from F')
<span style="color: #0000ff">pass<span style="color: #000000">
f1=<span style="color: #000000">F()
f1.test()
<span style="color: #0000ff">print(F.<span style="color: #800080">mro) <span style="color: #008000">#<span style="color: #008000">只有新式才有这个属性可以查看线性列表,经典类没有这个属性

<span style="color: #008000">#<span style="color: #008000">新式类继承顺序:F->D->B->E->C->A<span style="color: #008000">

<span style="color: #008000">经典类继承顺序:F->D->B->A->E->C<span style="color: #008000">

<span style="color: #008000">python3中统一都是新式类<span style="color: #008000">

<span style="color: #008000">pyhon2中才分新式类与经典类

8,继承原理

?python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列

>>> F.mro() [< >,< >,< >,< >,< >,< >,< >]

?为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:1.子类会先于父类被检查2.多个父类会根据它们在列表中的顺序被检查3.如果对下一个类存在两个合法的选择,选择第一个父类

?二、多态

1,抽象类与接口类

继承有两种用途:

一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) ?

二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

(%<span style="color: #0000ff">class<span style="color: #000000"> Applepay:
<span style="color: #800000">'''
<span style="color: #800000">
apple pay支付
<span style="color: #800000">'''

<span style="color: #0000ff">def
<span style="color: #000000"> pay(self,money):
<span style="color: #0000ff">print
(<span style="color: #800000">'
<span style="color: #800000">apple pay支付了%s元
<span style="color: #800000">'
%<span style="color: #000000">money)

<span style="color: #0000ff">def<span style="color: #000000"> pay(payment,money):
<span style="color: #800000">'''<span style="color: #800000">
支付函数,总体负责支付
对应支付的对象和要支付的金额
<span style="color: #800000">'''<span style="color: #000000">
payment.pay(money)

p =<span style="color: #000000"> Alipay()
pay(p,200)

(%<span style="color: #0000ff">class<span style="color: #000000"> Wechatpay:
<span style="color: #0000ff">def
<span style="color: #000000"> fuqian(self,money):
<span style="color: #800000">'''
<span style="color: #800000">
实现了pay的功能,但是名字不一样
<span style="color: #800000">'''

<span style="color: #0000ff">print
(<span style="color: #800000">'
<span style="color: #800000">微信支付了%s元
<span style="color: #800000">'
%<span style="color: #000000">money)

<span style="color: #0000ff">def<span style="color: #000000"> pay(payment,money):
<span style="color: #800000">'''<span style="color: #800000">
支付函数,总体负责支付
对应支付的对象和要支付的金额
<span style="color: #800000">'''<span style="color: #000000">
payment.pay(money)

p =<span style="color: #000000"> Wechatpay()
pay(p,200) <span style="color: #008000">#<span style="color: #008000">执行会报错

借用abc模块来实现接口

abc <span style="color: #0000ff">class Payment(metaclass=<span style="color: #000000">ABCMeta):
@abstractmethod
<span style="color: #0000ff">def<span style="color: #000000"> pay(self,money):
<span style="color: #0000ff">pass

<span style="color: #0000ff">class<span style="color: #000000"> Wechatpay(Payment):
<span style="color: #0000ff">def<span style="color: #000000"> fuqian(self,money):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">微信支付了%s元<span style="color: #800000">'%<span style="color: #000000">money)

p = Wechatpay() <span style="color: #008000">#<span style="color: #008000">不调就报错了

实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。

继承的第二种含义非常重要。它又叫“接口继承”。接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。

归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。

什么是抽象类

抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

abc

<span style="color: #0000ff">class All_file(metaclass=<span style="color: #000000">abc.ABCMeta):
all_type=<span style="color: #800000">'<span style="color: #800000">file<span style="color: #800000">'<span style="color: #000000">
@abc.abstractmethod <span style="color: #008000">#<span style="color: #008000">定义抽象方法,无需实现功能
<span style="color: #0000ff">def<span style="color: #000000"> read(self):
<span style="color: #800000">'<span style="color: #800000">子类必须定义读功能<span style="color: #800000">'
<span style="color: #0000ff">pass<span style="color: #000000">

@abc.abstractmethod </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt;定义抽象方法,无需实现功能</span>
<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; write(self):
    </span><span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;子类必须定义写功能</span><span style="color: #800000"&gt;'</span>
    <span style="color: #0000ff"&gt;pass</span>

<span style="color: #008000">#<span style="color: #008000"> class Txt(All_file):<span style="color: #008000">

<span style="color: #008000"> pass<span style="color: #008000">

<span style="color: #008000"> t1=Txt() #报错,子类没有定义抽象方法

<span style="color: #0000ff">class Txt(All_file): <span style="color: #008000">#<span style="color: #008000">子类继承抽象类,但是必须定义read和write方法
<span style="color: #0000ff">def<span style="color: #000000"> read(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">文本数据的读取方法<span style="color: #800000">'<span style="color: #000000">)

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; write(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;文本数据的读取方法</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;)

<span style="color: #0000ff">class Sata(All_file): <span style="color: #008000">#<span style="color: #008000">子类继承抽象类,但是必须定义read和write方法
<span style="color: #0000ff">def<span style="color: #000000"> read(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">硬盘数据的读取方法<span style="color: #800000">'<span style="color: #000000">)

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; write(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;硬盘数据的读取方法</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;)

<span style="color: #0000ff">class Process(All_file): <span style="color: #008000">#<span style="color: #008000">子类继承抽象类,但是必须定义read和write方法
<span style="color: #0000ff">def<span style="color: #000000"> read(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">进程数据的读取方法<span style="color: #800000">'<span style="color: #000000">)

</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; write(self):
    </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;进程数据的读取方法</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;)

wenbenwenjian=<span style="color: #000000">Txt()

yingpanwenjian=<span style="color: #000000">Sata()

jinchengwenjian=<span style="color: #000000">Process()

<span style="color: #008000">#<span style="color: #008000">这样大家都是被归一化了,也就是一切皆文件的思想
<span style="color: #000000">wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()

<span style="color: #0000ff">print<span style="color: #000000">(wenbenwenjian.all_type)
<span style="color: #0000ff">print<span style="color: #000000">(yingpanwenjian.all_type)
<span style="color: #0000ff">print(jinchengwenjian.all_type)

<div class="cnblogs_code">

12<span style="color: #000000">.方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现

python中没有接口类,有抽象类,abc模块中的metaclass =ABCMeta,@abstrutmethod

本质是做代码规范用的,希望在子类中实现和父类方法名字完全一样的方法

在Java的角度来看是有区别的:

  Java本来就支持单继承,所以就有了抽象类

  Java没有多继承,所以为了接口隔离原则,设计了接口这个概念

  python即支持单继承页支持多继承,所以对于接口类和抽象类的区别就不明显了。

甚至在python中没有内置接口类。

2,多态

多态指的是一类事物有多种形态

动物有多种形态:人,狗,猪

Animal(metaclass=abc.ABCMeta):

<span style="color: #0000ff">class People(Animal): <span style="color: #008000">#<span style="color: #008000">动物的形态之一:人
<span style="color: #0000ff">def<span style="color: #000000"> talk(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">say hello<span style="color: #800000">'<span style="color: #000000">)

<span style="color: #0000ff">class Dog(Animal): <span style="color: #008000">#<span style="color: #008000">动物的形态之二:狗
<span style="color: #0000ff">def<span style="color: #000000"> talk(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">say wangwang<span style="color: #800000">'<span style="color: #000000">)

<span style="color: #0000ff">class Pig(Animal): <span style="color: #008000">#<span style="color: #008000">动物的形态之三:猪
<span style="color: #0000ff">def<span style="color: #000000"> talk(self):
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">say aoao<span style="color: #800000">')

3,多态性

peo===<span style="color: #008000">#<span style="color: #008000">peo、dog、pig都是动物,只要是动物肯定有talk方法<span style="color: #008000">

<span style="color: #008000">于是我们可以不用考虑它们三者的具体是什么类型,而直接使用

<span style="color: #000000">peo.talk()
dog.talk()
pig.talk()

<span style="color: #008000">#<span style="color: #008000">更进一步,我们可以定义一个统一的接口来使用
<span style="color: #0000ff">def<span style="color: #000000"> func(obj):
obj.talk()

4,鸭子类型---不依赖父类的情况下实现两个相似的类中的同名方法

<span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; write(self):
    </span><span style="color: #0000ff"&gt;pass</span>

<span style="color: #0000ff">class<span style="color: #000000"> DiskFile:
<span style="color: #0000ff">def<span style="color: #000000"> read(self):
<span style="color: #0000ff">pass
<span style="color: #0000ff">def<span style="color: #000000"> write(self):
<span style="color: #0000ff">pass

三、封装--私有的

在python中只要___名字,就把这个名字私有化了

私有化之后,就不能从类的外部直接调用了

静态属性、方法对象属性、都可以私有化

这种私有化只是从代码级别做了变性并没有真的约束

变形机制:_类名__名字,在类外用这个调用,在累得内部直接__名字调用

私有变量和私有方法

在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

<span style="color: #0000ff">class<span style="color: #000000"> A:
<span style="color: #800080">N=0 <span style="color: #008000">#<span style="color: #008000">类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如N,会变形为_AN
<span style="color: #0000ff">def <span style="color: #800080">
init<span style="color: #000000">(self):
self.<span style="color: #800080">
X=10 <span style="color: #008000">#<span style="color: #008000">变形为self._AX
<span style="color: #0000ff">def <span style="color: #800080">
foo(self): <span style="color: #008000">#<span style="color: #008000">变形为_Afoo
<span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">from A<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">def<span style="color: #000000"> bar(self):
self.<span style="color: #800080">
foo() <span style="color: #008000">#<span style="color: #008000">只有在类内部才可以通过__foo的形式访问到.

<span style="color: #008000">#<span style="color: #008000">A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形

这种自动变形的特点:

1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果

2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

这种变形需要注意的问题是:

1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

2.变形的过程只在类的内部生效,在定义后的赋值操作,不会变形

3.在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

= = = self. type(newName) str newName.isdigit() == =( self. * self.jin = Room(<span style="color: #800000">'<span style="color: #800000">金老板<span style="color: #800000">',2,1<span style="color: #000000">)
<span style="color: #0000ff">print
<span style="color: #000000">(jin.area())
jin.set_name(
<span style="color: #800000">'
<span style="color: #800000">2
<span style="color: #800000">'
<span style="color: #000000">)
<span style="color: #0000ff">print
(jin.get_name())

并不能修改私有化属性

>>> (>>> (>>> b=>>><span style="color: #008000">#<span style="color: #008000">把fa定义成私有的,即__fa

<span style="color: #0000ff">class<span style="color: #000000"> A:
... <span style="color: #0000ff">def <span style="color: #800080">fa(self): <span style="color: #008000">#<span style="color: #008000">在定义时就变形为_Afa
... <span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">from A<span style="color: #800000">'<span style="color: #000000">)
... <span style="color: #0000ff">def<span style="color: #000000"> test(self):
... self.<span style="color: #800080">
fa() <span style="color: #008000">#<span style="color: #008000">只会与自己所在的类为准,即调用_A
fa
<span style="color: #000000">...
>>> <span style="color: #0000ff">class<span style="color: #000000"> B(A):
... <span style="color: #0000ff">def <span style="color: #800080">__fa<span style="color: #000000">(self):
... <span style="color: #0000ff">print(<span style="color: #800000">'<span style="color: #800000">from B<span style="color: #800000">'<span style="color: #000000">)
...
>>> b=<span style="color: #000000">B()
>>><span style="color: #000000"> b.test()
<span style="color: #0000ff">from A

?

会用到私有的这个概念de场景1.隐藏起一个属性 不想让类的外部调用2.我想保护这个属性,不想让属性随意被改变3.我想保护这个属性,不被子类继承2,property属性什么是特性propertyproperty是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
例一:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)

成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖,高于32
  体质指数(BMI)=体重(kg)÷身高^2(m)
  EX:70kg÷(1.75×1.75)=22.86


<div class="cnblogs_code">
<img id="code_img_closed_aa5a0c36-9180-4c4a-abe7-e2e317620b44" class="code_img_closed" src="https://www.52php.cn/res/2019/02-25/18/1c53668bcee393edac0d7b3b3daff1ae.gif" alt=""><img id="code_img_opened_aa5a0c36-9180-4c4a-abe7-e2e317620b44" class="code_img_opened" style="display: none" src="https://www.52php.cn/res/2019/02-25/18/405b18b4b6584ae338e0f6ecaf736533.gif" alt=""><div id="cnblogs_code_open_aa5a0c36-9180-4c4a-abe7-e2e317620b44" class="cnblogs_code_hide">

 == self.weight/(self.length)**2=Bmi(62,1.8(a.bmi)
(self,radius): self.radius=@property </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; area(self): </span><span style="color: #0000ff"&gt;return</span> math.pi * self.radius**2 <span style="color: #008000"&gt;#</span><span style="color: #008000"&gt;计算面积</span>

<span style="color: #000000">
@property
<span style="color: #0000ff">def<span style="color: #000000"> perimeter(self):
<span style="color: #0000ff">return 2math.piself.radius <span style="color: #008000">#<span style="color: #008000">计算周长
<span style="color: #000000">
c=Circle(10<span style="color: #000000">)
<span style="color: #0000ff">print<span style="color: #000000">(c.radius)
<span style="color: #0000ff">print(c.area) <span style="color: #008000">#<span style="color: #008000">可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
<span style="color: #0000ff">print(c.perimeter) <span style="color: #008000">#<span style="color: #008000">同上
<span style="color: #800000">'''<span style="color: #800000">
输出结果:
314.1592653589793
62.83185307179586
<span style="color: #800000">'''<span style="color: #000000">

例二:圆的周长和面积

为什么要用property

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

=val self. isinstance(value,str): TypeError( %=value TypeError(f=Foo(<span style="color: #800000">'<span style="color: #800000">egon<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">print
<span style="color: #000000">(f.name)
<span style="color: #008000">#
<span style="color: #008000"> f.name=10 #抛出异常'TypeError: 10 must be str'

<span style="color: #0000ff">del
f.name <span style="color: #008000">#
<span style="color: #008000">抛出异常'TypeError: Can not delete'

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

(@AAA.setter </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; AAA(self,value): </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;set的时候运行我啊</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;) @AAA.deleter </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; AAA(self): </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;delete的时候运行我啊</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;)

<span style="color: #008000">#<span style="color: #008000">只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=<span style="color: #000000">Foo()
f1.AAA
f1.AAA=<span style="color: #800000">'<span style="color: #800000">aaa<span style="color: #800000">'
<span style="color: #0000ff">del f1.AAA

(</span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; set_AAA(self,value): </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;set的时候运行我啊</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;) </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; delete_AAA(self): </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;'</span><span style="color: #800000"&gt;delete的时候运行我啊</span><span style="color: #800000"&gt;'</span><span style="color: #000000"&gt;) AAA</span>=property(get_AAA,set_AAA,delete_AAA) <span style="color: #008000"&gt;#</span><span style="color: #008000"&gt;内置property三个参数与get,set,delete一一对应</span>

<span style="color: #000000">
f1=<span style="color: #000000">Foo()
f1.AAA
f1.AAA=<span style="color: #800000">'<span style="color: #800000">aaa<span style="color: #800000">'
<span style="color: #0000ff">del f1.AAA

怎么用?

</span><span style="color: #0000ff"&gt;def</span> <span style="color: #800080"&gt;__init__</span><span style="color: #000000"&gt;(self): </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; 原价</span> self.original_price = 100 <span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; 折扣</span> self.discount = 0.8<span style="color: #000000"&gt; @property </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; price(self): </span><span style="color: #008000"&gt;#</span><span style="color: #008000"&gt; 实际价格 = 原价 * 折扣</span> new_price = self.original_price *<span style="color: #000000"&gt; self.discount </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; new_price @price.setter </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; price(self,value): self.original_price </span>=<span style="color: #000000"&gt; value @price.deleter </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; price(self): </span><span style="color: #0000ff"&gt;del</span><span style="color: #000000"&gt; self.original_price

obj =<span style="color: #000000"> Goods()
obj.price <span style="color: #008000">#<span style="color: #008000"> 获取商品价格
obj.price = 200 <span style="color: #008000">#<span style="color: #008000"> 修改商品原价
<span style="color: #0000ff">print<span style="color: #000000">(obj.price)
<span style="color: #0000ff">del obj.price <span style="color: #008000">#<span style="color: #008000"> 删除商品原价

3,classmethod

= @classmethod </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; func(cls): </span><span style="color: #0000ff"&gt;print</span><span style="color: #000000"&gt;(cls.role)

Classmethod_Demo.func()

4,staticmethod

= @staticmethod </span><span style="color: #0000ff"&gt;def</span><span style="color: #000000"&gt; func(): </span><span style="color: #0000ff"&gt;print</span>(<span style="color: #800000"&gt;"</span><span style="color: #800000"&gt;当普通方法用</span><span style="color: #800000"&gt;"</span><span style="color: #000000"&gt;)

Staticmethod_Demo.func()

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读