前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【python篇】关于函数当中的那些事,轻松拿捏

【python篇】关于函数当中的那些事,轻松拿捏

作者头像
用户11286421
发布2024-09-23 20:14:13
920
发布2024-09-23 20:14:13
举报
文章被收录于专栏:学习

函数的基础

函数的定义:使用 def 关键字定义一个函数,以及函数的基本结构,包括函数名、参数列表、函数体和返回值。

代码语言:javascript
复制
# 定义一个简单的函数,它接受两个参数并返回它们的和
def add_numbers(a, b):
    return a + b

# 调用函数并打印结果
result = add_numbers(3, 5)
print(result)  # 输出: 8

函数的参数

函数当中有形式参数和实际参数,分别简称形参和实参是非常重要的概念 下面举行一些例子来详细说明

1.位置参数(Positional Arguments)

代码语言:javascript
复制
def greet(name, age):
    print(f"Hello, my name is {name} and I am {age} years old.")

# 调用函数
greet("Alice", 25)
#	Hello, my name is Alice and I am 25 years old.

2. 关键字参数(Keyword Arguments)

代码语言:javascript
复制
def greet(name, age):
    print(f"Hello, my name is {name} and I am {age} years old.")

# 使用关键字参数调用函数
greet(age=25, name="Bob")
#	Hello, my name is Bob and I am 25 years old.

3. 默认参数(Default Arguments)

代码语言:javascript
复制
def greet(name="John", age=30):
    print(f"Hello, my name is {name} and I am {age} years old.")

# 调用函数,使用默认参数
greet()
greet("Alice")		#函数实参有默认值即使用默认值
greet("Alice", 25)
#	Hello, my name is John and I am 30 years old.
#	Hello, my name is Alice and I am 30 years old.
#	Hello, my name is Alice and I am 25 years old.

4. 可变长度参数 *args

args 用于接受任意数量的位置参数。它会将传入的多个参数打包成一个元组。*

代码语言:javascript
复制
def print_numbers(*args):
    for num in args:
        print(num)

# 传递多个实参
print_numbers(1, 2, 3, 4, 5)

输出:

代码语言:javascript
复制
1
2
3
4
5

5. 可变长度关键字参数 **kwargs

kwargs 用于接受任意数量的关键字参数。它会将传入的多个关键字参数打包成一个字典

代码语言:javascript
复制
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

# 传递多个关键字参数
print_info(name="Alice", age=25, city="New York")

输出:

代码语言:javascript
复制
name: Alice
age: 25
city: New York

6. 强制关键字参数(Keyword-Only Arguments)

在 Python 3 中,可以强制要求某些参数必须通过关键字来传递,而不能通过位置。

代码语言:javascript
复制
def describe_pet(pet_name, *, pet_type="dog"):
    print(f"I have a {pet_type} named {pet_name}.")

# 通过关键字传递参数
describe_pet("Max", pet_type="cat")

# 不传递 pet_type,使用默认值
describe_pet("Buddy")

输出:

代码语言:javascript
复制
I have a cat named Max.
I have a dog named Buddy.

函数的作用域

局部变量和全局变量:

代码语言:javascript
复制
x = 10  # 这是一个全局变量

def example():
    x = 5  # 这是一个局部变量
    print(f"Inside the function, x = {x}")

example()  # 输出: Inside the function, x = 5
print(f"Outside the function, x = {x}")  # 输出: Outside the function, x = 10

#在 example 函数内部定义的 x 是局部变量,它只在函数内部有效,不会影响全局变量 x。因此函数内外的 x 值不同。

global关键字:

global 的定义与作用: 通常情况下,如果你在函数内部定义一个变量,该变量是局部变量,仅在函数内部可见。如果在函数内部需要修改全局变量,必须使用 global 关键字进行声明。 作用: 声明全局变量:global 允许在局部作用域内声明并修改外部作用域(全局作用域)中的变量。 防止局部变量覆盖全局变量:如果没有 global 声明,当你在函数内部赋值时,Python 会默认创建一个新的局部变量,而不是修改全局变量。

代码语言:javascript
复制
x = 10  # 全局变量

def modify_global():
    global x
    x = 20  # 修改全局变量
    print(f"Inside the function, x = {x}")

modify_global()  # 输出: Inside the function, x = 20
print(f"Outside the function, x = {x}")  # 输出: Outside the function, x = 20

#使用 global 关键字可以在函数内部修改全局变量。这个例子中,函数内部将全局变量 x 修改为 20,所以函数外的 x 也被改变了。

global 的常见用途 1.计数器或全局状态的维护:在程序中,有时需要一个全局计数器或状态变量,global 可以帮助修改它们的值。 2.全局配置或设置的更新:如果程序中有全局的设置或配置变量,在需要修改这些配置时,可以使用 global。 3.跨函数共享数据:有时候多个函数需要共享某些数据,可以通过 global 声明全局变量来实现。 global 的局限性 尽管 global 可以让函数内部修改全局变量,但在大型程序中滥用全局变量可能会带来以下问题: 1.代码可读性降低:过多的全局变量会使代码难以维护,难以理解哪些函数依赖于哪些全局变量。 2.调试困难:由于全局变量可以在多个地方被修改,跟踪它的值变化可能变得复杂。 模块化难度增加:全局变量往往与模块化设计相冲突,影响代码的复用性和可测试性。

因此,尽量减少使用全局变量。更好的方法是使用函数参数、返回值或类的属性来管理状态。

nonlocal关键字:

nonlocal定义与作用: nonlocal 关键字用于声明一个变量是来自于外层的非全局作用域(通常是闭包中的外部函数)。nonlocal 允许在嵌套函数中修改外层函数中的局部变量,而不是全局变量或当前局部变量。 作用 修改外层函数的局部变量:nonlocal 可以让嵌套函数中的变量绑定到外层函数的局部变量上,避免创建新的局部变量。 闭包的实现:在闭包中,nonlocal 允许嵌套函数修改封闭函数中的变量,从而实现更复杂的功能。

代码语言:javascript
复制
def outer_function():
    x = 10
    
    def inner_function():
        nonlocal x
        x = 20
        print(f"Inside the inner function, x = {x}")
    
    inner_function()
    print(f"Inside the outer function, x = {x}")

outer_function()

#nonlocal 用于在嵌套函数中引用外层函数的变量,而不是全局变量。在这个例子中,inner_function 修改了 outer_function 中的 x 值。

nonlocal 常见用途 闭包的实现:nonlocal 常用于闭包中修改外层函数的局部变量,闭包可以记住外层函数的状态,而 nonlocal 可以允许修改这些状态。 nonlocal 的局限性 nonlocal 只能用于嵌套函数中,且仅能修改直接外层函数中的局部变量。它不能用于访问全局变量或更高层的嵌套作用域。 如果没有外层函数中的局部变量,使用 nonlocal 会导致 SyntaxError 错误。

nonlocal 和 global 的区别

global 用于声明一个变量是全局作用域中的变量,允许在函数内部修改全局变量。

nonlocal 用于声明一个变量是外层非全局作用域中的变量,允许在嵌套函数中修改外层函数的局部变量。

函数的进阶

1.函数嵌套(Nested Functions)

Python 支持在一个函数内部定义另一个函数,这被称为嵌套函数。内部函数可以访问外部函数的变量(闭包的概念)。

代码语言:javascript
复制
def outer_function(text):
    def inner_function():
        print(text)  # 内部函数可以访问外部函数的变量
    inner_function()

# 调用外部函数
outer_function("Hello from outer function!")
# Hello from outer function!

2.闭包(Closures)

闭包是指内部函数记住并访问它们被定义时的外部作用域的变量,即使外部函数已经返回了。 闭包的三个条件 1.必须有一个嵌套函数:闭包必须包含一个内嵌函数。 2.内嵌函数必须引用外部函数中的变量:这个引用的变量通常是外层函数中的局部变量。 3.外层函数必须返回内嵌函数:返回的内嵌函数可以在外部被调用,且能够访问外层函数的变量。

代码语言:javascript
复制
def outer_function(text):
    def inner_function():
        print(text)
    return inner_function

# 调用外部函数,并将返回的函数赋值给变量
my_closure = outer_function("Hello, World!")

# 调用闭包函数
my_closure()  # 输出: Hello, World!

闭包的应用场景 闭包通常用于需要保持某些状态的场景,特别是当你希望将某些状态与一个函数关联,而又不希望使用全局变量时。

示例:计数器

代码语言:javascript
复制
def make_counter():
    count = 0  # 闭包中的变量

    def counter():
        nonlocal count
        count += 1
        return count
    
    return counter

# 创建一个计数器实例
counter_a = make_counter()

print(counter_a())  # 输出: 1
print(counter_a())  # 输出: 2
print(counter_a())  # 输出: 3

# 创建另一个计数器实例
counter_b = make_counter()

print(counter_b())  # 输出: 1
print(counter_b())  # 输出: 2
# make_counter 函数创建了一个闭包,其中的变量 count 是内嵌函数 counter 的状态。
# 每次调用 counter() 时,count 都会增加1,并返回当前的计数。
# 你可以创建多个计数器,每个计数器都有独立的状态,不会互相影响。

闭包的核心:在函数外部可以访问函数内部的局部变量。这使得闭包在保持状态、实现工厂函数(如上面的计数器)、以及创建装饰器时非常有用。

3.装饰器(Decorator)

装饰器的基本概念

一个简单的装饰器结构通常是这样的: 定义一个装饰器函数,它接收一个函数作为参数。 在装饰器函数内部定义一个嵌套函数,这个嵌套函数将在原函数调用时被调用。 嵌套函数可以在执行原函数前后添加新的功能。 装饰器返回嵌套函数,从而替代原函数。

示例:

代码语言:javascript
复制
def simple_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@simple_decorator
def say_hello():
    print("Hello!")

# 调用装饰过的函数
say_hello()

解释: simple_decorator 是装饰器函数,它接收一个函数 func 作为参数。 wrapper 是在装饰器内部定义的嵌套函数,它在调用 func() 之前和之后分别打印一条消息。 @simple_decorator 语法糖用来应用装饰器,它等价于 say_hello = simple_decorator(say_hello)。 当你调用 say_hello() 时,实际执行的是 wrapper 函数,它先打印“Something is happening before the function is called.”,然后调用 say_hello 函数,最后打印“Something is happening after the function is called.”。

装饰器处理带参数的函数

如果被装饰的函数带有参数,装饰器也需要处理这些参数。我们可以修改 wrapper 函数来接受任意数量的参数和关键字参数。

代码语言:javascript
复制
def decorator_with_arguments(func):
    def wrapper(*args, **kwargs):
        print(f"Arguments were: {args}, {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@decorator_with_arguments
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

# 调用装饰过的函数
greet("Alice")
greet("Bob", greeting="Good morning")

解释: wrapper(*args, **kwargs) 能够接收并传递任意数量的位置参数和关键字参数。 当你调用 greet(“Alice”) 或 greet(“Bob”, greeting=“Good morning”) 时,装饰器都会先打印函数的参数,然后执行原始函数。

4.lambda表达式

lambda 表达式,也称为匿名函数,是Python中一种简洁的方式来创建简单的函数。与使用 def 关键字定义的常规函数不同,lambda 表达式可以在一行中定义,并且它没有函数名。因此,它常用于需要快速定义简单函数的场景,特别是当你只打算使用一次的函数。 lambda 表达式的基本语法 lambda 表达式的基本语法如下:

代码语言:javascript
复制
lambda 参数1, 参数2, ... : 表达式

基本例子

代码语言:javascript
复制
# 一个简单的lambda函数,它将两个参数相加
add = lambda x, y: x + y

# 调用这个lambda函数
result = add(3, 5)
print(result)  # 输出: 8

#lambda x, y: x + y 定义了一个匿名函数,它接收两个参数 x 和 y,并返回它们的和。add(3, 5) 调用了这个 lambda 函数,传入 3 和 5,得到结果 8。

lambda 表达式的常见使用场景 虽然 lambda 表达式可以像常规函数一样使用,但它通常用于需要简单函数的场合,尤其是与高阶函数(如 map, filter, reduce 等)配合使用时。

lambda 表达式的限制 lambda 表达式只能包含一个表达式,不能包含多个语句。 由于 lambda 是匿名的,它没有函数名,因此在调试时可能会不太方便。

5.生成器

生成器的基本概念 生成器函数与普通函数的不同之处在于它使用了yield关键字而不是return。每次调用yield时,生成器会返回一个值,并且暂停执行,直到再次被调用时从暂停的地方继续执行。

代码语言:javascript
复制
def simple_generator():
    yield 1
    yield 2
    yield 3

# 使用生成器
gen = simple_generator()

print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2
print(next(gen))  # 输出: 3

解释: simple_generator 是一个生成器函数,使用 yield 依次返回 1, 2, 3。 当你调用 next(gen) 时,生成器会从上一次暂停的地方继续执行,直到遇到下一个 yield 或结束。 如果生成器已经耗尽所有的值,再调用 next() 会引发 StopIteration 异常。

生成器处理斐波那契数列
代码语言:javascript
复制
def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for num in fibonacci(10):
    print(num)

总结: 生成器是Python中一种高效的工具,能够处理需要延迟计算、节省内存的场景。无论是通过生成器函数还是生成器表达式,它们都提供了一种优雅的方式来处理大量数据,避免了不必要的内存消耗。生成器广泛应用于数据流处理、大文件读取、复杂序列生成等任务中,是Python编程中非常重要的一个概念。

高阶函数

高阶函数(Higher-Order Function)是Python中一个非常重要的概念**,它指的是可以接收一个或多个函数作为参数,或返回一个函数作为结果的函数。**高阶函数是函数式编程的核心思想之一,能够让代码更加简洁和灵活。 高阶函数的特点 接收函数作为参数:高阶函数可以将其他函数作为输入参数传递。 返回一个函数:高阶函数可以将函数作为输出返回。

常见的高阶函数 Python 中有几个常见的内置高阶函数,如 map、filter、reduce、sorted 等。 1. map 函数 map 函数将一个函数应用到一个可迭代对象的每个元素上,并返回一个新的迭代器。

代码语言:javascript
复制
# 定义一个简单的函数,将数字平方
def square(x):
    return x ** 2

# 使用 map 函数将 square 应用于每个列表元素
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(square, numbers))

print(squared_numbers)  # 输出: [1, 4, 9, 16, 25]

2. filter 函数 filter 函数用于过滤可迭代对象中的元素,返回所有使给定函数返回 True 的元素。

代码语言:javascript
复制
# 定义一个函数,判断一个数是否是偶数
def is_even(x):
    return x % 2 == 0

# 使用 filter 函数过滤出偶数
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = list(filter(is_even, numbers))

print(even_numbers)  # 输出: [2, 4, 6]

3. reduce 函数 reduce 函数将一个二元函数累积地应用到可迭代对象的元素上,从而将可迭代对象简化为单个值。reduce 函数在 functools 模块中。

代码语言:javascript
复制
from functools import reduce

# 定义一个函数,将两个数相乘
def multiply(x, y):
    return x * y

# 使用 reduce 函数计算列表中所有元素的乘积
numbers = [1, 2, 3, 4, 5]
product = reduce(multiply, numbers)

print(product)  # 输出: 120

4. sorted 函数与 key 参数 sorted 函数可以根据指定的排序规则对可迭代对象进行排序。key 参数是一个高阶函数,用于指定排序的依据。

代码语言:javascript
复制
# 对一组单词按其长度进行排序
words = ['apple', 'banana', 'cherry', 'date']

# 使用 sorted 函数和 len 函数作为 key
sorted_words = sorted(words, key=len)

print(sorted_words)  # 输出: ['date', 'apple', 'banana', 'cherry']

实际应用

  1. 函数作为参数传递 高阶函数可以将函数作为参数传递给其他函数,使得代码更加灵活。
代码语言:javascript
复制
def apply_function(func, value):
    return func(value)

# 传递不同的函数进行计算
print(apply_function(square, 5))  # 输出: 25
print(apply_function(is_even, 5))  # 输出: False
#apply_function 是一个高阶函数,它接收另一个函数 func 和一个值 value,然后将 func 应用于 value。
  1. 函数作为返回值 高阶函数可以返回另一个函数,这使得可以创建工厂函数或封装某些逻辑。
代码语言:javascript
复制
def make_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

# 创建一个乘以3的函数
times3 = make_multiplier(3)
print(times3(10))  # 输出: 30

# 创建一个乘以5的函数
times5 = make_multiplier(5)
print(times5(10))  # 输出: 50
#make_multiplier 是一个高阶函数,它返回一个 multiplier 函数。multiplier 函数将一个值乘以给定的因子 n。
#你可以使用 make_multiplier 创建不同的乘法函数,如 times3 和 times5。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 函数的基础
    • 函数的参数
      • 1.位置参数(Positional Arguments)
        • 2. 关键字参数(Keyword Arguments)
          • 3. 默认参数(Default Arguments)
            • 4. 可变长度参数 *args
              • 5. 可变长度关键字参数 **kwargs
                • 6. 强制关键字参数(Keyword-Only Arguments)
                • 函数的作用域
                  • 局部变量和全局变量:
                    • global关键字:
                      • nonlocal关键字:
                        • nonlocal 和 global 的区别
                        • 函数的进阶
                          • 1.函数嵌套(Nested Functions)
                            • 2.闭包(Closures)
                              • 3.装饰器(Decorator)
                                • 装饰器处理带参数的函数
                              • 4.lambda表达式
                                • 5.生成器
                                  • 生成器处理斐波那契数列
                                • 高阶函数
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档