python函数详解

一、 函数概要

Python中,函数是一段组织好的、可重用的代码,用于执行一个特定的任务。

函数是一种编程结构,它允许你为代码块定义一个名称(函数名),并通过该名称在程序中的其他位置调用该代码块。使用函数的好处包括代码重用、模块化编程和可读性增强。


1. 函数定义规则:使用def关键字来定义函数
函数名:函数名应遵循Python的命名规则,通常是小写字母和下划线的组合(如my_function)。避免使用Python的内置函数名或保留字作为函数名。
参数:函数可以没有参数,也可以有多个参数,可设置可变参:*args**kwargs。参数列表用圆括号括起来,并在函数体内部使用。
返回值:函数可以使用return语句返回一个值。如果函数没有return语句或return后面没有跟值,那么函数将返回None。
缩进:在函数定义中,函数体应该相对于def语句缩进。
文档字符串:非必需,但建议为函数提供文档字符串来解释函数的功能、参数和返回值。使用函数名.__doc__访问。

2. 特殊定义方式函数:匿名函数
在Python中,匿名函数(也被称为lambda函数)是一种非常简短、一次性的函数,主要用于定义一个简单的函数对象。它们可以用在任何需要函数作为参数的地方,如排序函数sorted()的key参数,或者map()、filter()等内置函数。
Lambda函数的基本语法:lambda arguments: expressionarguments是参数列表(与常规函数定义中的参数列表类似,但不允许使用默认参数、可变参数列表或关键字参数),而expression是一个单个的表达式,其值就是该lambda函数的返回值。

3. 函数的注意事项
避免全局变量:尽量避免在函数内部使用全局变量,因为这可能导致代码难以理解和维护。如果需要在函数内部修改全局变量的值,可以使用global关键字,但通常最好避免这样做。关注变量的作用域,本文做了关于递归函数,高阶函数,闭包函数等案例。
函数的副作用:函数应该尽可能地只执行其声明的任务,并避免产生意外的副作用(如修改全局变量的值或更改调用它的函数的状态)。
函数的粒度:函数的粒度应该适中。如果函数太长或太复杂,考虑将其拆分成更小的函数。相反,如果函数太短或只做了一件事,考虑是否可以将它与其他相关功能合并。
错误处理:函数应该能够处理可能出现的错误和异常情况。可以使用try-except块来捕获和处理异常。
测试:编写函数后,应该编写测试用例来验证函数的正确性和健壮性。这有助于确保函数在所有预期的情况下都能按预期工作。


二、函数应用示例

以下是一些经典的Python函数案例,它们涵盖了函数的基本用法、参数传递、返回值以及更高级的概念,如默认参数、可变参数、递归函数等。

2.1 简单的加法函数

提示:这里可以添加技术名词解释

def add_numbers(a, b):  
    """这个函数接受两个参数并返回它们的和"""  
    return a + b  
  
# 调用函数  
result = add_numbers(3, 4)  
print(result)  # 输出: 7

注意:定义函数,函数的返回值是函数执行完成后返回给调用者的结果。这个返回值可以是任何数据类型,包括整数、浮点数、字符串、列表、元组、字典、集合、自定义对象,或者在没有明确返回值时默认为None。在函数内部,你可以使用return语句来指定返回值。当return语句被执行时,函数会立即结束并返回指定的值。如果没有return语句,函数会在执行完所有代码后返回None。
函数调用是程序执行函数代码的过程。当你使用函数名并后跟括号(可能包含参数)时,你就调用了该函数。调用函数会触发函数内部的代码执行。

2.2 带默认参数的函数

有默认参数的形参,在函数调用时可以传参也可以不传;没有默认参数的形参,调用时必须传参

def greet(name, greeting='Hello!'):  
    """这个函数接受一个参数name和一个默认参数greeting,并返回问候语"""  
    return f"{greeting}, {name}!"  
  
# 调用函数,只传递一个参数  
print(greet('World'))  # 输出: Hello, World!  
  
# 调用函数,传递两个参数  
print(greet('Python', 'Welcome to'))  # 输出: Welcome to, Python!

注意:三引号字符串为函数文档字符串,用于解释函数的功能、参数和返回值。同时,这个字符串也是可以被访问的。可以使用内置的__doc__属性来访问和打印出这些文档字符串。

# 访问函数的文档字符串  
doc_string = greet.__doc__  
# 打印出文档字符串  
print(doc_string)

2.3 可变参数函数

*args:用于收集非关键字参数(位置参数),这些参数在函数内部被收集为一个元组。args不是固定名,是习惯用名

def sum_numbers(*args):  
    """这个函数接受任意数量的参数并返回它们的和"""  
    return sum(args)  
  
# 调用函数,传递不同数量的参数  
print(sum_numbers(1, 2, 3))  # 输出: 6  
print(sum_numbers(4, 5, 6, 7))  # 输出: 22

2.4 关键字参数函数

**kwargs:用于收集关键字参数,这些参数在函数内部被收集为一个字典。

def display_info(**kwargs):  
    """这个函数接受任意数量的关键字参数并打印它们"""  
    for key, value in kwargs.items():  
        print(f"{key}: {value}")  
  
# 调用函数,传递关键字参数  
display_info(name='Alice', age=30, city='New York')  
# 输出:  
# name: Alice  
# age: 30  
# city: New York

注:可变参数一起使用如下:

def my_function(*args, **kwargs):  
    print("Positional arguments:")  
    for arg in args:  
        print(arg)  
  
    print("\nKeyword arguments:")  
    for key, value in kwargs.items():  
        print(f"{key}: {value}")  
  
# 调用函数,传入位置参数和关键字参数  
my_function(1, 2, 3, name="Alice", age=30)
# 1, 2, 3被args接收,变成元组格式。
# name="Alice", age=30,被kwargs接收,变成键值对格式,字典。

2.5 递归函数

n的阶乘计算

def factorial(n):  
    """这个函数使用递归计算n的阶乘"""  
    if n == 0 or n == 1:  
        return 1  
    else:  
        return n * factorial(n-1)  
  
# 调用函数  
print(factorial(5))  # 输出: 120

注:累加也可以递归:else:return n+f(n-1)

def accumulate(n):
    """这个函数使用递归计算n的阶乘"""
    if n == 1:
        return 1
    else:
        return n + accumulate(n - 1)
 # 调用函数
print(accumulate(100))  # 输出: 5050

2.6 函数作为参数传递(高阶函数)

把函数作为参数,作为返回值使用,那么整个函数就不止一阶,可二阶,三阶也

def apply_func(func, arg):  
    """这个函数接受一个函数和一个参数,并调用该函数"""  
    return func(arg)  
  
def square(x):  
    """这个函数返回x的平方"""  
    return x ** 2  
  
# 调用函数,传递函数作为参数  
print(apply_func(square, 5))  # 输出: 25

注:python中一切皆对象,所以返回值可以是整数、浮点数、字符串、列表、元组、字典、集合、自定义对象,函数对象也不例外。同理,参数也可以是函数对象。

2.7 闭包函数(带有内部状态的函数)

闭包函数:通过定义一个外部函数,并在该外部函数中定义一个内部函数来实现闭包;内部函数可以通过引用外部函数的局部变量(包括参数)来形成闭包;这些局部变量在外部函数返回内部函数后仍然被内部函数所引用,而不会被Python的垃圾回收机制回收。

def counter():  
    count = 0  
    def increment():  
        nonlocal count  
        count += 1  
        return count  
    return increment  
  
# 创建一个计数器函数  
counter_func = counter()  
  
# 调用计数器函数  
print(counter_func())  # 输出: 1  
print(counter_func())  # 输出: 2  
print(counter_func())  # 输出: 3
print(counter_func())  # 输出: 4
print(counter_func())  # 输出: 5
print(counter_func())  # 输出: 6

注:nonlocal关键字用于在嵌套函数中声明一个变量,该变量引用最近的上层(非全局)作用域中的变量,而不是在全局作用域中查找。
在内部函数increment中,我们使用nonlocal关键字声明了count 。这意味着当我们在这个函数内部引用或修改count 时,我们实际上是在引用或修改counter中的count,而不是在全局作用域中查找或创建一个新的变量。
所以,调用一次counter_func()完成,就是完成一次变量counter_func 的修改,多次调用,就是多次修改。

2.8 装饰器函数

在Python中,装饰器函数是一个接受函数作为参数并返回一个新函数的高阶函数。装饰器函数的主要用途是在不修改原函数代码的情况下,给函数增加额外的功能,如日志记录、性能测量、权限检查等。详细参考python装饰器博客。

def my_decorator(func):  
    def wrapper(*args, **kwargs):  
        print("Something is happening before the funct is called.这里你可以去检验参数合不合格,比如用户名有没有注册,手机号码是否合法等等")  
        result = func(*args, **kwargs)  
        print("Something is happening after the function is called.")  
        return result  
    return wrapper  
  
@my_decorator  
def say_hello(name):  
    print(f"Hello, {name}!")  
  
# 调用函数  
say_hello("World")

注:示例中,my_decorator是一个装饰器函数,它接受一个函数func作为参数,并定义了一个新的函数wrapperwrapper函数在调用原函数func之前和之后分别执行了一些额外的操作(在这个例子中是打印一些文本)。然后,my_decorator返回wrapper函数。
注意是定义函数时添加装饰。
使用@my_decorator语法糖,我们将装饰器函数my_decorator应用到了say_hello函数上。这样,当我们调用say_hello("World")时,实际上调用的是wrapper函数,而不是原始的say_hello函数。但是,从代码的角度看,我们仍然像是在直接调用say_hello函数一样。

2.8 匿名函数

计算两个数的和:

add = lambda x, y: x + y  
print(add(3, 4))  # 输出:7

对列表中的每个元素乘以2:

numbers = [1, 2, 3, 4, 5]  
doubled = map(lambda x: x * 2, numbers)  
print(list(doubled))  # 输出:[2, 4, 6, 8, 10]

过滤出列表中的偶数:

numbers = [1, 2, 3, 4, 5]  
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))  
print(even_numbers)  # 输出:[2, 4]

对列表进行排序(根据字符串长度):

words = ["apple", "banana", "cherry", "date"]  
sorted_words = sorted(words, key=lambda w: len(w))  
print(sorted_words)  # 输出:['date', 'apple', 'cherry', 'banana']

三、小结

  1. 函数定义,调用;参数,可变参数,关键字参数解析。
  2. 函数的高阶应用:递归,高阶函数,闭包,装饰器。
  3. 装饰器函数在Python中非常有用,特别是在需要为多个函数添加相同功能时。通过使用装饰器,我们可以避免重复编写相同的代码,并使得代码更加模块化和可维护。
  4. 匿名函数短小精悍,非常好用。但它们并不适合定义复杂的函数或包含多个语句的函数。对于更复杂的逻辑,通常应该使用常规的def语句来定义函数。

关注,收藏,多多浏览,经常实践,快速成长吧!

  • 35
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柏常青

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值