清华大佬详解Python面向对象,深化学习有妙招

前言

Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。本文我们将详细介绍Python的面向对象编程。

如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。

接下来我们先来简单的了解下面向对象的一些基本特征。

一、对面向对象的理解

1、面向对象的编程---object oriented programming

简称:OOP,是一种编程的思想。OOP把对象当成一个程序的基本单元,一个对象包含了数据和操作数据的函数。面向对象的出现极大的提高了编程的效率,使其编程的重用性增高。

2、python面向对象的重要术语:

  1、多态(polymorphism):一个函数有多种表现形式,调用一个方法有多种形式,但是表现出的方法是不一样的。

  2、继承(inheritance)子项继承父项的某些功能,在程序中表现某种联系

  3、封装(encapsulation)把需要重用的函数或者功能封装,方便其他程序直接调用

  4、类:对具有相同数据或者方法的一组对象的集合

  5、对象:对象是一个类的具体事例

  6、实例化:是一个对象事例话的实现

  7、标识:每个对象的事例都需要一个可以唯一标识这个事例的标记

  8、实例属性:一个对象就是一组属性的集合

  9、事例方法:所有存取或者更新对象某个实例一条或者多条属性函数的集合。

  10、类属性:属于一个类中所有对象的属性,

  11、类方法:那些无须特定的对性实例就能够工作的从属于类的函数。

3、函数和面向对象编程的区别

  相同点:都是把程序进行封装、方便重复利用,提高效率。

  不同点:函数重点是用于整体调用,一般用于一段不可更改的程序。仅仅是解决代码重用性的问题。

  而面向对象除了代码重用性。还包括继承、多态等。使用上更加灵活。

二、封装、继承、多态

1、封装(Encapsulation)

封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。 

对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

2、继承(Inheritance)

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

例如:

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

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

公共的部分就是 吃、喝、拉、撒

如下实现:

注意: 关于多继承 

- 在Python中,如果父类和子类都重新定义了构造方法init( ),在进行子类实例化的时候,子类的构造方法不会自动调用父类的构造方法,必须在子类中显示调用。 

- Python的类可以继承多个类,Java和C#中则只能继承一个类 

- Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先 

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

3、多态(Polymorphism)

首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型。

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述: 

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。

鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。

例子:

没有谁规定test方法是接收的参数是什么类型的。test方法只规定,接收一个参数,调用这个参数的prt方法。在运行的时候如果这个参数有prt方法,python就执行,如果没有,python就报错,因为abcde都有prt方法,而f没有,所以得到了上边得结果,这就是python的运行方式。

三、面向对象的各种方法

1、静态方法(用这个装饰器来表示  @staticmethod  )

意思是把 @staticmethod 下面的函数和所属的类截断了,这个函数就不属于这个类了,没有类的属性了,只不是还是要通过类名的方式调用  

看个小例子:

因为用静态方法把eat这个方法与Person这个类截断了,eat方法就没有了类的属性了,所以获取不到self.name这个变量。

2、类方法  (用这个装饰器来表示 @classmethod)

类方法只能访问类变量,不能访问实例变量

看个例子:

因为用静态方法把eat这个方法与Person这个类截断了,eat方法就没有了类的属性了,所以获取不到self.name这个变量。

3、属性方法 (用这个装饰器表示 @property)

把一个方法变成一个静态属性,属性就不用加小括号那样的去调用了

看个小例子:

因为eat此时已经变成一个属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了 

四、高级面向对象

1、成员修饰符

python的类中只有私有成员和公有成员两种,不像c++中的类有公有成员(public),私有成员(private)和保护成员(protected).并且python中没有关键字去修饰成员,默认python中所有的成员都是公有成员,但是私有成员是以两个下划线开头的名字标示私有成员,私有成员不允许直接访问,只能通过内部方法去访问,私有成员也不允许被继承。

上面就是类里面的私有成员了。

2、特殊成员

1.__init__

__init__方法可以简单的理解为类的构造方法(实际并不是构造方法,只是在类生成对象之后就会被执行),之前已经在上一篇博客中说明过了。

2.__del__

__del__方法是类中的析构方法,当对象消亡的时候(被解释器的垃圾回收的时候会执行这个方法)这个方法默认是不需要写的,不写的时候,默认是不做任何操作的。因为你不知道对象是在什么时候被垃圾回收掉,所以,除非你确实要在这里面做某些操作,不然不要自定义这个方法。

3.__call__

__call__方法在类的对象被执行的时候(obj()或者 类()())会执行。

4.__int__

__int__方法,在对象被int()包裹的时候会被执行,例如int(obj)如果obj对象没有、__int__方法,那么就会报错。在这个方法中返回的值被传递到int类型中进行转换。

5.__str__

__str__方法和int方法一样,当对象被str(obj)包裹的时候,如果对象中没有这个方法将会报错,如果有这个方法,str()将接收这个方法返回的值在转换成字符串。

6.__add__

__add__方法在两个对象相加的时候,调用第一个对象的__add__方法,将第二个对象传递进来,至于怎么处理以及返回值,那是程序员自定义的,就如下面的例子:

7.__dict__

__dict__方法在类里面有,在对象里面也有,这个方法是以字典的形式列出类或对象中的所有成员。就像下面的例子:

8.__getitem__ __setitem__ __delitem__

__getitem__方法匹配 对象[索引] 这种方式,__setitem__匹配 对象[索引]=value 这种方式,__delitem__匹配 del 对象[索引] 这种方式,例子如下:

9.__getslice__ __setslice__ __delslice__

这三种方式在python2.7中还存在,用来对对象进行切片的,但是在python3之后,将这些特殊方法给去掉了,统一使用上面的方式对对象进行切片,因此在使用__getitem__ __setitem__ 这两个方法之前要先判断传递进参数的类型是不是slice对象。例子如下:

10.__iter__

类的对象如果想要变成一个可迭代对象,那么对象中必须要有__iter__方法,并且这个方法返回的是一个迭代器。

for 循环的对象如果是一个可迭代的对象,那么会先执行对象中的__iter__方法,获取到迭代器,然后再执行迭代器中的__next__方法获取数据。如果for循环的是一个迭代器,那么直接执行迭代器中的__next__方法。

以上就是小编为大家整理的Python面向对象,有写的不对的地方,请大佬多多指教,共同进步。

另外,小编还为大家整理了一些清华大佬整理的Python面向对象的学习视频资料,还有基础教程,有需要的小伙伴记得关注小编,并添加微信:bjmsb1来免费领取吧~~~

你可能感兴趣的:(清华大佬详解Python面向对象,深化学习有妙招)