Python自学笔记

2019/12/18 Programming

笔者在自学 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关键字,那第二步呢?
这就用到分支结构了。
因为这是一个选择/判断,不同的选择会导致不同的结果,我们用ifelse关键字。
代码如下:

sex = input("请输入你的性别:")
if sex == "男":
    print("你是男的")
else:
    print("你是女的")

因此,分支结构的模板如下:

if 条件表达式为真:
    语句块1
else:
    语句块2

此处需注意三点:

  1. 不管条件表达式多长,它最终永远是一个布尔值,即非True即False,如果是True,执行语句块1,否则执行语句块2
  2. 条件表达式后面和else后面有一个(英文的)冒号,不能漏不能漏不能漏
  3. 冒号后边有缩进,默认一个Tab键或四个空格,python通过缩进来划分结构。

还需要注意一点,在几乎所有编程语言中,等号都是用于赋值,而双等号(==)才是数学含义的等于,用于判断左右是否相等。

其实进行到这了,你大概发现了一个问题,如果没发现说明你不太行,上边这个功能果然很智障。
因为只要用户不输入“男”,python总会反馈一个“你是女的”,比如我输入“天空”,“草地”,“炸鸡腿堡”,python都会义无反顾地给你反馈一个“你是女的”。
其实啊,这不是python的问题,这是的。

咳咳,其实上边这个if else叫做双分支结构,如果我们想要实现不止两个分支呢?

我们改进一下上边这个功能,我们想让用户输入“男”时,反馈一个“你是男的”,当用户输入“女”时,反馈“你是女的”,而如果用户乱输其它内容的话,我们给他个“我不知道你在说什么”。
聪明的你或许发现了,这个需要三个分支。代码如下:

sex = input("请输入你的性别:")
if sex == "男":
    print("你是男的")
elif sex == "女":
    print("你是女的")
else:
    print("我不知道你在说什么")

这叫做多分支结构
其实变化就只有一点,加了一个elif,同时要注意,它后面也是跟一个条件表达式,表达式后面也有一个冒号,它下面的语句块也需要缩进。

所以总结一下,分支流程就是,ifelif把所有可能的情况都列出来然后处理,如果都不是这些情况,则交给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 条件表达式为真:
    语句块

注意点:

  1. while表示循环的开始,后面接一个条件表达式,然后后边再加一个冒号,不能忘不能忘不能忘
  2. 需要循环的语句块要缩进。
  3. i+=1的意思是i=i+1,即把i增加1,然后赋值给i,即自增1
  4. 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)

观察输出结果,理解breakcontinue的区别。

除了while循环,还有一种更简单的方式可以实现最开始那个智障的功能:

for i in range(10):
    print(i)

是不是更简洁了?也更难懂了
难懂没关系,解释嘛。

这个循环叫for循环,模板如下:

for 变量名 in 可迭代对象:
    语句块

此处注意:

  1. 变量名就是一个普通的变量,起名时符合命名规范,同时尽量有一定意义。
  2. 可迭代对象可以理解为一个有限序列,这个序列中的值是可以从头数到尾的。比如此处的range就是一个整数序列。
  3. range序列默认从0开始,range(10)表示从0数到9,同理,range(99)表示从0数到98。
  4. 可迭代对象后面依然有个:不能忘不能忘不能忘
  5. 需要循环的语句块缩进。

其实此处的变量名就是对可迭代对象中的每个值的统一的一个称呼,变量会依次被每个值赋值,这个过程叫做遍历

尝试用for循环改写拥有限制次数的猜数字游戏。

此时聪明的你可能有发现了,这个地方的变量根本没用上!其实不是没用上,是你没看见
咳咳,那我就是想看见怎么办呢?
Hmm,不,你不想。

注意:breakcontinuefor循环同样适用

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,她说得对,的确不是一码事,但在后面,你要不可避免的理解返回值的时候(如果理解函数是什么是第一个难点,那么理解函数的返回值是什么就是第二个难点),把它结合数学上的函数会有点帮助。

不过这些都是后话了,我们还是先来想一个经典的例子吧。

问,如果让你把大象塞进冰箱,需要几步?
也许你现在还不会理解,但不得不说,这真是一个理解计算机问题的超典型的例子。
答案也许你早就知道了,没错,就分三步:

  1. 把冰箱门打开。
  2. 把大象塞进去。
  3. 把冰箱门关上。

根据这个例子,我们来理解函数的第一个功能(为什么不先说什么是函数呢,其实理解了函数干了什么事也就能理解函数是什么了):
假设上面的每一个步骤都是一行代码,三行代码来完成把大象放进冰箱这个任务,那么当我们想把一头大象塞进冰箱时,写出这三行代码就完事了。
但是!老师说不行,你得塞十头
好了,你有十头大象,你要把它们都塞进冰箱。怎么办呢?
聪明如你,写了三十行,每三行就重复一次,一共十次,塞了十头。
然后第二天你因为左脚进教室被老师逐出了班级名单。

太麻烦了对吧,代码重复性太高了,你写起来费劲(可能不费劲,复制粘贴就好了),别人看起来也费劲。
这就用到函数的第一个功能了——提高代码复用性。函数的定义模板如下:

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,就会直接结束函数,并返回要返回的值。

相关练习,从书上找找。

6. 文件使用

Search

    Table of Contents