Python学习(24)--面向对象编程1

这一节我们将介绍使用面向对象的编程思想来组织和编写Python代码,首先我们会讲解面向对象的思想,类和对象的概念。接着,将会介绍类中一些常用的方法,如构造函数,打印函数,析构函数等等。

1.面向对象思想

面向对象和面向过程都是一种编程思想,之前我们编写的代码,实现的功能都很简单,代码量也不多,也没有涉及到面向对象的编程思想,但当我们需要编写大量的代码去完成一个工程时,就需要考虑如何组织代码来高效的完成这个工程,这个时候就用到了面向对象。那么什么是面向对象?

面向对象可以和面向过程对比着来理解.例如盖一间房子,面向过程考虑的事情是盖房子的过程,比如先打地基,然后用砖砌墙,再搭房梁等等。面向过程会把盖房细节和盖房需要完成任务的先后次序都会林列出来,然后按部就班的完成盖房子这件事情。

而面向对象考虑的是房子这个对象是由哪些部件组成的,比如一个房子有地基,窗户,墙,房梁,房顶等等。而不会考虑如何打好地基,如何去砌墙等等这些细节问题,只会考虑一个房子有什么?具体房子某一个部分如何做的任务会交给相应的工人去完成。

2.类的概念

在面向对象中,类是一个抽象的概念,抽象的东西描述的都是事物的共性。例如人就是一个抽象的概念,人的共性有姓名,年龄,身高,体重等等标签,人的共性还有走路,吃东西等等行为。具体的每个人又有不同的姓名年龄,喜欢吃不同的东西,又体现出具体事物间的个性。

人这种抽象概念,在面向对象的世界里对应的是一个类;人的共性中的标签,在面向对象中对应的是类的属性;人的共性中的行为,在面向对象中对应的是类中的方法。具体的人又是人这个类的实例对象。在Python中定义一个类的格式如下:

在Python中定义一个类使用的是关键字class,表示这是一个类。后跟类的名字和父类列表,父类列表中是类的父类,涉及到继承的概念,以后会介绍到。所有的类都会有一个共同的父类(或者称之为超类或基类),就是object类,如果一个类没有特殊指定的父类,那么在定义类时父类列表一般只有object类,或者为空。最后,在类中定义类的属性和方法行为。

以人这个抽象概念为例,类的定义代码如下:

[python] view plain copy

  1. class Person():
  2. name=""
  3. age=0
  4. height=0
  5. weight=0
  6. def run(self):
  7. print("running...")
  8. def eat(self,food):

[python] view plain copy

  1. print(self.name+" eat "+food)

如上为一个类名为Person的类,父类列表为空,默认直接继承于object类。Person类的属性有name,age,height,weight;定义的方法行为有,run(self)和eat(self,food)。这里需要注意的是,在Python中,每一个类中的方法参数列表不能为空,至少要有参数self,self表示的是类的当前对象。例如,Person类有一个实例对象zhangsan,那么self表示的就是zhangsan这个对象。代码如下:

[python] view plain copy

  1. zhangsan=Person()#创建一个变量名为zhangsan的Person对象
  2. zhangsan.name="zhangsan"#将对象zhangsan的属性name的值设置为"zhangsan"
  3. zhangsan.eat("Apple")

通过如上代码,可以发现创建类的实例化对象的方式为:对象名=类名(参数列表),参数列表在之后的构造函数中会介绍到,如zhangsan=Person()就是创建了一个Person类的对象;获取对象属性的方式为:对象名.属性名,如zhangsan.name="zhangsan";对象调用方法的方式为:对象名.方法名(参数列表),如zhangsan.eat("Apple"),为调用Person类中定义的方法eat(self,food),打印结果如下:

Person类的方法eat(self,food)中的代码如下:

[python] view plain copy

  1. def eat(self,food):
  2. print(self.name+" eat "+food)

在对象zhangsan调用方法eat(self,food)时,参数self表示的是对象zhangsan;self.name表示的是对象zhangsan的name属性值:"zhangsan",所以zhangsan.eat("Apple")的打印结果为"zhangsan eat Apple"。

其实,类和Python中其他基本数据类型一样,都只是一种数据类型,只不过类的数据结构更加复杂,更加抽象。使用类创建的对象相当于基本数据类型的一个变量,是占据内存空间的一个实例。

3.参数self

在类中的,一个方法的参数列表的第一个参数代表的含义是该类的当前对象。之前我们在设计Person类时,方法eat(self,food),其中第一个参数为self,表示的就是Person类的当前对象,但是需要注意的是self并不是一个关键字,Python中只是默认类中方法参数列表的第一个参数代表该类的当前对象,self只是一个形参名,也可以使用其它形参名来代替,只不过使用self含义更加见名知意。如下,我们可以换一个形参名来证明以上所述:

[python] view plain copy

  1. class Person():
  2. name=""
  3. age=0
  4. height=0
  5. weight=0
  6. def run(I):
  7. print(I.name)
  8. print("running...")
  9. def eat(I,food):
  10. print(I.name+" eat "+food)
  11. per=Person()
  12. per.name="zhangsan"
  13. per.run()

如上代码所示,将Person类中方法的参数名self全部替换为I。然后创建一个Person类的对象per,并修改其name属性的值为"zhangsan",当per调用方法run()时,参数列表第一个参数I表示的就是当前对象per,打印结果如下:

通过打印结果可以看出,将Person类中的方法参数名self全部替换为I后,并没有出现错误提示,这是因为Python默认将类中方法参数列表的第一个参数识别为当前对象,这也决定了类中每一个方法的参数列表至少有一个参数,如果只有一个参数,那么这个参数的含义就是代表当前对象。

一般并不建议修改参数名self,这样降低程序的可读性。

4.类的构造函数

构造函数用于在创建一个类的实例对象时,初始化对象的属性值。对应到现实中,每个具体的人在出生时,姓名、体重、身高这些属性都可能有不同的属性值。而定义一个类的构造函数和定义方法的形式是一样的,如下是Person类的构造函数:

[python] view plain copy

  1. def __init__(self,name,age,height,weight):
  2. self.name=name
  3. self.age=age
  4. self.height=height
  5. self.weight=weight

每个类的构造函数的函数名都是__init__,参数列表一般为类的属性,在构造函数中执行的操作为初始化对象的属性值。如self.name=name为初始化当前被构造对象的name属性值。如下代码:

[python] view plain copy

  1. class Person():
  2. def __init__(self,name,age,height,weight):
  3. self.name=name
  4. self.age=age
  5. self.height=height
  6. self.weight=weight
  7. def run(self):
  8. print(self.name)
  9. print("running...")
  10. def eat(self,food):
  11. print(self.name+" eat "+food)
  12. per=Person("zhangsan",12,123,50)
  13. print(per.name,per.age,per.height,per.weight)

如上代码,通过构造函数创建并初始化了一个Person对象per,并打印per的属性值,打印结果如下:

需要注意的是,一个类没有构造函数也能创建这个类的对象,之所以如此,是因为类中有一个默认的构造函数,如下:

[python] view plain copy

  1. def __init__(self):
  2. pass

如果没有为类定义构造函数,创建对象时使用的是默认构造函数。

5.析构函数

构造函数是在内存中创建 一个类的对象,而析构函数是销毁该类在内存中的对象。在类中定义一个析构函数,用于动态的释放程序内存。但是由于Python中有垃圾回收机制,所以一般不需要用户自己释放内存。析构函数也一般不常用,这里只做简单的介绍。

在类中定义一个析构函数,就是定义一个函数名为__del__的方法,如下就是一个简单的析构函数,当用户销毁类的实例对象时,会调用这个方法。

[python] view plain copy

  1. def __del__(self):
  2. print("this is person's del")

那么如何销毁一个实例对象呢?其实和之前介绍的在内存中销毁一个基本类型数据的方式是一样的,即del 对象名。如下代码:

[python] view plain copy

  1. class Person():
  2. def __init__(self,name,age,height,weight):
  3. self.name=name
  4. self.age=age
  5. self.height=height
  6. self.weight=weight
  7. def run(self):
  8. print(self.name)
  9. print("running...")
  10. def eat(self,food):
  11. print(self.name+" eat "+food)
  12. def __del__(self):
  13. print("this is person's del")
  14. person1=Person("zhangsan",10,123,40)
  15. del person1

如上,创建了一个Person类的对象person1,并销毁它。当销毁对象person1时,就会调用Person类的析构函数__del__(self)。代码打印结果如下:

6.打印函数__str__(self)和__repr__(self)

在Python编程过程中,有时候我们可能需要打印一个对象的具体属性信息。这个时候就用到了打印函数__str__(self)和__repr__(self)。两者主要有两个不同点:一是在命令窗口模式下打印结果的不同;二是优先级的不同。如下我们在不使用打印函数的情况下打印一个对象。

[python] view plain copy

  1. class Person():
  2. def __init__(self,name,age,height,weight):
  3. self.name=name
  4. self.age=age
  5. self.height=height
  6. self.weight=weight
  7. def run(self):
  8. print(self.name)
  9. print("running...")
  10. print(self.__class__)
  11. person = self.__class__("wangwu", 13, 123, 40)
  12. def eat(self,food):
  13. print(self.name+" eat "+food)
  14. person1 = Person("zhangsan", 10, 123, 40)
  15. print(person1)

打印的结果如下:

可见在不使用打印函数的情况下,打印一个对象,显示的只是对象的类型和对象在内存中的地址,而用户真正关心的对象属性信息并没有打印出来。使用打印函数不仅可以打印用户真正关心的信息,还可以可以自定义信息打印的形式。如下是一个使用打印函数打印对象的例子:

[python] view plain copy

  1. class Person():
  2. def __init__(self,name,age,height,weight):
  3. self.name=name
  4. self.age=age
  5. self.height=height
  6. self.weight=weight
  7. def run(self):
  8. print("running...")
  9. def eat(self,food):
  10. print(self.name+" eat "+food)
  11. def __repr__(self):
  12. return "__repr__:"+self.name+"-"+str(self.age)+"-"+str(self.weight)+"-"+str(self.height)
  13. def __str__(self):
  14. return "__str__:"+self.name+"-"+str(self.age)+"-"+str(self.weight)+"-"+str(self.height)
  15. person1=Person("zhangsan",10,123,40)
  16. print(person1)

如上,在Person类中定义了两个打印函数__repr__(self)和__str__(self),都用于打印对象的属性信息。打印结果如下:

通过打印结果可见,在打印Person对象时,调用了方法__str__(self),打印了此方法返回的字符串。如果类中__str__(self)和__repr__(self)两个打印函数都存在,使用print函数打印对象时,Python会先调用方法__str__(self),因为前者的优先级要比后者的优先级要高。只有当类中只有函数__repr__(self)时,打印对象才会调用__repr__(self)。

两者的不同点还体现在命令窗口的交互模式下,在命令窗口模式下,一般适用于使用__repr__(self)。两者在打印结果上有着稍微的不同。如下:

如上,当类中只有方法__repr__(self)时,无论是>>>person 回车或者直接print(person)都会调用Person对象的__repr__(self)方法打印结果。

如上,当类中只有方法__str__(self)时,print(person)会调用Person对象的方法__str__(self);而>>>person 回车却没有调用打印函数,只是打印的对象的类型和内存地址。

如上,在交互模式下,>>>person 回车调用的是打印函数__repr__(self);而print(person)调用的是打印函数__str__(self)。可以这样理解,在交互模式下>>>对象名 回车,打印一个对象时,打印函数__repr__(self)的优先级要比__str__(self)高,所以使用这种方式打印对象,会调用对象的__repr__(self);而使用print(对象名)打印一个对象时,__str__(self)优先级较高,所以会优先调用函数__str__(self)打印对象。

以上就是这节介绍的所有内容,下一节将会继续介绍面向对象中的继承和多态的编程思想,敬请期待。

原文地址http://www.bieryun.com/2378.html

Python学习(24)--面向对象编程1相关推荐

  1. Python学习之面向对象编程

    Python学习目录 在Mac下使用Python3 Python学习之数据类型 Python学习之函数 Python学习之高级特性 Python学习之函数式编程 Python学习之模块 Python学 ...

  2. 从零开始学习python编程-从0开始的Python学习014面向对象编程(推荐)

    简介 到目前为止,我们的编程都是根据数据的函数和语句块来设计的,面向过程的编程.还有一种我们将数据和功能结合起来使用对象的形式,使用它里面的数据和方法这种方法叫做面向对象的编程. 类和对象是面向对象编 ...

  3. Python学习之==面向对象编程(一)

    一.面向对象与面向过程 面向对象与面向过程是两种不同的编程范式,范式指的是按照什么方式去编程.去实现一个功能.不同的编程范式本质上代表对各种不同类型的任务采取不同的解决问题的思路. 1.面向过程编程 ...

  4. python学习之面向对象编程--搬家具

    代码展示: class Furniture():def __init__(self, name, area):self.name = nameself.area = areaclass Home(): ...

  5. Python学习之面向对象高级编程

    Python学习目录 1. 在Mac下使用Python3 2. Python学习之数据类型 3. Python学习之函数 4. Python学习之高级特性 5. Python学习之函数式编程 6. P ...

  6. Python类及面向对象编程【转】

    Python类及面向对象编程 类是用来创建数据结构和新类型对象的主要机制.本章的主题就是类,面向对象编程和设计不是本章的重点.本章假定你具有数据结构的背景知识及一定的面向对象的编程经验(其它面向对象的 ...

  7. python采用面向对象编程模式吗_如何理解 Python 中的面向对象编程?

    现如今面向对象编程的使用非常广泛,本文我们就来探讨一下Python中的面向对象编程. 作者 | Radek Fabisiak 译者 | 弯月,责编 | 郭芮 以下为译文: Python支持多种类型的编 ...

  8. python基础之面向对象编程

    python基础之面向对象编程 面向对象编程思想 面向对象是一门编程思想,编程思想仅仅是一门思想,与任何技术无关 核心是对象两字,对象可以理解为特征与技能的结合体 基于该编程思想编写程序,就好比创造世 ...

  9. python如何初始化对象数组_如何理解Python中的面向对象编程?

    (由Python大本营付费下载自视觉中国) 作者 | Radek Fabisiak 译者 | 弯月,责编 | 郭芮 出品 | CSDN(ID:CSDNnews) 现如今面向对象编程的使用非常广泛,本文 ...

  10. 如何理解 Python 中的面向对象编程?

    现如今面向对象编程的使用非常广泛,本文我们就来探讨一下Python中的面向对象编程. 作者 | Radek Fabisiak 译者 | 弯月,责编 | 郭芮 出品 | CSDN(ID:CSDNnews ...

最新文章

  1. Android Studio 第五十期 - 自定义TabLayout
  2. 史上最全的长读长数据校错方法大比拼
  3. Android 计算Bitmap大小
  4. Zookeepe实践与应用--分布队列
  5. MySQL5.7本地首次登录win10报错修改
  6. 【源码】2012年斗地主算法大全
  7. HTTP状态:202、301、304、404、503
  8. 关于路径的问题(以后会慢慢的补进来)
  9. 照葫芦画瓢之老男孩购物车程序
  10. 用vbs脚本实现软件的自动登录
  11. 华东师范大学《模式识别与机器学习》试题
  12. 如鹏网.Net高级技术4.String特点及常用方法
  13. python无穷大怎么表示_python如何表示无穷大
  14. cd linux安装到u盘,安装 CDLinux 到移动硬盘或U盘
  15. UML之教学管理系统——4、Rational Rose画活动图
  16. 信息安全等级测评内容
  17. 视频教程-【吴刚大讲堂】电商品牌文案设计方法-电子商务
  18. 解决windows电脑蓝屏的方法
  19. 少儿编程scratch与机器人
  20. 吊打 CLIP 平均10个点,Meta 多模态通用模型 FLAVA真香啊

热门文章

  1. unity中连接MySQL数据库的方法封装
  2. glibc的几个有用的处理二进制位的内置函数(转)
  3. 5个基于Javascript的桌面
  4. 将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止位的地方...
  5. 不同数据库之间的独立性
  6. BZOJ5212: [Zjoi2018]历史
  7. robotframework 接口测试 +RSA 加密
  8. 利用socket.io构建一个聊天室
  9. Google Chrome Native Messaging开发实录(二)Chrome Extension扩展
  10. Jmeter插件监控服务器性能