前言
很久没有更新了,想了想,觉得之前那个思维导图有点不合适,而且忘了一个很重要的内容,所以重新做了两张思维导图,把基础语法内容和进阶内容分开了,在之前的文章教程中,我们已经讲完了Python的基础语法,如果有感兴趣的朋友可以去我的主页查找我之前的文章来阅读。
这张思维导图是后面文章的内容了,这篇文章呢,我们就从函数开始讲起。
目录
一、什么是函数
概念上来说,函数就是一段可重复使用的代码块,用于执行特定的任务。
在Python中,函数分为三种,一种是库函数,一种是内置函数,还有一种是自定义函数。
库函数:
库函数是编程语言中已经预先编写好的函数集合,这些函数被组织在库(library)中。库是一段经过编译的代码,可以被程序重复使用,以实现特定的功能。就像一个工具包,里面有各种各样的工具(函数),开发者可以直接使用这些工具来完成任务,而不用自己从头开始编写实现这些功能的代码。
调用库函数时,我们首先要调用该函数所在的库,用import 函数名的方式来调用,
python中有很多库函数,应用于不同的功能,例如math库常用于做数学计算:
import math #这是一个与数学计算相关的库,包含了很多数学计算函数,这里介绍几个常用的库函数
math.sqrt(9) #math.sqrt()该函数用于计算平方根,参数为数字,返回数字的平方根
math.pow(2,3) #math.pow()该函数用于计算幂,参数为两个数字,第一个参数为底数,第二个参数为指数,返回第一个参数的第二个参数次方
math.log(2) #math.log()该函数用于计算对数,参数为数字,返回该数字的自然对数
math.exp(2) #math.exp()该函数用于计算指数,参数为数字,返回e的该数字次方
math.sin(math.pi/2) #math.sin()该函数用于计算正弦值,参数为角度,返回角度的正弦值
math.cos(math.pi/2) #math.cos()该函数用于计算余弦值,参数为角度,返回角度的余弦值
math.tan(math.pi/4) #math.tan()该函数用于计算正切值,参数为角度,返回角度的正切值
再比如,numpy库,常用于做数据处理分析:
import numpy #导入numpy库
numpy.array([1,2,3,4,5]) #创建一个一维数组
numpy.array([[1,2,3],[4,5,6]]) #创建一个二维数组
numpy.ones((3,4)) #创建一个3行4列的全1数组
numpy.zeros((2,3)) #创建一个2行3列的全0数组
numpy.empty((2,3)) #创建一个2行3列的未初始化数组
有些人可能会觉得numpy写起来有些复杂,调用库函数时需要反复去写这个库名称,所以我们还可以给它重新起一个名字,换一种简洁的命名,以便书写。
import numpy as np #导入numpy库,并简写为np
np.array([1,2,3,4,5])
np.array([[1,2,3],[4,5,6]])
np.ones((3,4))
np.zeros((2,3))
np.empty((2,3))
好了,关于库函数的内容,我们就暂时介绍到这里,库函数的内容太多了,这里根本讲不完,在后面的文章会逐渐补充讲解各种Python的第三方库。
顺带一提,Python海量的第三方库无疑是Python的一大特色,安装灵活快捷,易于扩展定制,以及丰富多样的功能,大大提高了Python开发的高效性和功能的全面性。
内置函数:
内置函数是编程语言自带的函数,不需要额外导入库就可以直接使用。它们是语言核心的一部分,通常提供了一些最基本、最常用的功能,这些功能在各种编程任务中频繁出现。
可能大家对内置函数这个概念并不很清楚,但是它却很常见。
我们在Python中最常用的 print() 和 input() 就属于一种内置函数,还有最基本的那些格式转化函数,序列操作相关的函数……
内置函数很简单,没有什么特点,都是很常用的一些函数,这里就直接简单带过了。
自定义函数:
好了,上面写了那么多,终于来到了我们本篇文章的重点内容——自定义函数
先来讲一讲自定义函数的定义:
自定义函数是用户根据自己的需求编写的函数。它是一段被命名的、可重复使用的代码块,用于完成特定的任务。通过定义自定义函数,程序员可以将复杂的程序逻辑分解为更小、更易于管理的部分,提高代码的可读性和可维护性。
我们平时说的函数,其实大多数也就是在讲自定义函数
接下来就详细讲解一下自定义函数是如何被定义以及调用的。
二、函数的定义和调用
在Python中,我们可以使用def关键字来定义一个函数,其具体语法如下:
def 函数名():
函数执行代码块
这里举个例子,定义一个比较简单的函数:
def hello():
print("Hello, World!")
从 def 开始函数定义,紧接着是函数名,括号内部为函数的参数,内部为函数的具体功能实现代码
定义完这个函数之后,函数是不会自动执行的,需要我们调用才可以执行:
def hello():
print("Hello, World!")
hello()
只需要 函数名() 就可以调用执行该函数功能了,输出结果就会是Hello,World!
这样一行代码可能看不出来函数的功能,别着急,这里只是举了一个最简单的定义调用的例子,后面看我慢慢讲解,函数可是Python的核心语法之一,在一个项目中,绝对是不可缺少的部分。
三、函数的参数
在前面我们应该也提到过关于参数的概念,那参数在函数中又有什么实际的应用呢
位置参数
def subtract(a, b):
return a - b
位置参数是最常见的参数类型。在定义函数时,参数的顺序很重要。例如:
当调用 函数subtract(5, 3)
时,5
会被赋值给 a
,3
会被赋值给 b
,函数返回 2
。参数按照定义的顺序传递,改变顺序会得到不同的结果,如subtract(3, 5)
会返回-2
。
关键字参数
def multiply(a, b):
return a * b
a = multiply(2, 3)
print(a)
# Output: 6
- 关键字参数允许在调用函数时通过参数名来指定参数的值,这样可以不按照参数定义的顺序传递参数。例如:
- 可以用
multiply(b = 2, a = 3)
来调用这个函数,此时a
的值为2,b
的值为3
,函数返回6。
默认参数
def divide(a, b = 1):
return a / b
print(divide(2))
#输出结果为 2.0
- 在函数定义时可以为参数指定默认值。例如:
- 当调用
divide(2)
时,由于b
有默认值1
,所以函数会计算2/1
并返回2。也可以用divide(4, 2)
来调用,此时b
的值为2
,函数返回2
。
可变长度参数(*args 和**kwargs)
def print_args(*args):
for arg in args:
print(arg)
print_args(1, 2, 3, 4, 5)
#输出结果为:
#1
#2
#3
#4
#5
def print_kwargs(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_kwargs(name="John", age=30, city="New York")
#输出结果为:
# name: John
# age: 30
# city: New York
*args
:用于接收任意数量的非关键字参数。在函数内部,args
是一个元组。例如:- 可以用
print_args(1, 2, 3)
来调用,函数会依次打印出1
、2
和3
。 **kwargs
:用于接收任意数量的关键字参数。在函数内部,kwargs
是一个字典。例如:- 可以用
print_kwargs(name="Alice", age = 25)
来调用,函数会打印name: Alice
和age: 25
。
参数组合
def combined_function(a, b, *args, c = 1, **kwargs):
print(f"a: {a}, b: {b}, args: {args}, c: {c}, kwargs: {kwargs}")
combined_function(1, 2, 3, 4, 5, c = 6, d = 7, e = 8)
#输出结果为:a: 1, b: 2, args: (3, 4, 5), c: 6, kwargs: {'d': 7, 'e': 8}
- 在一个函数中可以同时使用多种参数类型。但是参数的顺序有一定要求:位置参数、*args、关键字参数、**kwargs。
四、函数的返回值
可以看到,上面举得几个定义的例子中,有几个函数中出现了一个叫做 return 的关键字
return 用于给函数返回值
对于一些简单的函数来说,一个函数都是返回单个值的,例如这样:
def square(x):
return x * x
a = square(5)
print(a)
或者还可以返回一些可迭代对象,例如列表、集合、字典等:
返回值为列表的示例:
def get_even_numbers(start, end):
"""
返回给定区间内(包含起始和结束值)的所有偶数组成的列表
"""
result_list = []
for num in range(start, end + 1):
if num % 2 == 0:
result_list.append(num)
return result_list
# 调用示例
even_numbers = get_even_numbers(1, 10)
print(even_numbers)
输出结果为:
返回值为集合的示例:
def remove_duplicate_words(text):
"""
接收一段文本,将其中的单词提取出来,去除重复单词后以集合形式返回
"""
words = text.split()
unique_words = set(words)
return unique_words
# 调用示例
text = "hello world hello python world"
unique_word_set = remove_duplicate_words(text)
print(unique_word_set)
输出结果为:
返回值为字典的示例:
def count_characters(text):
"""
统计输入文本中每个字符出现的次数,并以字典形式返回,字典的键为字符,值为对应字符出现的次数
"""
char_count_dict = {}
for char in text:
if char in char_count_dict:
char_count_dict[char] += 1
else:
char_count_dict[char] = 1
return char_count_dict
# 调用示例
input_text = "hello"
char_count_result = count_characters(input_text)
print(char_count_result)
输出结果为:
当然,在Python中,我们也可以一次返回多个值,例如:
def get_max_min(num_list):
if num_list: # 判断列表是否为空
max_num = min_num = num_list[0] # 初始化最大值和最小值
for num in num_list[1:]: # 遍历列表
if num > max_num: # 如果当前元素大于最大值,则更新最大值
max_num = num
if num < min_num: # 如果当前元素小于最小值,则更新最小值
min_num = num
return max_num, min_num # 返回最大值和最小值
return None, None # 如果列表为空,则返回None
# 调用函数
nums = [12, 5, 18, 3]
max_num, min_num = get_max_min(nums)
print(f"最大值是: {max_num}, 最小值是: {min_num}")
五、函数的嵌套调用
- 函数嵌套调用是指在一个函数的定义体内调用另一个函数。例如,有函数
A
和函数B
,在函数A
的代码块中可以调用函数B
来完成一些子任务。
这里来做一个简单示例:
我们定义一个函数 add
用于计算两数之和,再定义一个函数 calculate
,在 calculate
函数中调用 add
函数。
def add(a, b):
return a + b #定义一个函数add,用于求两个数的和
def calculate():
num1 = 3
num2 = 5
result = add(num1, num2) #调用add函数,并传入两个数作为参数
print(f"The sum of {num1} and {num2} is {result}") #打印结果
calculate()
#输出:The sum of 3 and 5 is 8
在这个例子中,calculate
函数内部调用了add
函数来计算3
和5
的和,并将结果打印出来。
当然,在一些复杂的项目中,我们可能不止需要一次嵌套调用,可能需要多个函数来实现多层嵌套
例如:
计算多层嵌套中的数学表达式:
def outer_math(x):
def middle_math(y):
def inner_math(z):
return x + y + z
return inner_math
return middle_math
# 这里的outer_math函数返回了一个函数middle_math,这个函数接收一个参数y,返回一个函数inner_math,这个函数接收一个参数z,并返回z+y+x的和
# 调用函数
result_function = outer_math(2)
mid_result_function = result_function(3)
final_result = mid_result_function(4)
print(final_result)
# 输出:9
基于多层嵌套函数处理字符串:
def outer_text_operation(text):
def middle_text_operation(func):
def inner_text_operation():
processed_text = func(text)
return processed_text.upper()
return inner_text_operation
return middle_text_operation
# 这里的outer_text_operation函数接收一个参数text,返回一个函数,这个函数接收一个参数func,返回一个函数,这个函数调用func函数,并将结果转换为大写。
# 定义一个函数,用于添加前缀
def add_prefix(text):
return "Prefix_" + text
# 调用函数
operation_chain = outer_text_operation("example")# 调用outer_text_operation函数,传入参数"example"
mid_operation = operation_chain(add_prefix)# 调用outer_text_operation函数返回的函数,传入参数add_prefix
final_text = mid_operation()# 调用mid_operation函数,返回结果
print(final_text)# 输出"Prefix_EXAMPLE"
可以通过我给出的这两个代码示例,结合注释去理解,体会一下多层嵌套函数的关系,以及其中运行的逻辑,相信看代码去理解,比我直白的叙述会更利于你对其逻辑的掌握。
六、递归
在数学中,我们可能也听到过递归这个名词,在Python的函数中也有这么一个叫做递归的高级用法
- 递归是指在函数的定义中使用函数自身的方法。一个典型的递归函数包括两个部分:基线条件(base case)和递归条件(recursive case)。
- 基线条件是用于终止递归的条件,当满足这个条件时,函数不再调用自身,而是直接返回一个结果。递归条件则是函数调用自身的部分,用于将问题分解为更小的子问题。
一个简单的例子,计算阶乘:
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
#在这个函数中,基线条件是n等于0,这时返回1;否则,递归调用factorial(n-1)并乘以n。
n = int(input("Enter a number: "))
print("Factorial of", n, "is", factorial(n))
我们常见到的斐波那契数列:
- 斐波那契数列的定义是:F(n) = F(n-1) + F(n-2),其中F(0)=0,F(1)=1。
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
n = int(input("Enter the number of terms: "))
print("Fibonacci Series:", fibonacci(n),end=" ")
注意!!!
递归函数一定要有终止条件,否则会导致无限递归,使程序最终崩溃。另外,递归调用的深度如果过深,可能会导致栈溢出(stack overflow),因为每次函数调用都会在栈中占用一定的空间来保存函数的状态等信息。在实际应用中,对于一些可以用递归解决的问题,有时也需要考虑使用迭代等其他方式来优化,以避免这些潜在的问题。
结语
好了,今天关于函数的讲解就到这里了,内容很多,大家慢慢理解消化~
函数确实是Python中很重要的一个语法,不管是考试,或者是做一些项目,都是不可避免的一部分,所以一定要熟练掌握,理解其逻辑,还是一样,如果有不理解的地方,可以发在评论区,我们一起交流~
创作不易,能否给个三连支持一下~
寒假期间,更新加速,后续的文章内容会加快更新的~