导读
- 这节内容对新手程序员可能是个挑战,面向对象编程的思维方式与能力的建立是程序员技能的一个分水岭,如果你觉得有难度可以浏览下先略过,写一段时间代码后再回来学习也不晚,但是,无论如何还是要认真阅读理解下本节课程。
- 提问本节的问题前请确保完整通读本教程2遍以上再问。
面向对象
- 首先我们要说下这个标题,面向对象编程,这是一种编程的思维模式,当我们只写一个小功能的代码的时候,可能只是需要几行就可以了,这个时候我们着眼的是一个个小功能是实现,这种思维模式就不是面向对象编程的思维。
- 如果,我们要写一个基于Python的软件开发项目,内容是无人驾驶辅助系统,这个时候你会发现,这么大的项目,不是流水线样式的编程思路,需要若干个不同功能的代码共同完成,相互之间还有制约和影响。
- 此时,我们就要用面向对象来编程了,就是把现实世界看成一个个对象,然后使用把这些大的对象,分解成小的对象,再用代码实现小对象,最后组合调用构成一个项目。
- 我们使用对象来模拟一切现实世界,而不是纠结于具体的代码实现,理解面向对象后,你就可以用宏观逻辑思维来构思一个开发项目,开发的时候就有种按图索骥的信心,把虚拟代码和现实世界一一对应,这种思维和方法几乎可以解决任何问题。
- 除此之外,一个大的开发项目,往往需要团队完成,按照面向对象的思维和分工,大家协同开发,每个人只负责整体框架下的一小部分,最后再合并。
我们先用:面向过程,的思路来看看:
- 写一个定义鸟儿的项目,用字典把小鸟的属性和行为写出来:
# 代码01 bird_1 = {'name':'Woodpecker','eat':'worm'} bird_2 = {'name':'eagle','eat':'rabbit'} # 如果说明啄木鸟和老鹰吃虫子和兔子,面向流程的思维方式: print('%s eat %s' % (bird_1['name'], bird_1['eat'])) print('%s eat %s' % (bird_2['name'], bird_2['eat'])) # %s 是格式化输出字符串的方法 # 使用函数 def bird_eat(bird): print('%s eat %s' % (bird['name'], bird['eat'])) bird_eat(bird_1) bird_eat(bird_2)
output:
Woodpecker eat worm eagle eat rabbit Woodpecker eat worm eagle eat rabbit
- 上面是面向过程的思路,就是流程顺序化编写代码。
- 如果是面向对象的思路,我们从逻辑层面考虑:既然是鸟,就有名字这个属性,也有吃什么食物这个行为,我们就可以定义一个鸟的类,这个对象有一个属性是名字,有一个行为是吃食物。
- 我们定义好这个类后,需要的时候调用这个类的一个方法函数,输出吃什么食物,如果还有其他的行为,我们一直在这个类中添加函数就可以了,不用按顺序,需要上面行为(方法)就调用什么,几乎可以解决关于鸟儿的所有问题了,这就是面向对象编程,下面我们代码演示:
# 代码02 class Bird(): '''鸟儿吃什么食物的一个类测试''' def __init__(self, name, eat): '''初始化属性name和eat''' self.name = name self.eat = eat def print_eat(self): '''鸟儿吃什么东西的方法''' print(self.name.title() + ' eat ' + self.eat.title()) bird_1 = bird('Woodpecker', "worm") bird_2 = bird('eagle', "rabbit") bird_1.print_eat() bird_2.print_eat()
output:
- 这里会报错,是特意设置,请自行debug
Woodpecker eat Worm Eagle eat Rabbit
下面我们来详细解析下这个bird类:
-
类的声明语法是首字母大写;
-
三组引号是文档说明的格式;
-
从构思鸟儿吃什么到定义各个变量和函数的过程是基于对象思维实现的,即是面向对象;
-
类: 就像是描述某个对象的设计图纸,是描述对象共性属性和方法的集合;
-
方法:类中的函数;
-
属性:类的共性变量
-
init方法是特殊的函数(init前后有个下划线,最后一个括号),每次根据类创建新的实例的时候,都会运行它;
-
根据类创建实例这句话的意思是:我们创建的类是具有某些共性的对象,如果我们要具体对一个对象通过调用类来实现我们想要的结果,这一具体的一次过程就是一个实例;
-
我们定义init方法的时候,用了self、name和eat三个形参;
-
所谓形参,就是定义类中方法的时候写的参数,区别于实参,实参是对类实例化的过程中传递的实际使用的参数;
名词备忘:
- 类:class
- 实例:instance
- 对象:object
- 方法:method
- 函数function
- Self类似C++的this指针,如果没有接触过C++我们换一个方式理解它:
- 举例:如果我们有一个汽车的class,那么基于这个class可以建立很多instance的object,即不同的汽车,那么这些汽车都是相似的,哪一个才是自己的呢,self就可以帮到你识别。
# 代码03 class Test(): def Name(self, name): self.name = name def who(self): print('我是 %s ,你好!' % self.name) a = Test() # 标记01 a.Name('test01') a.who() class Test2(object): def __init__(self, name): # 标记02 self.name = name def who(self): print('我是 %s ,你好!' % self.name) b = Test2('test02') b.who() class Test3(): def __init__(self): self.a = '没有self就用不了c.a了哦,你瞅啥,瞅你咋滴,你去了self试试看!' c = Test3() print(c.a)
output:
我是 test01 ,你好! 我是 test02 ,你好! 没有self就用不了c.a了哦,你瞅啥,瞅你咋滴,你去了self试试看!
-
我们再看03这个代码:
-
Test和Test2是类名,括号里面的是默认的对象(object或空),# 标记01就是类的一个实例;
-
我们使用# 标记01的方式,把类的共性用就是属性提前定义好。
-
其实类中的方法和普通函数一样,只是多了一个self。加了self就是全局变量,都可以用,不加self的变量,只能具体的函数使用。
-
Test3例子就是这样的,你可以自己去掉self试试看。
通过前十节课,我们基本上入门了Python的基本技能,后面就是Python的初级应用:使用Python做基础数据分析。
练习题,关注下方公众号获取答案(后台输入:Python练习答案):
本节练习比较抽象和困难,先思考几遍找到思路,使用面向对象的方法:
-
构架一个汽车的类,包含的属性有:品牌、车型、年份,每个方法都要有注释,构建一个显示汽车属性的方法(输出的语句每个单词首字母大写),然后调用类中的任意属性显示出来;
-
另外定义一个更新里程的属性和方法,并禁止里程表往回调。