Python 函数与模块

一、函数

函数是一段可以重复使用的代码,通过传递的参数返回不同的结果,前面章节已经使用了 Python 定义的函数如 range()、len()、input()等,本章讲解用户自定义的函数。

对于重复使用的代码,可以编写为自定义函数以便于重复使用代码,同时提高开发人员的 开发效率。函数可以分为无参函数和带参函数。

1.无参函数

Python 的自定义无参函数并不复杂。

以关键字 def 开始,后面跟函数名、小括号、冒号,最后使用 return 退出函数。用表达 式可以传递函数的返回值,如果没有返回值,则返回 None。

函数是以字母、数字和下划线组成的字符串,但是不能以数字开头。

示例 1:

使用无参函数实现两数相加并输出二者之和。示例代如下:

python 复制代码
def add():
    op1=10
    op2=20
    rt=op1+op2
    print(op1,'+',op2,'=',rt)
    return
add()

#程序输出:
10 + 20 = 30

该程序首先定义了无参函数 add(),它输出 10+20 的结果值,return 没有返回值,直接使用 函数名add()进行了调用。

把上面的代码进行修改,用 return 返回结果值,代码如下:

python 复制代码
def add():
    op1=10
    op2=20
    rt=op1+op2
    return rt
i=add()
print(i)

#程序输出
30

函数 add()使用 return 语句可以返回两数相加的结果值,变量 i 接收函数 add()返回的 值。Python 在处理返回值时,如果没有 return 语句,会默认返回 None,程序并不会报错。

示例 2:

输出九九乘法表示例代码如下:

python 复制代码
def nine():
    op1=(1,2,3,4,5,6,7,8,9)
    op2=(1,2,3,4,5,6,7,8,9)
    for i in op1:
        for j in op2:
            print(i,"*",j,"=",i * j)
    return
nine()

使用函数时经常会范围一些错误,总结如下:

  • 函数的定义要先于函数的调用,否则会出错。
  • 函数体的代码是一个整体,要注意缩进。
  • 定义函数时要使用冒号,但调用时不可以使用冒号。

2.带参函数

Python 带参函数的语法格式如下。

语法:

def 函数名称(形式参数列表):

代码块

return [表达式]

通过语法可以看出,带参函数与无参函数的区别是在函数名称后面的小括号中有形式参数列表,简称形参列表。

注意:形式参数列表实际上只是占位符,用于体现参数的个数,每个参数都没有提供具体 的数值。

调用带参函数时,需要为每个参数传递对应的实际数值,又称实参列表。

示例 4 是完成加法运算的函数代码。

示例 3:

定义并调用带参函数完成两数相加的运算。

python 复制代码
def add(x,y):
  return x+y
print(add(1,2))

#执行结果:
3

当调用函数时,根据传递的实际参数值出现位置与函数定义的形式参数列表进行匹配。

示例 4:

使用位置参数方式或关键字参数方式调用带参函数。示例代码如下:

python 复制代码
def aa(x, y):
print(x, y)
aa(10, 6)
aa(6, 10)
#执行结果:
10 6
6 10

当程序代码比较繁琐时,参数的顺序很难记住,可以使用关键字参数。关键字参数是在调用函数时, 明确指定参数值赋给指定的形参,示例代码如下:

python 复制代码
def aa(x, y):
print(x, y)
aa(x=10, y=6)aa(y=6, x=10)
#执行结果
10 6
10 6

代码中,aa(x=10,y=6)和 aa(y=6,x=10)语句在调用函数 aa(x,y)的同时,指定了参数 的名称和对应值(x=10,y=6)和(y=6,x=10)。这两个语句明确指定了实参和形参的对应关系, 与参数所在的位置无关,所以输出结果是相同的。

调用带参函数时,传入函数的参数个数必须和声明的参数个数一致。当函数包含有多个 参数时,一旦实参个数与形参个数不符,就可能出错。为了避免这样的错误发生,Python 在 函数定义时允许为形式参数指定默认值,从而在调用参数时可以少写参数,省略的参数用默认值为其 赋值。

下面是使用参数默认值的代码示例:

python 复制代码
def aa(x, y):
print(x, y)
aa(10) ##会报错,缺少 y
aa(x=10) ##会报错,缺少 y
aa(10, 5)
aa(x=10, y=5)

函数定义时,参数 y 的默认值是 6。函数调用时,可以不传递 y 的值,只传递 x 的值。 直接传值或使用参数名并赋值的方式都可以,aa(10)和 aa(x=10)的结果是相同的。当传递 y 的值是 5 时,此时 y 的默认值不起作用,所以 aa(10,5)和 aa(x=10,y=5)输出时 y 的值都 是 5。

定义参数默认值时,要注意:位置参数必须出现在有默认值参数之前。

下面的函数定义是错误的。

python 复制代码
def aa(x=1,y):
print (x,y)
aa(10,6)

上面的代码中,位置参数 y 出现在有默认值的参数 x=1 的后面,此时,会产生语法错误。

纠正错误后的正确写法

python 复制代码
def aa(x,y=1):
print (x,y)
aa(10,6)

下面通过示例 6 加深对带参函数的理。

示例 5:

编码实现计算器功能

要求:用户输入两个数字和运算符,程序根据用户指定的运算符执行加、减、乘、除运 算。为了使程序结构清晰,需要编写 2 个函数,一个是用来处理加减乘除运算,一个是用 来处理字符串和数值转换。实现步骤如下:

python 复制代码
def add(x,y):
  return x+y
def subtract(x,y):
  return x-y
def multiply(x,y):
  return x*y
def divide(x,y):
  return x/y

print("选择运算:")
print("1、相加")
print("2、相减")
print("3、相乘")
print("4、相除")
choice = int(input("输入你的选择(1/2/3/4):"))
num1=int(input("请输入第一个数字:"))
num2=int(input("请输入第二个数字:"))

if choice==1:
  print(num1,'+',num2,'=',add(num1,num2))
elif choice==2:
  print(num1,'-',num2,'=',subtract(num1,num2))
elif choice==3:
  print(num1,'*',num2,'=',multiply(num1,num2))
elif choice==4:
  print(num1,'/',num2,'=',divide(num1,num2))
else:
  print("非法输入")

3. 函数中变量的作用域

作用域是指变量在程序中的应用范围,而变量声明的位置决定它的作用域。Python 按作用 域区分有局部变量和全局变量。

全局变量是指在一个模块中最高级别的变量有全局作用域,除非被删除,否则存活到程 序 运行结束,所有函数都能访问全局变量。

局部变量是指定义在函数内的变量有局部作用域,依赖于定义变量的函数现阶段是否处 于活动状态。调用函数时,局部变量产生,暂时存在。一旦函数执行完,局部变量将会被释放。

局部变量和全局变量的使用规则:

  • 局部变量的作用域仅限于定义它的函数,
  • 全局变量的作用域在整个模块内部都是可见的,
  • 在同一个函数中,不允许有同名局部变量。
  • 在不同的函数中,可以有同名局部变量。
  • 在同一个程序中,全局变量和局部变量同名时,局部变量具有更高的优先级。
示例 6:

使用函数实现年龄的输出。

python 复制代码
name='zhangsan'
def f1():
  age=20
  print(age,name)
def f2():
  age=19
  print(age,name)
f1()
f2()

#输出结果
20 zhangsan
19 zhangsan

在 Python 中尽量不使用全局变量,因为程序的任意代码都可以自由地访问和修改全局变 量的值,非常容易出现数据被意外修改的错误,而这种错误很难被发现。

global 的作用是声明变量为全局变量,即使变量定义在函数内部,加上 global 后,也 可以在全局范围访问。

示例代码如下:

python 复制代码
def f1():
  global name
  name='zhangsan'
  age=20
  print(age,name)
def f2():
  age=19
  print(age,name)
f1()
f2()

#输出结果
20 zhangsan
19 zhangsan

4.lambda 函数

lambda 函数的作用是创建匿名函数,是一种声明函数的特殊方式。其中 params 相当于 函数接收的参数列表,expr 是函数返回值的表达式。

示例 7

编写一个普通函数和一个 lambda 函数。

示例代码如下:

python 复制代码
def sum1(x,y):
return x+y
sum2=lambda x,y:x+y
print(sum1(3,4))
print(sum2(3,4))
#执行结果:
7
7

实现的是相同的功能,但 lambda 函数更加简洁,只需一条语句实现,所以 lambda 也称 为 lambda 表达式。使用 lambda 只能是表达式,不能包含 if、for 等条件循环语句。对于 不需要复用、简单的匿名函数,使用 lambda 能起到很好的效果。

5.内建函数

Python 除了本身的语法结构,还提供了常用的内建函数。内建函数是程序员经常使用到的 方法,可以提高程序的编写效率。如 float()就是内建的函数。内建函数是自动加载的,Python 的解释器可以识别。它不需要导入模块,不必做任何的操作,不需要引用就可以调用 。下面开 始介绍常用的内建函数。

(1)abs()函数

abs()函数能够返回一个数字的绝对值,即正数。语法格式如下。

语法:

abs(x)

参数 x 可以是正数,也可以是负数,示例 9 代码如下:

python 复制代码
>>> abs(10)
10
>>> abs(-10)
10
>>> bb = -3
>>> abs(bb)
3

参数是 10 或-10,返回的是绝对值,结果都是 10.

(2)bool()函数

bool()函数返回值是 True 或 False,它是 Boolean(布尔值)的简写,

将参数 x 转换为 Boolean 类型,当参数是数字时,0 返回 False,其他任何值都返回 True。 参数是字符串时,None 或空字符串返回 False;否则返回 True。参数是空的列表、元组或字 典返回 False;否则返回 True。

示例 10 代码如下:

python 复制代码
>>> bool() #无参时返回
False
>>> bool(0)
False
>>>bool(-3)
True
>>> bool(None)
False

注意,括号中 None,首字母要大写

python 复制代码
>>> bool('')
False
>>> bool('xyz')
True
>>> bool([11,22])
True
(3)float()函数

float()函数用于转换数据为 float 类型,

参数 x 可以是字符串或数字,

示例 11 代码如下:

python 复制代码
>>> float('25')
25.0
>>> float(3)
3.0
>>> float(999.586103)
999.586103
>>> float('999.586103')
999.586103

字符串和数字都可以转为 float 类型。如果不能转换,就会抛出异常。

(4)int()

int()函数可以将数据转换为整数,

示例 12 代码如下:

python 复制代码
>>> int(199.99) #浮点数199
>>> int('100') #字符串
100
>>> int('99.9') #字符串
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '99.9'

注意:当参数是字符串时,字符串中只能是整数格式。如果是浮点格式将有异常产生。

(5)range()

range()函数可以生成一个迭代对象,

  • 第一个参数 start 表示起始值,是可选参数,默认值是 0。
  • 第二个参数 stop 表示终止值。
  • 第三个参数表示步长,是可选参数,可以是正数或负数,默认值是 1。

从给定的第一个参数开始,到比第二个参数值小 1 的数字结束,常与 for 循环一起使用, 循环执行指定数字的次数。示例 13 代码如下:

python 复制代码
>>> ange(0,5)
range(0,5)
>>> list(range(0,5))
[0, 1, 2, 3, 4]
>>> >>> range(0,30,3)
range(0, 30, 3)
备注:0 表示开始的数字,30 表示结束的,3 表示步进
>>> list(range(30,0,-3))
[30, 27, 24, 21, 18, 15, 12, 9, 6, 3]
>>> for i in range(0,5):print (i)
0
1
2
3
4
(6)sum()函数

sum()函数可以对列表中元素求和,示例 14 代码如下:

python 复制代码
>>> num=list(range(1,101))
>>> num
[0, 50, 100, 150, 200, 250, 300, 350, 400, 450]
>>> print(sum(num))
5050

使用 range()生成了一个列表,然后使用 sum()对列表中的数值进行累加求和。

(7)max()函数

max()函数可以返回列表、元组或字符串中最大的元素,如果元素是英文字母,那么字母是 "大于"数字的,而小写字母"大于"大写字母,示例 15 代码如下:

python 复制代码
>>> num = [6,2,12,7,65]
>>> max(num)
65
>>> string = 'd,u,a,n,g,D,U,A,N,G'
>>> max(string)
'u'
>>> max(1000,650,98,2678,9)
2678
(8)min()函数

min()函数返回列表、元组、或字符串中最小的元素,与 max()的使用方式相反,它取的是最 小值,示例 16 代码如下:

python 复制代码
>>> min([6,2,12,7,65])
2

二、模块与包

如果编写的程序中类和函数较多时,就需要对它们进行有效的组织分类,在 Python 中模 块和包都是组织的方式。复杂度较低可以使用模块管理,复杂度高则还要使用包进行管理。

1.模块

模块是 Python 中一个重要的概念,实际上就是包含 Python 函数或者类的程序。模块就 是一个包含 Python 定义和语句的文件,把一组相关的函数或代码组织到一个文件中,一个文 件即是一个模块。模块的文件名=模块名+后缀.py。模块之间代码共享,可以相互调用,实现代 码重用,并且模块中函数名称必须唯一。

(1)模块定义

下面代码演示模块的定义,保存的文件名是 myModule.py

python 复制代码
#fileName : myModule.py
def add(a,b):
print (a+b)
def mul(a,b):
print (a*b)

在模块 myModule 中,定义了 2 个函数,一个加法函数和一个乘法函数。它们处理的问题 是同类的,作为一个模块定义。

(2)模块导入

使用模块中的函数时,要先导入模块才能使用,导入有 2 种方式。在一行导入一个模块, 语法如下。

语法:

import 模块名

还可以在一行导入多个模块,语法如下。

语法:

import 模块名 1[,模块名 2][,模块名 3]...

模块和变量一样也有作用域的区别。如果在模块的顶层导入,则作用域是全局的。如果在 函数中导入,则作用域是局部的,其作用域只是所在的函数中。一个模块只能被加载一 次, 无论它被导入多少次,可以阻止多重导入时代码被多次执行。在实际编码时,推荐直接在顶层 导入。

导入的模块也分几种,有 Python 的标准库模块、第三方模块和应用程序自定义的模块。 加载执行时在搜索路径中找到指定的模块,如果是第一次导入,模块将被加载并执行,之后再 调用时就不需要再次加载了。

示例 1:导入标准库模块 sys。示例代码如下:

python 复制代码
>>> import sys
>>> print (sys.platform)
linux

Python 的标准库模块 sys 包含了 Python 环境相关的函数,sys.platform 返回当前平 台的系统名称。

示例 2:导入并调用自定义模块 myModule 示例代码如下:

python 复制代码
>>> import myModule
>>> myModule.add(2,3)
>>> myModule.mul(2,3)
#结果
5
6

模块名就是定义的文件名。在调用模块中函数的语句格式是"模块名.函数名"。每个模块都有 name 属 性,表示模块的名称。

如果不使用模块名,而直接用函数名进行调用,就需要在导入时指定需要使用模块的属 性,一行导 入一个模块属性的语法如下。

语法:

from 模块名 import 属性名

一行导入模块的多个属性语法如下。

语法:

from 模块名 import 属性名 1[,属性名 2] [,属性名 3]...

示例 3:

导入模块属性代码如下所示:

python 复制代码
>>> from myModule import add,mul
>>> add(2,3)
>>> mul(2,3)
#结果
5
6

示例3 的代码是先导入模块 myModule 的add()、mul()函数,然后,可以不使用模块名, 直接使用函数名 调用。另外,还可以使用 as 关键字为模块或模块属性重新命名,语法如下。

语法:

import 模块名 as 模块新名称

from 模块名 import 属性名 as 属性新名称

示例 4:
python 复制代码
使用 as 关键字为模块重新命名,示例代码如下:
>>> from myModule import add as add1,mul as mul1
>>> add1(2,3)
>>> mul1(2,3)
#结果
5
6

示例 4 的代码中,先将函数 add()重命名为 add1,mul 重命名为 mul1。随后,程序中可以用新的 名称调用函数。

2.包

当程序中的模块非常多时,可以把模块再进行划分,组织成包。包实际上就是一个目录,但必须包含 一个" init .py"文件。" init .py"可以是一个空文件,表示当前目录是一个包。包还可以嵌套使 用,包中可以包含其它子包。

(1)包的使用

导入包中的模块只需要在模块名前加上包的名称即可,如按以下方式组织的目录:

project/ #目录

project.py

subproject/ #子目录

init.py #注意:init 前后都是两个下划线

submodel.py

示例 5:

project.py 中调用包 subproject 中 submodel.py 模块示例代码如下:

在 subproject 目录下创建模块 submodel.py

python 复制代码
#submodel.py
def add(a,b):
return a+b

在 project 目录下创建程序文件 project.py

python 复制代码
#project.py
import subproject.submodel
print (subproject.submodel.add(1,3))
python 复制代码
[root@localhost project]# python3
project.py 4

示例 5 中,先导入加入包名 subproject.submodel,再调用执行包 subproject.submodel 中的函数 add()。

(2)init.py

前面使用的是空 init.py 文件,也可以在里添加代码,它的作用实际上是初始化包中的公共变 量。在第一次使用 import 导入 subproject 包中的任何部分后,会执行包中的

init .py 文件代码。

示例 6:

在 subproject 目录中的__init__.py,加入如下代码:

python 复制代码
name = '__init__.py'
print ('subproject->',name)
python 复制代码
[root@localhost project]# python3 project.py
subproject->__init__.py
4

3.常用模块

(1)keyword 模块

使用 keyword 模块可以查看 Python 语言的关键字,它的属性 kwlist 包含了所有 Python 关键 字的列表。方法 iskeyword(字符串)用于判断参数是否是 Python 的关键字。如果参数是 Python 的关 键字,则返回 True;否则,返回 False。

示例 10:判断 Python 的关键字示例代码如

python 复制代码
>>> import keyword
>>> print(keyword.iskeyword("if"))
True
>>> print(keyword.iskeyword("abcde"))
False
>>> print(keyword.kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def',
'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import',
'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while',
'with', 'yield']
(2)random 模块

random 模块用于生成随机的浮点数、整数或字符串,常用的方法如下表所示。

|------------------------|-----------------------------|
| 方法 | 操作 |
| random() | 生成一个随机的浮点数,范围在 0.0~1.0 之间 |
| uniform([上限][,下限]) | 在设定浮点数的范围内随机生成一个浮点数 |
| randint([上限][,下限]) | 随机生成一个整数,可以指定这个整数的范围 |
| choice(序列) | 从任何序列中选取一个随机的元素返回 |
| shuffle(序列) | 随机打乱一个序列中元素的顺序 |
| sample(序列,长度) | 从指定的序列中随机截取指定长度的片断,序列本身不做修改 |

示例 11:使用 random 模块常用方法生成随机整数,并重新排序示例代码如下:

python 复制代码
>>> import random #导入 random 模块
>>> print (random.randint(1,100)) #随机选取 1-100 之间的整数
>>> print (random.randint(100,500)) #随机选取 100-500 之间的整数
>>> list1 = ['aaa','bbb','ccc']
>>> str1 = random.choice(list1) #随机选取列表中一个元素
>>> print ('随机选取列表中的一个元素:',str1)
>>> print ('重新排序后:\n')
>>> random.shuffle(list1) #随机重新排序列表中的元素 for str1 in list1:
>>> print (list1)
#结果
>>> 2
310

随时选取列表中的一个元素: ccc

重新排序后:

['bbb', 'aaa', 'ccc']

random 模 块 产 生 的 结 果 都 是 随 机 的 , 每 次 运 行 的 结 果 不 一 定 相 同 。 示 例 11 中 , random.randint(1,100)方法随机返回 1 至 100 之间的一个整数,random.choice(list1)方法随机 返回列表中一个元素,而 random.shuffle(list1)方法是随机打乱列表元素的顺序。

(3)sys 模块

sys 模块包含与 Python 解释器和运行环境相关的属性和方法,常用的属性和方法如下表:

|------------|------------------------------------|
| 属性/方法 | 操作 |
| version | 获取解释器的版本信息 |
| path | 获取模块的搜索路径,初始化时使用 PYTHONPATH 环境变量的值 |
| platform | 获取操作系统平台名称 |
| maxint | 最大的 int 值 |
| maxunicode | 最大的 Unicode 值 |
| stdin | 读取信息到 Shell 程序中 |
| stdout | 向 Shell 程序输出信息 |
| exit() | 退出 Shell 程序 |

示例代码如下所示:

python 复制代码
>>> import sys #导入 sys 模块
>>> print ("Python version:%s" %sys.version)
>>> print ("Python platform:%s" %sys.platform)
>>> print ("Python path:%s" %sys.path)
(4)time 模块

time 模块包含各种操作时间的方法,常用方法如下表所示:

|-------------|--------------------------|
| 属性/方法 | 操作 |
| time() | 获取当前时间戳 |
| localtime() | 获取当前时间的元组形式 |
| ctime() | 获取当前时间的字符串形式 |
| asctime(t) | 将时间转换成字符串,参数 t 是元组形式的时间 |
| sleep(secs) | 按指定的时间推迟运行,参数是推迟的时间,单位是秒 |

Python 中时间有时间戳和元组两种表示形式。时间戳的表现形式是以相对 1970.1.1 00:00:00 为 起点,以秒计算的偏移量,是唯一的值。而以元组的形式表示则共有 9 个元素,分别是 year(4 位数字组成)、month(1-12)、day(1-31)、hours(0-23)、minutes(0-59)、second(0-59)、weekday(0-6, 0 表示周一)、Julian day(1-366,一年里的天数)、DST flag(-1, 0 或 1,是否是夏令时,默认为 -1)。

使用"time.time() "获得的是以秒为单位的偏移量,在 for 循环开始处获得时间戳,循环结束时再获得时间戳,相减后就是循环执行的时间。

以元组的形式获取时间,示例代码如下:

python 复制代码
>>> import time
>>> print (time.time()) #获取时间戳
1702474400.840029
>>> print (time.asctime()) #时间的字符串形式
Wed Dec 13 21:33:20 2024
>>> print (time.localtime()) #时间的元组形式 t1 =
time.struct_time(tm_year=2024, tm_mon=12, tm_mday=13, tm_hour=21, tm_min=33, tm_sec=22,
tm_wday=2, tm_yday=347, tm_isdst=0)
>>> t1 = (2015,9,29,10,30,12,12,12,0)
>>> print (time.asctime(t1)) #把时间的元组形式转换为字符串形式
Sat Sep 29 10:30:12 2015
>>> t2 = time.localtime()
>>> year = t2[0] #获得时间元组中的年份
>>> print (year)
2024
相关推荐
明月看潮生14 分钟前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
南宫理的日知录25 分钟前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
coberup34 分钟前
django Forbidden (403)错误解决方法
python·django·403错误
逊嘘41 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
Half-up44 分钟前
C语言心型代码解析
c语言·开发语言
龙哥说跨境1 小时前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
Source.Liu1 小时前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马1 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng1 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust