1. 函数
1.1. 什么是函数
函数,其实我们一开始学 Python 的时候就接触过。
不过我们目前使用的大多数都是 Python 的内置函数,比如 print()
,而现在,我们主要学习的是自定义函数。
「为什么需要函数呢?」
如果要想回答这个问题,我们需要先了解函数是什么?
函数就是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。或者说,函数其实就是把特定功能抽象出来的代码段。
那为什么要抽象出来呢?
「方便我们使用,方便我们重复使用。」
「函数的本质就是我们把一些数据喂给函数,让他内部消化,然后吐出你想要的东西,至于他怎么消化的,我们不需要知道,它内部解决。」
怎么理解这句话呢?
举个例子,好比每次用到的 print()
函数,我们都知道这个函数的作用是可以把我们的数据输出到屏幕,让我们看到。所以 print('Hello,world!')
, 我们想打印 Hello,world!
出来,就把 Hello,world!
这个数据喂给 print
函数,就可以直接把结果打印到控制台上了。
1.2. 怎么自定义函数
#伪代码 def 函数名(参数1,参数2....,参数n): 函数体 return 语句 # 可以不写return语句
这就是 Python 函数的组成部分。
所以自定义函数,有以下规则步骤:
- 函数代码块以
def
关键字开头,后接函数名和圆括号()
以及:
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
- 函数的第一行语句可以选择性地使用文档字符串(用于存放函数说明)
- 函数内容在第二行起始,并且缩进
- return [表达式] 结束函数,选择性地返回一个值给调用方。「不带表达式的 return 和没有return语句的函数都是相当于返回 None」。
# 伪代码 def function_name(parameters): """函数说明""" do_something return expression
现在我们有一个计算两数之和的需求,需要实现一个函数,具体步骤如下:
def
定义一个函数,给定一个函数名sum
- 声明两个参数
num1
和num2
- 函数的第一行语句进行函数说明:两数之和
- 最终使用
return
语句返回两数之和
def sum(num1,num2): """两数之和""" c = num1 + num2 return c
通过上面的sum
函数,我们可以通过sum(5, 6)
的形式来进行函数的调用,并把返回值赋给c
,可以知道,c=11
>>> c = sum(5, 6) >>> c 11
1.3. 函数的参数
设置与传递参数是函数的重点,而 Python 的函数对参数的支持非常的灵活。
主要的参数类型有:默认参数、关键字参数(位置参数)、不定长参数(这里不进行讲解)。
下面我们将一一了解这几种参数。
1.3.1 默认参数
有时候,我们自定义的函数中,如果调用的时候没有设置参数,需要给个默认值,这时候就需要用到默认值参数了。
默认参数,只要在构造函数参数的时候,给参数赋值就可以了
def print_user_info(name, age,gender='男'): # 打印用户信息 print(name) print(age) print(gender) >>> print_user_info('Jack' , 18 , '女') 'Jack' 18 '女' >>> print_user_info('Tom' , 20) 'Tom' 20 '男'
从输出结果可以看到,当你设置了默认参数的时候,在调用函数的时候,不传该参数,就会使用默认值。但是这里需要注意的一点是:「含有默认值的参数必需放在没有默认值参数的后面」。
1.3.2 关键字参数(位置参数)
一般情况下,我们需要给函数传参的时候,是要按顺序来的,如果不对应顺序,就会传错值,不过在 Python 中,可以通过参数名来给函数传递参数,而不用关心参数列表定义时的顺序,这被称之为关键字参数。
使用关键参数有两个优势 :
- 由于我们不必担心参数的顺序,使用函数变得更加简单了
- 假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值
具体看例子:
def print_user_info(name, age,gender='男'): # 打印用户信息 print(name) print(age) print(gender) >>> print_user_info(name = 'Tom' ,age = 18 , gender = '女') 'Tom' 18 '女' >>> print_user_info(name = 'Tom' ,gender = '女', age = 18) 'Tom' 18 '女'
1.4. lambda
匿名函数
有没有想过定义一个很短的回调函数,但又不想用 def
的形式去写一个那么长的函数,那么有没有快捷方式呢?
答案是有的。
python 使用 lambda 来创建匿名函数,也就是不再使用 def 语句这样标准的形式定义一个函数。
匿名函数主要有以下特点:
- lambda 只是一个表达式,函数体比
def
简单很多。 - lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
lambda 参数1,参数2,参数3,...,参数n : expression
我们使用lambda
将上面sum
函数重写一下,就可以得到下面的代码
sum = lambda num1 , num2 : num1 + num2 >>> sum(5, 6) 11
注意:**尽管 lambda 表达式允许你定义简单函数,但是它的使用是有限制的。你只能指定单个表达式,它的值就是最后的返回值。也就是说不能包含其他的语言特性了, 包括多个语句、条件表达式、迭代以及异常处理等等。**所以lambda
仅限于功能较简单的函数,当功能较复杂时,最好还是使用def
进行定义
2. 文件读写
2.1. 类比一下
2.1.1 把大象放进冰箱需要几步?
- 把冰箱门打开
- 把大象放进去
- 把冰箱门关上
2.1.2 把内容写进文件需要几步?
- 把文件打开
- 把内容放进去
- 把文件关上
2.2. 文件类型
在计算机中,文件可以大致分为两类,一类是文本文件,一类是二进制文件,后者是存储的0101001111
这样的二进制文件,后者则是在前者的基础上对二进制数据进行编码,将编码后的数据写入文件。常见的文件有下面这些。
- 文本文件
.txt
.csv
...
- 二进制文件
.doc
.jpg
.mp4
...
2.3. 打开文件
在python中有一个内置函数,即open()
函数。这个函数有几个重要的参数
# 伪代码 def open(file, mode, encoding=None): ...
file
:即文件的路径mode
: 对文件所要进行的操作类型,是读取还是写入还是即读取又写入,是对文本文件进行操作,还是对二进制文件进行操作encoding
:这个参数只有对文本文件操作时才是有效的,因为二进制文件不存在编码的过程
具体的看下面的例子
fp = open("1.txt",'w') # 打开了一个文件名为 "1.txt"的文件,如果不存在,就先创建后打开,打开的模式是'w' fp.write("123") # 写入了一个字符串 能不能同时写两个write语句? fp.close() # 把文件关上
上面是一个文本文件,如何写入一个二进制的文件?只需要改一下mode
参数就可以写入二进制文件了
fp = open("1.jpg",'wb') fp.write(content_data) fp.close()
2.3.1 把内容从文件中读出来
和写方法一样,只是 把write()
方法换成了read()
方法
fp = open("1.txt",'r') fp.read() fp.close()
如何读一个二进制文件
fp = open("1.jpg",'rb') fp.read() fp.close()
总结一下文件操作的步骤就是
- 把文件打开
open()
- 把内容放/拿进去
read()/write()
- 把文件关上
close()
他们的区别主要在于mode
和打开以后使用的方法,是使用write
还是使用read
,对于write
还是read
很好理解,写的时候就用write
,读的时候就用read
。下面对于mode
详细讲解一下。从上面的例子可以发现,当mode
含有w
(write
)时,无论是对于文本文件还是对于二进制文件,都是写的操作,同理当mode
中含有r
(read
)时,都是读的操作。至于具体是针对文本文件还是针对二进制文件,则取决于mode
中的第二个字母,对于文本文件而言,在不做生命的情况下就是默认针对文本文件,所以r
和w
都是针对文本文件的。对于二进制文件,会再加一个b
(binary
)来声明是对二进制文件的操作。
2.3.2 对于读写更好的方法
使用with(上下文管理器)
with open("1.txt",'r') as f: f.read() with open("1.txt",'w') as s: # as 后面的s是一个你自己定义的变量名,只要合法就行 s.write(data)
with 可以帮助我们自动关闭文件,从而不需要再进行close()
未完待续