python入门-------夜曲编程

1.格式化io

除了使用加号+连接字符串,我们还可以通过格式化输出的方式来对字符串进行“填空”。

格式化输出的语法如图:

1.在字符串常量前添加小写字母f

2.字符串中需要“填空”的地方使用大括号 { } 括起来

3.将需要填空的内容填入大括号 { } 中

2.表又称线性结构,是一种最简单也最基础的数据结构。

一个线性表是由多个逻辑相关的数据所组成的序列。列表就是一种线性表,但线性表不只有列表。

隐喻
索引是在数据结构中用来定位和寻找数据的检索方式。
前面的课程中我们使用Fruit[0]来访问列表的第一个数据,这个0就是索引。
所以我们可以说,列表的索引就是从0开始的。
隐喻

索引就像中药柜子上的标签,用于准确找到某种药材。

----------------------列表删除pop()

在Python中对列表进行“弹出”操作,我们可以使用.pop( )方法。

我们在.pop( )括号中可以填入具体需要删除的数据所对应的索引位置,如图中代码的第4行。

我们也可以不在.pop( )括号中填入任何数据,这时候代码会默认删除最后一个数据,如图中代码的第7行。

使用pop()删除指定的数据后,还会记录被删除的数据,如有必要可以将此数据赋值给一个变量在之后使用。

除了pop( ),我们还可以使用del( )方法来删除列表中的某个数据。

del( )并不是列表中内置的一个功能,而是Python中用来删除某个数据的通用方法。

所以如图所示,我们可以直接使用del,不需要通过列表名加点(.)的方法。

概念卡No.032    for

循环循环也是计算机程序的三大语句结构之它是在满足条件的情况下,反复执行某段代码的计算过程循环就像在运动场里跑園,在结束条件达到之前,都会一闘一的“跑下去。

在编程中,这样的例子有很多。

比如想要打印一个列表中的全部元素,我们可以使用多个print()语句,按照顺序,依次打印。

定义计数循环又称for循环,是一种以关键字for开头,通过计数器是否完成遍历来判断是否终止循环的代码执行结构。隐喻计数循环就像心里数着数跑操场五,跑到五就不跑了。

应用:

for循环经常应用在多个数累加/累乘的计算中,也就是说需要反复多次地对大量数字进行同样地操作。

比如我有一个列表,里面是自己京东账户购物车里的5件商品的价格,然后需要计算清空购物车花多少钱。

8、24今天我们继续学习另外一种循环语句,条件循环,又称while循环。

同样是打印一个list里面的所有元素,如何使用while循环来完成?

概念卡No.035条件循环while

条件循环又称 while循环,是一种以关键字while开头,以判断条件是否成立来决定是否重复执行某些代码的执行顺序。判断条件为真就继续循环执行,判断条件为假就经止循环。隐喻条件循环就像固定的航斑,天气正常的时候就会一直往返飞行,天气不好的时候才会停止飞行。

从代码的输出来看,这两段代码执行了相同的功能,它们的区别在哪里?
第一个区别:
for循环是在每一次循环的时候,按照从头到尾的顺序自动遍历,给变量i赋值列表中的元素;
而while循环是用变量j作为一个计数器来索引列表,分别访问这个列表里面的每个元素。

那什么是计数器呢?
图中,变量j就是一个计数器,它的作用是通过自身值的不断变化来索引出列表NumberList中对应的值,推动while循环的进行。
需要注意的是,不一定是j或者n才是计数器,任意一个变量都可以设置为一个计

值得注意的是,自增或者自减的书写形式不止是我们上面看到的那种,很多时候为了方便,我们也会像如图这样书写。

a+=2其实就是a=a+2

a-=1其实就是 a=a-1

当然,自增或者自减后面的数值只是一个范围的大小,可以根据实际情况设定。数器。

第二个区别:

循环的终止条件不一样。

for循环的终止条件是遍历完这个list;

而while循环的终止条件是一个比较运算,j<5,当这个比较条件为True的时候继续执行代码,为False的时候就终止执行。这个终止条件我们又叫边界条件。

一个良好的while循环结构需要对判断条件进行精心地设计和控制。

可以看出,while循环和if判断有一定的相似度,他们都依赖一个判断条件的True或False。

如果是True,就执行“自己内部”的代码块,如果是False,则不执行“自己内部”的代码块。

第三个区别:

while循环是有可能一直运行的。只要判断条件为真,它就会一直执行下去。

这点和for循环不一样,因为for循环是有天然的边界条件——完成遍历。

比如图中代码就会永远执行,这种循环我们又叫做”死循环”。

学完今天的课程,你明白for循环和while循环的区别了吗?

简而言之,需要记住三条。

1. for循环又叫计数循环,多用于批量处理列表内的每个元素;while循环又叫条件循环,多用于条件判断。

2. for循环有天然的边界条件,while循环没有,需要程序员精心设计。

3. 大多数时候,for循环和while循环可以互换使用。

概念卡 No.039 迭代  Iteration

定义

编程中的迭代是指重复执行某些代码,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。

在实际应用中迭代经常和循环混用。

隐喻

迭代就像螺旋一样,一圈一圈的进行下去,每一圈都会变得更好(更大)一点。

第一个关键字:continue。

continue的作用:跳过本次迭代(小循环)中它后面的剩余代码,直接进入下一次迭代。

在for循环和while循环中,我们会经常用到continue。

break\定义

break会“跳出”或终止某一个循环,它结束的是整个循环结构。

可能学到这里,有的同学就会疑惑,难道实现大于5的输出就要用continue,小于5的输出就要用break吗?

当然不是。编程的世界是非常灵活的,即使最终的输出一样,编写的程序也可以千变万化。

例如,我们使用continue+while循环,也能实现输出1-10中小于5的数。

注意,无论if判断为True还是Flase,我们都会执行自增计算i= i + 1,因为i作为一个计数器,要推动循环的进行就必须不断的取值。

同样的,当我们改变if判断的条件,在if判断为True的时候,执行break,代码就无法打印任何结果。

因为i第一次取值进入if判断时为True,执行到break的时候,整个while循环就结束了。循环终止,没有任何打印输出。

同样的,当我们改变if判断的条件,在if判断为True的时候,执行break,代码就无法打印任何结果。

因为i第一次取值进入if判断时为True,执行到break的时候,整个while循环就结束了。循环终止,没有任何打印输出。所以,为了能够更灵活地控制代码的执行顺序,我们经常在循环结构里面使用continue和break。

不同之处在于:

continue是跳过小循环中剩下的代码,继续下一次迭代。而break直接终止整个大循环。

到目前为止,我们已经学习完了三大执行语句~

可以看出,在代码的世界中,执行顺序是一个很重要的部分。

所以我们在学习过程中,一定要先学会分析,哪些代码是顺序执行,哪些代码是判断执行,哪些代码是循环执行,这样才能更好的理解程序是如何运行的。

第一种执行顺序是顺序语句。

顺序执行是最简单的。

图中就是最简单的顺序语句,每一行代码都按照从上至下的顺序执行。

一、

顺序执行也是最常用的。

图中,我们一共打印了三次变量a的值,每一次打印的结果都不一样。

因为代码是按照从上往下顺序执行的,所以每次都是打印出来的值,都是变量a最新一次赋值的值。

二、

第二种执行顺序是条件语句,它的特点是:

1.条件为真(True),则执行分支代码

2.条件为假(False),则不执行分支代码

图中,第三行代码条件判断为True,则执行第四行和第五行代码。

图中,我们修改了第三行代码的判断条件,导致判断为False。因此代码执行到第三行就停止了。注意,不管条件判断为True还是False,条件判断语句本身是一定会执行的,因为它和第一行、第二行代码是同样的缩进(属于同一个优先级的代码块)。

同样地,在if-else语句中,代码执行顺序也是类似的原则:

1.if的判断条件成立,为真(True),执行if内部(缩进)的代码

2.if判断条件不成立,为假(False),则执行else内部(缩进)的代码。

而在if-elif-else语句中,同样还是类似的执行顺序,只不过要进行三次的条件判断。

注意除了if和elif以外,else也涉及到一次条件判断。

图中,如果if和elif的判断条件都是False,else就会判断为True,执行它内部的代码。

第三种执行顺序是循环语句,它的特点是:

当循环的边界条件未被触发的时候,一直重复运行循环中的代码。

图中,在列表NumberList中的值未被取完之前,第二三行代码会一直重复运行,直到列表NumberList中的所有值都被取完,循环才会结束。

三、

while循环和for循环,在代码执行顺序上没有区别。

都是在触发边界条件之前,反复判断循环条件以及执行循环中的代码块。

continue和break是为了让我们能够更灵活的使用循环语句。

它们只能都在循环中使用,控制循环的进行。

range() 函数可以创建一个整数列表,一般用在 for 循环中。

range()一般有两个参数, 这两个参数生成一个左闭右开的区间。

如果只传了一个参数, 表示是0到这个参数的左闭右开的区间。

比如,range(1001)就能生成一个0到1000的数列。

range(1,100)就能生成一个1到99的数列。

ange(),我们就能很方便地进行累加计算了。

图中,我们进行一次1到1000的累加。

设置累加器Sum并初始化为0,然后进入for循环,依次从range(1001)中取出0-10

因此,有了range(),我们就能很方便地进行累加计算了。

图中,我们进行一次1到1000的累加。

设置累加器Sum并初始化为0,然后进入for循环,依次从range(1001)中取出0-1000的数值赋值给i,每次将i与Sum相加的和再次赋值给Sum。Sum不断带着新值进入下一次循环,完成累加。

循环结束以后,程序跳出循环,顺序执行同级代码,打印最终Sum的值。

同样地,如果我们结合之前学到的.append(),想要把0到100的所有偶数添加到一个新列表里面也很方便。

首先,我们设置一个空列表NewList,然后在for循环中嵌套一个if判断语句:i%2 == 0,因为如果i是偶数的话,它是能被2整除的,也就意味着它对2取模应该等于0。

最后我们依次将取得的所有偶数都添加进列表NewList中。直到循环结束,程序跳出循环,执行print语句,打印输出结果。

之前我们在学习while循环的时候,需要自己设定判断条件,比如j<5。这是一个非常“死板”的判断条件。不仅依靠我们人为去计数,而且只适用于元素数量为5的列表。

为了增加这段代码的“通用性”,我们介绍一个新函数len()。len()函数能返回一个列表元素的个数或者返回一个字符串的字符数。

我们学了len(),再来使用while循环去分类奇数和偶数也会非常方便。

要分出列表numbers中的奇数、偶数,需要准备两个空列表来装这些数,分别命名为even和odd。

然后进入while循环,判断列表numbers现有元素个数是否大于0。

如果是,使用.pop()弹出列表numbers中的最后一个元素并赋值给number,再判断number取模2运算,余数是否为0(因为偶数都能整除2)。如果是,则将number添加进even这个列表中。

如果不是,则将number添加进odd这个列表中。

直到列表numbers中现有元素个数全部取完,成为空列表,不符合条件,循环才结束。

----practice

三、循环执行代码

你在操场上跑步,目标是第五圈,心里默默数着跑到第五圈就不跑了,所以之前一直在数还剩几圈。输出:还剩x圈(从“还剩4圈”开始,到第五圈的时候输出“完成”)。

lession15

我们知道列表/list是一个可变的线性数据结构,例如淘宝的购物车就可以用列表来存储,里面的商品是有可能被我修改的。但有时候我们为了避免误修改到列表里面数据(比如日历,日历显然是不可更改的),我们需要一个不可变的线性数据结构,元组tuple。

元组tuple是一个不可变的线性数据结构,为了方便理解,你可以认为它是一个不可变的列表list。tuple的使用如图中代码所示,这里定义了一个tuple,并且打印了tuple里面的全部元素。

对于元组tuple和列表list这样的线性数据结构,还可以截取里面的一部分数据来使用,这就是切片。截取的方式是使用索引下标。我们既可以同时使用起点和终点的索引,也可以只使用起点或者终点的索引,如果你“空出”了尾部数字,尾部默认为列表的尾部;如果你“空出”了头部数字,头部默认为列表的头部。

这四行代码做的事情是定义了一个叫做“SomeNumber”的tuple(中文名我们又叫元组),然后第一次打印了SomeNumber里面第2和第3个元素,第二次打印了SomeNumber里面第2到第5共四个元素,第三次打印了第1到第3共三个元素。

具体的数据起始位置和终止位置,但数据切片截取遵从“左闭右开”原则,即包括了左边的数字(位置),但不包括右边的数字(位置)。 0表示元组中的第一个数据元素,空值表示到头(第一个)或者到尾(最后一个)。

\我们再强调一下元组tuple和列表list的区别,程序员也是人,所以一定会犯错,因此像元组这样不可变的数据结构可以有效防止写代码的人因为自己的错误,误修改了里面的数据。比如图中的代码展示了一个“一线城市”元组,这里面的数据是不允许被修改的,这时候我们就使用元组。

字典dict

字典又叫dict,是一种python内置的数据结构,访问字典的元素需要通过一个叫做关键字(key)的方式来访问。

隐喻

字典目录里面某个单词对应的字典正文里面的详细讲解,如单词abandon对应的详细讲解。

如果我们想存储一个城市和它对应的邮编,这样的数据存在一个一的对应关系中,用list和tuple都不是特别好处理,我就可以用到另外一种python内置的数据结构,字典dict。

字典dict的存储方式是一种key-value的存储方式,也就是说,dict中的数据都是以一对一的方式存储的。冒号前的数据叫做key,冒号后的数据叫做value,它们一一对应,当我们想要访问dict中的数据时我们需要使用它的key来作为索引。

隐喻

图书馆一本书的编号对应的书架上的具体位置。

字典dict中的key值可以是任意数据类型,但这个key(键)值是唯一的,在定义字典的时候如果给同一个key进行重复赋值的话,后面的赋值会覆盖前面一次的赋值。比如图中代码我们给b赋值了两次,后一次就覆盖了前一次的值。

在一个字典定义完成以后,我们还可以给dict增加元素,图中代码我们给字典添加了一个key-value值,key是“Height”,value是178。

当我们使用keys()的时候,它会返回一个list。这时候我们结合for循环,list,dict,可以打印出这个字典的所有value。图中第二行代码获取了字典PersonDictKeys里面的所有key,第三行代码开启了一个for循环,遍历了所有key,并在第四行用key作为索引访问了所有value。

截止目前我们已经学了三种python内置的数据结构了,它们分别是列表list,元组tuple,字典dict。它们之间最明显的不同就是代码书写格式的不同。

图中代码分别定义了三种数据结构,并展示了如何访问这三种数据结构中的元素。因为列表list和元组tuple是线性的数据结构,我们可以直接在索引中使用连续增长的下标(数字)来访问数据;而字典dict是一个“一对一指向”的数据结构,所以我们需要用key值作为索引来访问里面的元素。

它们之间深度的不同包括了数据的排列方式,可变/不可变等,这源于它们在内存中的存储方式是不同的,线性的数据结构中,数据是连续存储在内存中的,但key-value是一种指引的关系,key中直接存放的不是value的值,而是value所在的内存地址,通过这个内存地址能找到value的值。

这里我们说的内存区域,在计算机中是用内存地址来表示的,通常我们用十六进制来表示这个内存地址(以0x开头),具体的工作原理涉及到计算机硬件,作为软件开发者不需要关注那么底层,但是你需要有这样一个概念:程序运行时候涉及到的数据结构我们会存在内存中,程序通过“内存地址”去内存中找这些数据。

三、最高分是谁?

班级考试成绩如下:Result = {'Tony':69, 'Lihua':64, 'Rain':93, 'Jack':61, 'Xiuxiu':82, 'Peiqi':67, 'Black':77}

输出全班最高分分数。

函数

function

定义

函数,又叫方法,是指某一段聚合在一起做特定事情的代码。

隐喻

函数就像炒菜,把一堆原材料通过一定的烹饪方式产出一道菜。

我们可以感觉到函数有几个特点:

1,特定的功能——每个函数都有某个特定功能。 2,有输入——我们在使用函数的时候需要在函数的括号里面填入一些数据。 3,有输出——使用函数后会返回一些数据,或者做特定的事情。

刚才使用了一个叫做PrintThreeTimes()的函数,但我们还没有定义这个函数,接下来需要定义这个函数,也就是实现这个函数的具体功能。图中代码就是一个函数的定义,关键字def是英文定义define的缩写。

我们需要函数名和函数参数来调用这个函数。比如图中函数名是PrintPlus,函数参数是content,函数的参数可以是常量,也可以是变量,重点是需要有数据。

对于函数参数,涉及到一个转换,就是当我们调用一个函数时,传入的数据(变量或常量)会转换为函数定义中使用的数据。比如第6行我们使用字符串“This is Beijing”作为参数,和我们第8行使用变量contentOne作为参数,最后在函数中都转换成了content。

前面的PrintPlus()函数只有一个参数,我们在函数定义的时候可以定义多个参数。调用函数的时候需要按照定义的参数个数来调用,这里我们使用了两个参数,函数把每个参数打印了三次。\

内置函数:int()函数用于把一个字符串或者数字转换为整型。 int(x, base=10) 函数参数:x是字符串或者数字,base是一个默认参数,代表是进制,默认为十进制。 函数返回值:整型。

在函数定义的时候写在代码里的参数,是“必选参数”,也就是说这些参数是你在调用这个函数的时候必须要传入的,如果不传入这些“指定参数”程序就无法正常运行。

概念卡

No.055

默认参数

Default paramete

函数定义中的一种参数类型,在函数调用的时候不使用参数的话,就会使用默认值。

必选参数也是相对不够灵活,如果我们想更灵活地使用函数,例如函数定义时有两个参数,但函数调用时只传入一个参数或者不传入参数,此时这个函数也能正常工作。这时候可以使用“默认参数”。

默认参数是我们在调用函数时,没有传入参数,它会使用自己默认值的一种机制.

有时候我们需要给一个函数传入多个参数,但是具体参数数目我们也不确定,需要根据具体情况来灵活处理,这时候我们可以使用“可变参数”/“不定长参数”。如同我们想要写一个计算所有数字的累加和的函数,我们可能传入3个数,也可能传入6个数。

一个星号*,表明这个参数是一个可以接受任意多个数值传入的参数。

一串字母numbers,这个参数和前面的星号结合在一起,表明了这个参数可以接受多个数值传入。

概念卡

No.056

可变参数

variable parameter

定义

可变参数,又叫不定长参数,是函数定义中的一种参数类型,当一个函数可能会处理的参数数目未知的时候,我们可以使用可变参数。

在定义函数时,还可以同时使用这三种参数,这时函数参数的顺序是:1,必选参数;2,默认参数;3,可变参数。

当有必选参数和默认参数的时候,必选参数必须写在默认参数的前面,同理,如果有默认参数和可变参数的时候,默认参数也必须写在可变参数前面。

概念卡

No.059

变量作用域

Variable scope

定义

一个变量有自己生效的区域,它决定了你在什么地方能访问或修改这个变量,局部变量和全局变量就是描述变量作用域的。

局部变量,全局变量和变量作用域是Python编程语言的一种机制(很多其他编程语言也有类似的机制),Python会根据你的代码来判断什么时候“销毁”这个变量,销毁以后这个变量就无法被访问,无法被赋值,无法被使用。

因为这个变量已经不存匿名函数之所以叫匿名函数,是因为它没有函数名,代码中我们是把一个匿名函数赋值给了变量square,square不是这个函数的函数名,它是一个指向了这个匿名函数的变量。在了。

概念卡

No.061

匿名函数

Anonymous function

定义

匿名函数是Python中以lambda关键字开头的,不需要函数命名和函数参数的计算形式。

一个函数如果调用了自己,我们就叫它递归函数,比如我们要算一个数的阶乘 5!=5*4*3*2*1,我们可以用图中的代码,当n大于1的时候,函数会调用它本身,直到n<=1。

递归这个概念比较抽象,但也比较重要,所以这里需要你思考一下这段代码。我们可以使用最笨的办法,一次一次去思考代码的执行顺序,第一次执行是在第6行调用了factorial(),这个时候n=3,函数定义中的判断条件不成立,进入第4行代码,再次调用factorial(),这次调用传入的参数是2。以此类推,直到n = 1才返回。

函数的最后,我们来学习一下函数中的代码执行顺序。函数的代码执行顺序不是三大顺序(顺序,条件,循环)之一,但是它仍然很重要,我们把调用函数的代码执行顺序称为“跳转”。

当代码执行到函数调用的时候,代码的执行就进入了函数定义,函数体执行完毕之后,代码返回到进入函数调用之前的地方。如图中箭头所示。

1,代码执行到函数调用

2,进入函数定义

3,执行函数定义

4,返回到进入函数调用的地方。

概念卡

No.062

Class

定义

类是程序用来进行数据封装的方式,一般来说一个类会包含一些变量和一些函数,它可以用来抽象的表现真实世界里面的某一类事物,如城市,汽车等等。

隐喻

类就像鸟类一样,可能有很多不同种类的鸟,以及不同个体的鸟,它们合起来是一个“类”。

同时这个类还包含了4个函数,他们分别是__init__(),display_name(),display_height(),display_weight(),这些函数又叫这个类的“成员函数”或“方法”。

概念卡

No.065

方法

method

定义

方法又叫类方法,成员函数等,是类里面的函数,用来表现这个类的一些对外互动的行为。

隐喻

方法就像鸟会飞一样,是某个事物能做的事情,拥有的功能。

一个类由属性(成员变量)和方法(成员函数)构成, 类里面的属性都有一个self.的前缀,这是用来标识这个变量是这个类的属性的机制。

代码的作用

这里我们定义了一个“模板”Person,在计算机里面我们叫它类,这个Person包含了一个变量,self.name和两个函数,__init__(),print_name()。第一行是定义这个“模板”,第二行是定义这个模板里面的第一个函数__init__(),第三行是给这个模板里面的变量self.name赋值,第五行是定义了这个模板里面的第二个函数print_name(),第六行是打印了某个变量。

例子:

No.063

对象

Object

定义

对象是以某个类为模板,有具体数据的数据类型,对象中的变量和函数是可以被访问的。

隐喻:一个具体的人,有自己的名字,身高,体重,年龄,职业等信息。

以类为模板创造对象的过程叫做实例化,图中代码的第16行和第18行就是两行以Person类为模板实例化两个对象personA,personB的代码。

对象在调用自己的方法的时候一定要有“.”这个符号,句点这个符号是不是会让你回想起之前课程讲过的一些代码?比如一个列表/list,在末尾添加一个元素的时候会调用append(),中间就有个点,是的,list就是一个类,我们创建一个list的时候就是创建了一个list对象。

由于列表/list是一个python内置的数据结构,所以它的实例化和我们定义的类的实例化有些不一致,但是完成实例化以后,它们本质上都是对象了,所以调用一个方法的时候也是一样的代码书写格式。

类似的还有字典dict,我们看看dict自带的一个方法:clear()。

这个方法的功能是清除字典内的所有元素。

总结一下关于类和对象, 类是一类事物的抽象/模板;对象是按照某个类实例化出来的具体事物;类具有属性(成员变量)和方法(成员函数),对象能够给属性进行具体的赋值以及调用具体的方法;类是人类,对象是你我他;类是列表/list,对象是NumerberList = [1, 2, 3, 4, 5]。

__init__()这个函数又叫构造函数或初始化函数,在用某个类初始化一个对象的时候,会默认调用它,这意味着它是第一个被调用以及一定会被调用的方法。init是英文initialize(初始化)的缩写,由于它给属性进行了赋值,也就意味着赋予了一个对象“生命”(具体的数据)。

我们可以通过两个层次来理解类“内部”和类“外部”,直观层次的理解就是代码中class的”内部“和“外部”,写在类里面(缩进里)的就是“内部”,写在类外面(缩进外)的就是“外部”;在“内部”调用类成员和类属性的时候,需要使用self加上.作为前缀来调用,在“外部”则是使用对象名PersonA加上.作为前缀来调用。

抽象层次的理解可以通过一个叫做封装的特性。类“内部”需要关注具体功能的实现,如图中代码我们用一个类来模拟一个长方形,这个类的属性就是长和宽;这个类提供的功能是计算和展示这个长方形的周长和面积,我们需要在一个类“内部”实现具体的功能。

当我们在类“外部”使用这些功能的时候,我们就不需要关注具体的代码实现细节了,比如周长是如何计算的,面积是如何计算的。我们只需要知道,这个类的某个方法能帮我们计算周长,某个方法能帮我们计算面积,然后调用它们就好了。

封装

Package

定义

把内部具体的数据和对数据的运算和操作屏蔽起来,只对外展示操作接口,让外部调用者只关心输入输出的编程思想。

隐喻

封装就像售票亭窗口,你不需要知道售票的具体步骤,和火车的调度等,你只需要找售票员,它就能给你你想要的票送你去你想去的地方。

面向对象编程有三大特性,封装是其中的第一个,面向对象编程思想是一种用程序模拟现实世界的思想,就像你去食堂打饭,你并不关心这个饭菜是如何采购,如何烹饪的,你只需要到窗口选你想要的菜然后支付就好了;你去窗口买动车票也是一样,你不需要关心动车是如何生产,运行,调度的,你只需要付钱购买你想要的动车票就好。

面向对象编程

Object-Oriented Programming

定义

基于类和对象机制的编程思想,通过这套机制去对现实世界中的事物进行抽象和归纳,来进行建模模拟的一种编程思想。

隐喻

面向对象编程是一种思想,它是在编程世界中对现实世界的模拟和抽象。

列表list,字典dict也是面向对象的实际案例,我们再来看看作为类和对象,他们还提供了哪些方法。

除了列表list和字典dict,其实我们在python中使用的字符串也是类和对象,代码如下,lower()的功能是把一个字符串的大写变小写。

对于list,dict,string这些python的内置类,我们只需要了解它们提供的方法能实现什么样的功能,而不需要关注它们的具体实现细节,这就是“封装”编程思想的一个体现。

面向对象编程一共有三大特性,昨天我们学习了第一个特性——封装,今天我们来学习剩下两个特性“继承”和“多态”。

之前学写了类Person,这个类知道广义的人类,因为人都有名字,身高,体重。用这个类我们可以创建具体的对象如tony和kevin。

继承让我们不用这么辛苦重复写这么多代码,我们在定义类ChinesePerson的时候传入了类Person作为参数,这表明了我们要继承类Person的属性和方法

继承

inherit

定义

继承是面向对象编程中的三大核心概念之一,它让一个类可以具有另一个类的一些属性(成员变量)和方法(成员函数)。

隐喻

继承就像汽车这个大概念和某品牌汽车这个小概念之间的关系,某品牌汽车即继承了汽车的特性,又有一些属于自己的独立特性。

()

一个括号,说明这个类会以其他的某个类作为基础。

父类

parentclass

定义

父类又称基类或超类,是面向对象编程的继承中被继承的那个类。

隐喻

父类就像汽车和某品牌汽车中的汽车,他是继承关系里面更“大”的那个概念。

子类

childclass

定义

子类又称派生类,是面向对象编程中继承了其他类的那个类。

隐喻

子类就像父类就像汽车和某品牌汽车中的某品牌汽车,它是继承关系中更“小”的那个概念。

多态

Polymorphism

定义

多态是面向对象编程中的三大核心概念之一,它让不同类的同一个方法能有不同的功能。 它让不同类的同一个方法能有不同的功能。

面向对象编程的最后一个特性是多态,比如图中代码就是多态的一种表现,类Mac和类Alienware都有方法computer_type(),这个方法虽然名字一样,但是实现的功能是不一样的。这种现象就叫做多态

还有一种机制也属于多态,比如左边的代码里面,两个类都展示了一部分车的信息car_brand()和car_type(),我们可以像右边的代码中那样,用一个方法car_information()来完整的展示车的信息,然后在子类中去丰富和修改这个方法的功能。

方法重写

Method rewriting

方法重写又称方法覆盖,是面向对象编程中的一种机制,子类在继承父类的时候可以对父类的方法(成员函数)进行修改

这种在子类中重写了父类里面同名方法的做法又叫方法重写,也是多态机制中的一种。

所以多态主要包含两种机制,第一种是同一个父类的两个子类有同名的方法,但功能不一样;第二种就是同一个方法,在父类和子类中的功能是不一样的。

函数和类有两个共性,第一个共性就是封装,函数和类都是封装了一些可能会重复使用的代码,让程序员不用反复写一样的代定目码。只需要通过调用它们就能实现特的。

对于类,比如我想定义一个表示人的信息的类Person,当我以后再次遇到这样的需求的时候,我就可以直接用这个类来创建对象,而不需要反复写类似的代码。

所以函数和类都体现了封装的特性,就是你不需要知道他们内部的具体代码实现,你只需要关心如何使用它们就好了,也就是说只需要关心它们的输入和输出就可以了。

第二个共性是代码执行顺序上面的“跳转”,“跳转”顺序不属于代码执行的三大顺序,但是在调用函数,调用一个对象方法,或者创建一个对象的时候,代码的执行顺序会发生一些变化。

比如图中代码,我们在第4行的时候调用了函数area(),这个时候代码执行顺序就进入了函数内部,“跳转”到了第1行;并且在第2行代码的时候,代码执行顺序再次“跳转”回了第4行代码。

我们在使用对象方法的时候也是类似的“跳转”流程,第17行代码调用对象PersonA的方法display_name()的时候代码执行“跳转”到了第7行,并在函数执行完毕以后跳转回17行。

同样的,在创建一个对象的时候,实际上我们是“隐性”调用了类的初始化函数__init__(),在16行创建对象的时候,代码执行“跳转”到了第二行的__init__()函数,并在函数执行完毕以后“跳转”回16行。

在执行到函数和类/对象的时候,代码的执行顺序都发生了变化,他们从默认的顺序执行变成了跳转进入函数或者类/对象的内部,并在执行完内部代码之后,再跳出到原来的代码执行地点。

(0)

相关推荐