这一篇主要介绍函数
定义
函数是带名字的语句块,我们可以写好各块语句,并把它命名,等到我们在某处需要,就可以写函数,程序就会自动跳转的指定语句块并执行。这样大大减少了工作量。
#使用函数
def greet_user():
print("Hello !")
#使用函数
greet_user()
组成部分
函数名
跟在def关键词后面的即是函数名,是接下来语段的标志,是程序用于识别并调用语句块的重要组成部分。
参数
在()里的内容就是参数,**一个函数可以没有参数,但是一定不能不写(),**参数分为实参和形参:
实参指的是程序在运行中实际传给函数语句的参数
形参指的是在定义并编写语句时所用到参数
在程序运行的过程中,每个形参在调用时必须有一个实参与之对应,只要在定义函数的时候和调用函数的时候把实参和形参的位置对应起来就不用担心,有一种更保险的方法就是传入实参时以形参=实参的方式传入,这种方式赋值的实参叫做关键字实参。这两种方式可以混合使用,但永远记住:实参参入的顺序是从左至右,依次传入为赋值的形参中
默认值:在实参和形参一一对应的过程中,实际上可以设置形参的默认值(对应的默认实参),这样在调用函数时,就不一定要对所以参数进行赋值,但要注意:实参参入的顺序是从左至右,默认值的设置只能从右至左。
小技巧
设置形参的默认值为空是一个很好用的技巧,这样该形参就好像隐身了一样
如果在形参名前加一个*,代表这是一个空列表,那么你就可以实现传入的参数个数可变
当你在形参名前加**则表示该形参是一个空字典,你可以实现传入键值对
返回值
函数调用时,并不会直接改变实参值,而更像是一种映射。函数中所以变量发生的更改都不会直接影响实际值,想要带出函数内部得到的一个或多个数据,就要定义函数的返回值
下面是一个得到返回值的例子:
def calculate(a, b):
sum = a + b
difference = a - b
product = a * b
quotient = a / b
return sum, difference, product, quotient
result = calculate(10, 2)
print(result)
# 输出:(12, 8, 20, 5.0)
#如果你想分别得到它们,则:
sum, difference, product, quotient = calculate(10, 2)
print(sum) # 输出:12
print(difference) # 输出:8
print(product) # 输出:20
print(quotient) # 输出:5.0
#如果你想得到的是3+1的结果可能就不能一步到位了
修改性质
在Python中,函数参数传递的是对象的引用。如果参数是不可变类型(如整数、字符串、元组),那么在函数内部对参数的修改,实际上是创建了一个新的对象,而原对象并未改变。如果参数是可变类型(如列表、字典),那么在函数内部对参数的修改,会直接影响到原对象。
这是因为在Python中,变量是对对象的引用。当我们传递参数时,实际上是传递了对象的引用。对于不可变类型,由于无法修改对象本身,所以在函数内部对参数的修改,实际上是创建了一个新的对象,并将参数的引用指向了这个新对象。而对于可变类型,由于可以修改对象本身,所以在函数内部对参数的修改,实际上是直接修改了原对象。
例如,以下代码展示了如何在函数中修改可变类型的值:
def change_list(lst):
lst.append(4)
my_list = [1, 2, 3]
change_list(my_list)
print(my_list) # 输出:[1, 2, 3, 4]
在这个例子中,change_list
函数接收一个列表作为参数,并在其上调用append
方法。由于列表是可变类型,所以这个修改直接影响到了原列表my_list
。
然而,如果我们尝试在函数中修改一个不可变类型的值,情况就会不同:
def change_int(n):
n = n + 1
my_int = 1
change_int(my_int)
print(my_int) # 输出:1
在这个例子中,change_int
函数接收一个整数作为参数,并试图通过增加其值来修改它。但是,由于整数是不可变类型,所以这个修改并未影响到原整数my_int
,my_int
的值仍然是1。
不可变类型的值在函数中虽然是无法直接修改的。但是,我们可以通过返回新的值并重新赋值的方式来“修改”不可变类型的值。例如:
def change_int(n):
return n + 1
my_int = 1
my_int = change_int(my_int)
print(my_int) # 输出:2
在这个例子中,change_int
函数接收一个整数作为参数,并返回这个整数加1的结果。然后,我们将这个结果重新赋值给my_int
,从而实现了对my_int
的“修改”。
这种方式的缺点是需要手动进行重新赋值,而且如果有多个不可变类型的参数需要修改,那么就需要返回一个元组或者列表,然后使用解包的方式进行赋值,这会使代码变得复杂。例如:
def change_ints(n, m):
return n + 1, m + 1
my_int1 = 1
my_int2 = 2
my_int1, my_int2 = change_ints(my_int1, my_int2)
print(my_int1) # 输出:2
print(my_int2) # 输出:3
在这个例子中,change_ints
函数接收两个整数作为参数,并返回这两个整数各加1的结果。然后,我们使用解包的方式将这两个结果重新赋值给my_int1
和my_int2
,从而实现了对my_int1
和my_int2
的“修改”。
模块
模块是扩展名为.py的文件,一个模块就像是许多函数的集合,如果你可以将别人打包好的模块导入到你的电脑,那么你就可以轻松使用到他们的成果。
导入
我们可以使用mport语句来导入模块。以下是一些常见的导入方式:
导入整个模块
使用import
关键字后跟模块名。例如,如果我们想要导入名为math
的模块,我们可以这样做:
import math
然后,我们可以使用模块名.函数名
的方式来调用模块中的函数。例如,调用math
模块中的sqrt
函数:
sqrt_4 = math.sqrt(4) # 结果是2.0
从模块中导入特定的函数或变量
使用from ... import ...
语句。例如,如果我们只想要导入math
模块中的sqrt
函数,我们可以这样做:
from math import sqrt
#from math import * 表示导入模块的所有函数,接下来你就可以直接写函数名进行调用
然后,我们可以直接使用函数名来调用函数,无需再使用模块名。例如:
sqrt_4 = sqrt(4) # 结果是2.0
以别名导入
导入模块并给它一个别名有时候,模块的名字可能很长,或者我们想要避免与其他变量或函数的名字冲突,我们可以在导入模块时给它一个别名。例如,我们经常将numpy
模块导入并给它一个别名np
:
import numpy as np
然后,我们可以使用这个别名来调用模块中的函数。例如,调用numpy
模块中的array
函数:
arr = np.array([1, 2, 3])
当然你也可以结合别名和导入函数的方法,给模块中的函数起一个别名
pip
请注意,模块必须在你的Python环境中可用,否则导入会失败。如果模块不可用,你可能需要使用包管理器(如pip)来安装它,
python有太多有意思的经典模块了,记住这是使得python这门语言伟大的原因之一。