笔者在自学 Python 一段时间以后,通过一些自我总结写出来的自学笔记,未完结,应该也不会完结了。
1. 发展历史
1.1 什么是python
Python是一种计算机程序语言,是一门面向对象的动态类型语言。
程序语言分面向过程和面向对象,分静态类型和动态类型,分解释性和编译性。
这些是什么意思,不用管,后面会遇到。
1.2 python是怎么来的
Python的创始人为荷兰人Guido van Rossum。
1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序。
之所以选中Python(大蟒蛇的意思)作为该编程语言的名字,是取自英国20世纪70年代首播的电视喜剧《蒙提·派森的飞行马戏团》(Monty Python’s Flying Circus)。
1.3 下载和使用python
略。
2. 编程初识
2.1 仪式感
第一个python程序:
print("Hello World!")
2.2 变量
2.2.1 什么是变量
变量是一种标识符。
也可以说,变量是一个门牌号,是我们表示数据的方式,也是找到数据的方式。
2.2.2 如何创建变量
name = "FMY"
age = 20
2.2.3 变量名命名规范
Of course 你想给它起什么名就起什么名,比如:
a = "julian"
b = 3
哪怕这样写 wodeshengao = “216cm” 也没人会管你
但是!
为了以后还能看懂自己写的代码,建议遵循相关规范。
相关规范如下:
变量名只能包含字母、数字和下划线(_)
变量名不能以数字开头
变量名要有意义,能解释所存数据的含义
对于有多个单词的变量名,单词全部小写,中间用下划线隔开
2.3 注释
此外,同样为了程序员们以后能看懂自己的代码,以及为了解释某段代码是干什么的,或者需要注意什么,每种编程语言都有自己的注释方式。
# 在python中这样单行注释
'''也可以这样
多行注释'''
"""当然双引号
也可以"""
2.4 基本数据类型
2.4.1 有哪些基本数据类型
既然变量可以存数据了,那么它到底可以存什么样的数据呢?数据又分哪几种呢?
基本数据类型分为:
整数类型、浮点数类型
字符串类型
布尔类型
None
- 整数类型(int)有 -1,0,1,10000等;
- 浮点数类型(float)有 -1.0,0.0,1.0,3.1415926等;
- 字符串类型(str)有 “about”,”x”,”你真好看” 等;
(字符串类型可以用单引号,也可以用双引号,但必须对应) - 布尔类型(bool)只有两个 True和False,注意首字母大写;
- 空类型只有 None,表示啥也没有。
注意: “1” 和 1 不是相同的数据类型,他们分别是什么?
2.4.2 动态语言和静态语言
两者的区别简单来说就是 在声明变量时需不需要声明数据类型。
很明显,python不需要声明数据类型。
直到代码被解释前,python都不知道这个变量到底是什么类型。
但其他的语言就不一定了。比如Java。
int age = 20;
float pi = 3.1415f;
同时Java是一门编译型语言,即必须把一个文件的所有代码都写完后,统一编译成计算机理解的二进制语言,然后执行。
Python则可以边解释边执行,即你写一句,我解释/执行一句。
2.4.3 数据的存储方式/字符编码
为什么”1”和1会不同呢?1和1.0又有什么区别?
根本原因是数据在内存/硬盘中的存储方式不同。
电脑只能识别二进制,因此在电脑中存储的所有数据都会最终转换为二进制。
而不同的数据类型在电脑中的二进制形式是不同的。
至于怎么不同呢,这就涉及到字符编码了。
最开始的时候计算机是美国发明的,所以用的语言也肯定是英语。
而英语呢,字符比较简单,只有二十六个英文字母,算上大小写,以及数字和其他特殊字符,用八位二进制(一个字节)完全够了。
即0000 0000 ~ 1111 1111,一共可以表示256个符号。
这种编码方式叫ASCII码,即美国信息交换标准代码。
但是,后来,计算机逐渐普及,其他国家也要用计算机,他们也想在电脑上显示和存储他们的语言,怎么办呢?
于是各个国家就开始以ASCII码为基准,开发自己的编码系统。
比如中国,最开始是GB2312,即国标码,除了ASCII码中原本的符号,又加入了中国的汉字。
然后,国标码又扩展了,加入了更多汉字,叫GBK。
但是这个样子,国与国之间太独立,一个国家的计算机不能存储其他国家的语言,不利于全球化,于是一种新的编码方式出现了,叫Unicode。
Unicode涵盖了几乎全球所有的语言符号,统一用两个字节(十六位)表示所有符号。
但是美国不乐意了,因为原本保存一个“Hello World”用ASCII编码只需要11个字节的空间就够了,结果现在用Unicode需要22个,白白浪费了很多空间。
于是,UTF-8诞生了,它是一种可变长度的编码方式,它规定原ASCII码还是用一个字节表示,然后汉字用三个字节表示,至于其他符号,不重要,暂不赘述。
所以是不是还是没明白1和1.0有什么区别?
其实我也不懂
咳咳,总之,知道它们的存储方式不同就好了。
此外,还要熟悉字符串类型的常用方法及字符串的格式化,这个等讲完其它数据类型后再讲
2.5 用户交互
Python是一门十分适合做大数据分析的语言,主要领域还有人工智能,科学计算等,所以它十分适合处理数据。
因此要处理数据,就要先获取数据,下面是一种十分简单的获取数据的方式——键盘录入:
name = input("请输入你的名字:")
input
关键字用于从键盘获取数据,引号内的内容为提示文字,用于提示用户此处该输入什么内容,然后把用户输入的内容用等号赋值给name
变量。
注意:用
input
获取的所有数据均为字符串类型!
2.6 流程控制
流程结构一共有三种:顺序,分支,循环。
顺序最好理解,之前见的所有代码都是顺序结构,即从上往下的顺序执行。
2.6.1 分支结构
接下来,我们来实现一个简单且智障的功能。
我们询问用户的性别,如果用户的反馈是“男”,则输出“你是男的”,否则输出“你是女的”,不可能都不是吧。
如何实现这个功能呢?
其实分三步就好了:
让用户从键盘录入信息,同时计算机获取到信息
计算机判断信息
输出结果
第一步让计算机获取信息,我们用input
关键字,第三步输出结果,我们用print
关键字,那第二步呢?
这就用到分支结构了。
因为这是一个选择/判断,不同的选择会导致不同的结果,我们用if
和else
关键字。
代码如下:
sex = input("请输入你的性别:")
if sex == "男":
print("你是男的")
else:
print("你是女的")
因此,分支结构的模板如下:
if 条件表达式为真:
语句块1
else:
语句块2
此处需注意三点:
- 不管条件表达式多长,它最终永远是一个布尔值,即非True即False,如果是True,执行语句块1,否则执行语句块2
- 条件表达式后面和
else
后面有一个(英文的)冒号,不能漏不能漏不能漏!- 冒号后边有缩进,默认一个Tab键或四个空格,python通过缩进来划分结构。
还需要注意一点,在几乎所有编程语言中,等号都是用于赋值,而双等号(==)才是数学含义的等于,用于判断左右是否相等。
其实进行到这了,你大概发现了一个问题,如果没发现说明你不太行,上边这个功能果然很智障。
因为只要用户不输入“男”,python总会反馈一个“你是女的”,比如我输入“天空”,“草地”,“炸鸡腿堡”,python都会义无反顾地给你反馈一个“你是女的”。
其实啊,这不是python的问题,这是你的。
咳咳,其实上边这个if
else
叫做双分支结构,如果我们想要实现不止两个分支呢?
我们改进一下上边这个功能,我们想让用户输入“男”时,反馈一个“你是男的”,当用户输入“女”时,反馈“你是女的”,而如果用户乱输其它内容的话,我们给他个“我不知道你在说什么”。
聪明的你或许发现了,这个需要三个分支。代码如下:
sex = input("请输入你的性别:")
if sex == "男":
print("你是男的")
elif sex == "女":
print("你是女的")
else:
print("我不知道你在说什么")
这叫做多分支结构。
其实变化就只有一点,加了一个elif
,同时要注意,它后面也是跟一个条件表达式,表达式后面也有一个冒号,它下面的语句块也需要缩进。
所以总结一下,分支流程就是,if
和elif
把所有可能的情况都列出来然后处理,如果都不是这些情况,则交给else
处理。
作业:登录匹配;猜数字。
猜数字时你会遇到的问题:
- 遇到
TypeError
对于这个问题,想想是怎么产生的,有什么解决办法?
2.6.2 循环结构
此时让我们再来实现一个智障的功能。
如果我们想要在屏幕上输出0到9这十个数字,以我们之前所学的知识,该怎么做呢?
聪明如你,想到这样做:
print(0)
print(1)
print(2)
print(3)
print(4)
print(5)
print(6)
print(7)
print(8)
print(9)
此时如果计算机有眼睛,它会给你翻个白眼,如果它有jio,它还会给你一jio。
这样做的坏处显而易见,代码的重复性太高,而且不好看。而且如果是输出100个数呢,一万个数呢?
这样肯定是不行的,那怎么改进呢?这就用到我们接下来讲的循环结构了。
代码如下:
i = 0
while i < 10:
print(i)
i += 1
怎么样?是不是很简洁?简洁不代表你能看懂
咳,看不懂没关系,讲嘛。
这个叫while循环。模板如下:
while 条件表达式为真:
语句块
注意点:
while
表示循环的开始,后面接一个条件表达式,然后后边再加一个冒号,不能忘不能忘不能忘!- 需要循环的语句块要缩进。
i+=1
的意思是i=i+1
,即把i
增加1,然后赋值给i
,即自增1- while循环一定要有终止条件,否则会陷入死循环。尝试如果没有
i+=1
会怎样。
练习:改写猜数字,限制猜的次数。比如10次。
练习中你会遇到的问题:
- 怎么进入循环?条件表达式要怎么写?
- 如果我没到10次就猜对了,这个时候还需不需要继续猜了呢?
- 如果不需要了,怎么退出循环呢?
对于最后一个问题,要解决的话需要一个新的关键字,叫break
。代码如下:
my_age = 19
while True:
age = int(input("age:"))
if my_age == age:
print("You got it!")
break
elif my_age > age:
print("Older!")
else:
print("Younger!")
除了break
,还有一个continue
关键字。它俩的区别如下:
break
直接结束整个循环
continue
只结束当前循环
观察如下代码:
i = 0
while i < 10:
if i % 2:
continue
elif i == 6:
break
else:
print(i)
观察输出结果,理解break
和continue
的区别。
除了while
循环,还有一种更简单的方式可以实现最开始那个智障的功能:
for i in range(10):
print(i)
是不是更简洁了?也更难懂了
难懂没关系,解释嘛。
这个循环叫for循环,模板如下:
for 变量名 in 可迭代对象:
语句块
此处注意:
- 变量名就是一个普通的变量,起名时符合命名规范,同时尽量有一定意义。
- 可迭代对象可以理解为一个有限序列,这个序列中的值是可以从头数到尾的。比如此处的
range
就是一个整数序列。range
序列默认从0开始,range(10)
表示从0数到9,同理,range(99)
表示从0数到98。- 可迭代对象后面依然有个
:
,不能忘不能忘不能忘!- 需要循环的语句块缩进。
其实此处的变量名就是对可迭代对象中的每个值的统一的一个称呼,变量会依次被每个值赋值,这个过程叫做遍历。
尝试用
for
循环改写拥有限制次数的猜数字游戏。
此时聪明的你可能有发现了,这个地方的变量根本没用上!其实不是没用上,是你没看见
咳咳,那我就是想看见怎么办呢?
Hmm,不,你不想。
注意:
break
和continue
对for
循环同样适用
3. 引用数据类型
其实引用数据类型是Java的叫法,在Python里不这么叫,Python里叫引用传递,同样不好懂。
咳,这不重要。
有些时候我们不只是单独的对一个数据进行操作,比如我想记录下全班同学的成绩,根据之前所学的我只能这样做:
grade1 = 97
grade2 = 76
grade3 = 78
grade4 = 89
grade5 = 83
所以你看,不仅代码量很大,变量名也不好写,写代码时尽量不要写这种变量名。
当我们想存储一堆数据时,Python提供了三种数据结构让我们使用,分别是
序列(列表,元组)
映射(字典)
集合(集合)
3.1 列表
在这四种数据类型中,列表是最常用的。
Python中列表用一对中括号表示,即[]
,列表内可存储任意类型和任意数量的元素,元素可重复。
ls1 = [1, 2, 4, 5, 8, 8]
ls2 = ['a', 45, True, 0.23, "Hello"]
ls3 = [] # 这是一个空列表
列表的索引:
names = [“FMY”, “FZH”, “XD”, “LYX”]
写法 | 描述 |
---|---|
names[0] | 输出列表第一个值(下标为0) |
names[1:3] | 切片;输出列表第二到第三个值,即输出下标为1和2的值,不输出下标为3的值 |
names[-1] | 输出列表最后一个值;列表下标从左往右为0,1,2…从右往左为-1,-2,-3… |
names[-2:] | 输出列表倒数两个值 |
names[:2] | 输出列表前两个值 |
注意正负索引一起用的情况,同时时刻牢记左闭右开
列表的常用方法:
方法 | 描述 |
---|---|
append(e) | 在列表尾部追加一个元素e |
count(e) | 返回列表内元素e的数量 |
index(e) | 返回列表内元素e第一次出现的下标 |
insert(i,e) | 在下标为i的位置插入一个元素e |
pop(i) | 删除下标i的元素并返回,默认是最后一个 |
remove(e) | 删除列表中的元素e |
reverse() | 反转列表 |
sort() | 列表排序,默认升序 |
然后你发现,哇,怎么这么多啊,这咋记啊,呵呵,后面的还多着呢
这个不需要死记硬背,因为用到的次数多了,自然就记住了。
列表的遍历:
names = ["FMY", "FZH", "XD", "LYX"]
for name in names:
print(name)
3.2 元组
在Python中元组用一对圆括号表示,即()
,但下面几点需要注意:
ls = ["Hello"] # 这是一个列表
t1 = ("Hello") # 但这不是一个元组,这本质上还是个字符串
t2 = ("Hello",) # 这才是一个元组
t3 = 1, 3, 5, 6 # 这也是一个元组
t4 = ('a', 45, True, 0.23, "Hello")
t5 = () # 这是一个空元组
元组也可以存储任意类型和任意数量的元素,且元素可重复。
但元组是一个不可变对象(所有基本数据类型都是不可变对象,特别注意字符串类型),即元组一旦创建便不可改。
因此它只有两个方法:
方法 | 描述 |
---|---|
count(e) | 返回元组内元素e的数量 |
index(e) | 返回元组内元素e第一次出现的下标 |
元组的遍历:
names = ("FMY", "FZH", "XD", "LYX")
for name in names:
print(name)
3.3 字典
字典内存储的是键值对,即key-value对,就像查字典一样,根据键找到值,根据key找到value。
Python中字典用一对花括号表示,即{}
,且内部的键值对是无序的(列表和元组内的元素都是有序的,因此可以使用索引)。
字典内的键是唯一的,不可重复,但值可以重复。
d1 = {} # 这是一个空字典
d2 = {"50901":"FMY", "50902":"XD", "50903":"FZH", "50904":"LYX"}
需要注意的是,字典内的键必须是不可变对象,但值并没有此限制。
字典的索引:
info = {"50901":"FMY", "50902":"XD", "50903":"FZH", "50904":"LYX"}
print(info) # 输出字典信息;无序;冒号前为key,后为对应信息
print(info["50901"]) # 按key查找对应信息并输出,若不存在则报错
info["50903"] = "fzh" # 原字典中存在该key,则修改其信息
info["51001"] = "MLY" # 原字典中不存在该key,则添加其信息
print("51002" in info) # 判断该key是否存在于该字典,存在输出True,不存在输出False
del info["50904"] # 删除字典中对应信息
复杂吗?我说吧,复杂的还在后面呢
字典的常用方法:
方法 | 描述 |
---|---|
get(key) | 按key查找对应的value并输出,若不存在则输出None |
pop(key) | 删除字典中key对应的键值对 |
keys() | 返回一个包含所有key的可迭代对象 |
values() | 返回一个包含所有value的可迭代对象 |
items() | 返回一个包含所有(key, value)的可迭代对象 |
setdefault(key,value) | 添加键值对key:value |
字典的遍历:
info = {"50901":"FMY", "50902":"XD", "50903":"FZH", "50904":"LYX"}
for i in info:
print(i, info[i]) # 字典循环;较高效
for k, v in info.items():
print(k, v) # 需要将字典先转换为dict_items类型,较低效
这个需要多解释解释……
3.4 集合
最后一个类型叫集合,跟高中学的那个集合几乎一毛一样,但用的挺少。
Python中创建集合的方式如下:
s1 = set() # 这是一个空集合
s2 = {1, 2, 4, 5, 6, 7} # 集合也可以用一对花括号表示,但里边是单个值而非键值对
s3 = {} # 不可以这样创建集合,因为这样是创建了一个字典
s4 = set(['a', 45, True, 0.23, "Hello"]) # 你也可以这样创建集合,即把列表强制转换为集合
注意:
集合内的元素是无序且唯一的,因此集合不可遍历和索引
集合是一个可变对象
因为集合不常用,所以就不介绍方法了,如有用到可以用help(set)
自行查找。
3.5 说明
所以说到这了,为什么这些类型叫引用数据类型或者引用传递呢?他们跟基本数据类型有什么区别?
其实就是,引用数据类型就像个容器,内部存储着一堆数据,但这只是外观上看,实际上这些容器存储的是这些数据的内存地址,而数据们本身到底在哪,就看计算机怎么给它们安排了。
所以实际上,这些引用数据类型存储的是对那堆数据的引用,或者数据把引用传递到了容器里。
越解释越难懂,那就不要管了,这真的不重要
4. 字符串
4.1 字符串的相关方法
观察如下代码,理解字符串的相关方法:
name = “my name is fmy”
方法 | 描述 |
---|---|
name.capitalize() | 强制将字符串转换为首字母大写其它小写的形式 |
name.count(“m”) | 统计字符串中“m”的数量 |
name.center(50,”-“) | 输出50个字符,将赋值信息放在中间,其余用“-”补上 |
name.ljust(50,”-“) | 输出50个字符,将赋值信息放在前面,后面用“-”补上 |
name.rjust(50,”-“) | 输出50个字符,将赋值信息放在后面,前面用“-”补上 |
name.endswith(“my”) | 判断赋值信息是否以“my”结尾 |
name.find(“n”) | 输出“n”位置的下标(此时为3);此方法可用于字符串切片,用法与列表切片相同 |
方法 | 描述 |
---|---|
“ab123”.isalnum() | 判断信息中是否只有英文和数字;全英、全数、英加数皆为True |
“abc”.isalpha() | 判断信息中是否只含英文 |
“123”.isdecimal() | 判断信息是否是十进制数 |
“name”.isidentifier() | 判断信息是否为合法的变量名 |
“abC”.islower() | 判断信息中的英文是否全为小写(可以含其他字符) |
“abC”.isupper() | 判断信息中的英文是否全为大写(可以含其他字符) |
”,”.join([“a”,”b”,”3”,”4”]) | 将列表转换为字符串;“,”为不同值的分隔方法,可换为“+”等 |
“1+2+3+4”.split(“+”) | 将字符串转换为列表;默认按空格分隔,若特殊注明,则按注明方式分隔 |
” \nmy name is fmy\n “.strip() | 去除信息中开头和结尾的空格和换行;“\n”即换行 |
4.2 字符串的格式化
因为Python底层代码是用C语言实现的,所以在字符串格式化上也保留了C的特点,即用%
。
例如:
name = "FMY"
age = 20
info = "My name is %s. I'm %d now." % (name, age)
print(info)
其中%s
和%d
是一种占位符,表示在字符串中,此位空出,后面待补充。%s
占的地方必须引用字符串,%d
则必须引用整数。
但是这个亚子一点也不Pythonic,Python有自己的格式化方法,即用{}
作占位符。
上面的代码可以修改为:
name = "FMY"
age = 20
info = "My name is {0}. I'm {1} now.".format(name, age)
print(info)
其中,0代表format
里的第一个元素,1代表第二个,以此类推。
当然也可以这样写:
name = "FMY"
age = 20
info = "My name is {n}. I'm {a} now.".format(n=name, a=age)
print(info)
此外还有更多关于{}
内的语法,一点也不好记,详情见课本。
5. 函数
5.1 什么是函数/函数的功能
这一部分就是初次学编程语言的人第一个比较难理解的地方了。
或许你会问,函数是什么呢?我们老师当初跟我们说,这个函数跟数学上那个函数并不是一码事。
Hmm,她说得对,的确不是一码事,但在后面,你要不可避免的理解返回值的时候(如果理解函数是什么是第一个难点,那么理解函数的返回值是什么就是第二个难点),把它结合数学上的函数会有点帮助。
不过这些都是后话了,我们还是先来想一个经典的例子吧。
问,如果让你把大象塞进冰箱,需要几步?
也许你现在还不会理解,但不得不说,这真是一个理解计算机问题的超典型的例子。
答案也许你早就知道了,没错,就分三步:
- 把冰箱门打开。
- 把大象塞进去。
- 把冰箱门关上。
根据这个例子,我们来理解函数的第一个功能(为什么不先说什么是函数呢,其实理解了函数干了什么事也就能理解函数是什么了):
假设上面的每一个步骤都是一行代码,三行代码来完成把大象放进冰箱这个任务,那么当我们想把一头大象塞进冰箱时,写出这三行代码就完事了。
但是!老师说不行,你得塞十头。
好了,你有十头大象,你要把它们都塞进冰箱。怎么办呢?
聪明如你,写了三十行,每三行就重复一次,一共十次,塞了十头。
然后第二天你因为左脚进教室被老师逐出了班级名单。
太麻烦了对吧,代码重复性太高了,你写起来费劲(可能不费劲,复制粘贴就好了),别人看起来也费劲。
这就用到函数的第一个功能了——提高代码复用性。函数的定义模板如下:
def 函数名(参数1, 参数2...):
"""注释"""
语句块
return 返回值
需要注意的地方:
def
关键字定义一个函数
函数名可以理解为一个变量名,符合变量名命名规范,能体现函数的功能
函数名后面要跟一对()
,参数可以没有,但括号不能省略,括号后有一个:
注释用于解释这个函数是干嘛的,可以省略
函数下的语句块都要缩进
返回值先不解释,可以省略
所以对于塞十头大象这个问题,我们怎么解决呢?我们可以造一个机器,告诉这个机器,你只需要干三件事,第一件就是把冰箱门打开,第二件把大象塞进去,第三件关上冰箱门。
好了,我们机器造出来了,这个时候只需要给它一台冰箱和十头大象,然后一摁开关,机器就刷刷把十头大象塞进去了,多简单!
这台机器呢,就是函数。
def 塞大象(冰箱, 大象):
把冰箱门打开
把大象塞进去
把冰箱门关上
如果说摁一次开关就可以把一头大象塞进冰箱,那么你需要做的就只是摁十次开关而已,是不是比之前轻松了许多?
这里的摁开关就是调用函数。
到这里,有没有稍微理解了什么是函数了?
那接下来我们看一段代码。
def add(x, y):
z = x + y
print(z)
add(1, 2)
add(343, 123)
add(0, -43)
先思考一下,这段代码干了个什么事?
此处需要说明一下,当读带有函数的代码时应该怎么读。
应当像计算机那样读。
计算机怎么读呢?你已经知道当你执行一段代码时,python会从上往下依次解释每段代码的含义,但是当python遇到函数时,它会直接跳过。因为如果函数没有被调用,那么函数就没有用。
如同你造了一台机器,却没有摁开关,机器是不会自己启动的。
所以只有当函数被调用了(比如此处的add(1, 2)
),python才会跑回去根据函数名找到相应函数,然后解释执行函数内部的代码。在此之前python也不知道函数里是什么。
建议你也这样阅读代码。
你可能觉得上段代码的提高复用性功能表现得不是很明显,那是因为函数里只有两条代码,如果有100条呢。
使用函数可以美化代码,也能帮助其他阅读代码的人快速理清代码的思路。
函数的第二个功能就是使代码模块化。
啥是模块化呢?想象一下一辆车是怎么造出来的,是由一个工厂把所有零件都造出来吗?当然不是,有些工厂造轮子,有些工厂造引擎,有些工厂造真皮坐垫。不同工厂的物件一起组合起来共同造出了一辆车。
回想那个塞大象的例子,我们的解决方案其实用的就是模块化的思想,我们把塞大象这件事分成了三个模块,可以定义三个函数,让它们共同完成这件事。
第一个函数负责打开冰箱,第二个函数负责把大象分尸然后塞进冰箱,第三个函数负责把冰箱关上。
看吧,步骤清晰而明确,写的人好懂,看的人也好懂。
其实面向过程的编程方法就是把一个任务分成多个模块,然后逐一地解决问题的。
比如,要实现一个人进车门的过程,利用面向过程的方法可以是这样:
写一个函数实现人打开车门
写一个函数实现人钻进车里
写一个函数实现人关上车门
写一个主函数调用上面三个函数
而相对的,利用面向对象的方法,可以是这样:
定义一个人,这个人有仙女般的模样,穿着粉红色的衣服,会唱会跳还会开车门,当然也会关车门
定义一辆车,这辆车,是粑粑色的,有四个轮子,能开会跑还会漂移,车门可以被打开,当然也能被关上
把车的车门当作参数传给人,然后人调用开车门的方法
人调用钻进车里的方法
把车的车门当作参数传给人,然后人调用关车门的方法
所以说,面向过程注重的是动作,而面向对象注重的是对象,这里的人和车都是对象。
面向对象在这里不会讲,书上也没讲,如果感兴趣想学,……
呵,你不会的
5.2 函数的返回值
思考一个数学里的函数:
f(x) = 2x
y = f(x)
当我们把一个数传给自变量x,便得到y是两倍的x。然后我们怎么用计算机函数实现这一功能?
你可能会这样写:
def func(x):
print(2*x)
其实能写出这个来已经很好了,说明你大体理解了函数是什么。此时我们调用函数,假设func(3)
,你会发现屏幕上打印了6,这就对了,这很完美!
但其实很多时候我们想要的并不是单单的看到结果,就如同上边那个y=f(x)
,我们实际上把结果传给了因变量y,然后后面可能还会对y做一些操作(换元不就是这样嘛)
我们如何把2*x
的结果保留下来呢?你可能会这样想:
def func(x):
y = 2*x
其实这样是不行的,比如你可以试试,当调用完函数后,你就找不到y
了。
因为此处的y
是一个局部变量,在函数内定义的变量在函数结束后都会被销毁,并不会保留到函数外面,我们称函数域是这些变量的局部作用域。
所以这个方法是不行的,那有没有什么方法呢?当然是有的。
看看上面那个y=f(x)
,有没有给你什么灵感?我们可不可以写成这样y=func(x)
?
答案是当然absolutely一万个可以!实际上这就是之前被残忍省略的return
关键字的作用。
def func(x):
return 2*x
return
的作用就是把它后面的值返回给函数名(当然要带着括号和必要的参数),然后我们就可以对这个返回值进行操作了。
注意:不管函数内的代码运行到哪了,只要遇到
return
,就会直接结束函数,并返回要返回的值。
相关练习,从书上找找。