特别篇 函数基础

1.函数目的

 函数的主要目的是提高代码的模块性和重用性。

def add_numbers(a, b):
    """
    This function takes two numbers as input and returns their sum.
    """
    return a + b

# 调用函数并打印结果
result = add_numbers(3, 5)
print("The sum of 3 and 5 is:", result)

通过使用函数,我们可以将复杂的任务分解为更小的部分,使代码更加模块化和易于理解。此外,我们还可以通过编写不同的函数来处理不同类型的数据或执行不同的操作,从而进一步提高代码的灵活性和可重用性。

2.函数定义

 在Python中,可以使用def关键字来定义一个函数。

def 函数名(参数1, 参数2, ...):
    函数体
    return 返回值

其中,函数名是你为函数起的名字,参数1, 参数2, ...是传递给函数的输入值,函数体是执行特定任务的代码块,return语句用于返回函数的结果。如果函数不需要返回任何值,可以省略return语句。下面是一个简单的示例,定义了一个名为add的函数,用于计算两个数的和:

def add(a, b):
    result = a + b
    return result

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

3.函数声明

 函数还可以包括文档字符串(docstring),即函数开始处的第一个字符串,用于解释函数的用途和行为。这可以通过三引号(""")来定义,

def calculate_square(number):
    """
    This function calculates the square of a given number.
    """
    return number ** 2

Python中函数的声明涉及使用def关键字,指定函数名和参数列表,并提供函数体以执行特定任务。选项包括添加文档字符串以提供关于函数功能的详细解释。理解并正确声明函数对于编写可重用、模块化和易于理解的代码至关重要。

4.函数调用

 在Python中,函数的调用是通过在函数名后面加上括号,并在括号内传递参数(如果有的话)来实现的。

def greet(name):
    print("Hello, " + name + "!")

# 调用函数
greet("Alice")

5.函数形参

 形式参数,在函数的定义时()中出现的数值,形参是一个变量,它需要使用实参赋值

def greet(name):  # 'name' 是一个形参
    print("Hello, " + name + "!")

# 函数调用,'Alice' 是实参
greet("Alice")
# 输出: Hello, Alice!

# 再次调用同一函数,传递不同的实参
greet("Bob")
# 输出: Hello, Bob!

name是一个形参,当greet函数被调用时,它接收传递的实参值(如"Alice"或"Bob"),并将其用于打印问候语。

6.函数实参

 实际参数,在函数调用时()中出现的数值,与形参不同,形参是出现在函数定义时而实参是出现在函数调用的时候。

def greet(name):  # 'name' 是一个形参
    print("Hello, " + name + "!")

# 函数调用,'Alice' 是实参
greet("Alice")
# 输出: Hello, Alice!

# 再次调用同一函数,传递不同的实参
greet("Bob")
# 输出: Hello, Bob!

"Alice""Bob"都是实参,它们分别被传递给了greet函数的形参name。当函数被调用时,实参的值会被赋给形参,然后函数内部的代码可以使用这些值进行操作。

7.函数返回值

 函数通过使用return语句来指定要返回的值。如果在一个函数中没有使用return,那么将返回None,return也可以返回多个数据,它会将多个数据存入元组返回。return代表函数结束后续代码不在执行。

def add_numbers(a, b):
    result = a + b
    return result  # 返回计算结果

# 调用函数并接收返回值
sum_result = add_numbers(3, 5)
print("The sum is:", sum_result)
# 输出: The sum is: 8

8.函数的参数类型

 函数的参数类型是指在定义或调用函数时传递给函数的参数所属的数据类别,

默认参数:调用没有传值则使用默认值,有传值则使用传递的值,只能出现在非默认参数后方。

位置参数:按照位置依次顺序赋值。

关键字参数:通过指明关键字表明要将值赋予哪一个形参。

可变参数:元组参数(*args)字典参数(**kwargs)args和kwargs可以叫其他名字,但args是元组类型可以接受任意个数实参,kwargs是字典类型,可以接受除了形参关键字参数以外的其他关键字参数。

def new_up(n, msg, *args, info="今日上限", tips="抱歉", **kwargs):
    """

    :param n:
    :param msg:
    :param args: 元组参数
    :param info: 关键字参数
    :param tips: 关键字参数
    :param kwargs: 字典参数
    :return:
    """""
    for name in args:
        print(f"{n}{msg},{name},{info},{tips}{kwargs}")


new_up(101, "下次吧", "熊大", "熊二", more1="明天十点", more2="123")

9.变量的作用域(global与nonlocal)

全局作用域(Global Scope)
  • 定义位置:全局作用域中的变量是在函数之外定义的。
  • 访问权限:这些变量可以在同一模块中的任何函数内部或外部被访问。
  • 修改权限:如果在函数内部需要修改全局变量的值,必须使用global关键字声明。
# 全局作用域
global_var = "I'm a global variable"

def my_function():
    # 使用 global 关键字修改全局变量
    global global_var
    global_var = "Modified inside a function"

my_function()
print(global_var)  # 输出:Modified inside a function
非局部作用域(Nonlocal Scope)
  • 定义位置:非局部作用域中的变量是在嵌套函数的外层函数内部定义的。
  • 访问权限:这些变量可以在嵌套的内部函数中被访问。
  • 修改权限:如果要在内部嵌套的函数中修改外层函数中的变量,必须使用nonlocal关键字声明。
    def outer_function():
        # 外层函数作用域
        outer_var = "I'm a variable from outer function"
    
        def inner_function():
            # 使用 nonlocal 关键字修改外层函数中的变量
            nonlocal outer_var
            outer_var = "Modified inside an inner function"
    
        inner_function()
        print(outer_var)  # 输出:Modified inside an inner function
    
    outer_function()
    

10.递归函数

 递归函数是一种编程技术,其中一个函数能够直接或间接地调用自己的情况。这种结构使得递归能够非常有效地解决一类可以通过重复将问题分解为更小的相同类型的子问题的问题。

下面是一个使用Python编写的递归函数来计算阶乘的例子:

def factorial(n):
    # 结束条件:当n为1时,返回1
    if n == 1:
        return 1
    # 递推关系:n的阶乘等于n乘以(n-1)的阶乘
    else:
        return n * factorial(n - 1)

# 测试代码
print(factorial(5))  # 输出结果应为120

factorial函数首先检查输入参数n是否等于1,如果是,则直接返回1作为结果。否则,它通过调用自身来计算(n-1)的阶乘,并将结果乘以n来得到n的阶乘。这个过程会一直重复,直到达到结束条件。

11.匿名函数

 Python中的匿名函数也被称为lambda函数,它允许在不需要显式定义函数的情况下创建简单的、一次性的函数。这种函数通常用于需要快速定义和使用一次的简单操作,而无需给予函数名。以下是一些使用Python中的lambda函数的例子:

求和

add = lambda a, b: a + b
result = add(5, 3)
print(result)  # 输出8

筛选偶数

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

按字符串长度排序

fruits = ['apple', 'banana', 'cherry', 'date']
sorted_fruits = sorted(fruits, key=lambda x: len(x))
print(sorted_fruits)  # 输出['date', 'apple', 'banana', 'cherry']

这些例子展示了如何使用lambda函数来创建简单的匿名函数,并在不同的场景中应用它们。通过lambda函数,我们可以快速定义简单的操作,而无需显式地定义一个完整的函数。

12.闭包

 Python中的闭包是一种函数,它能够记住并访问其所在的词法作用域中的变量,即使该函数在当前词法作用域之外执行。闭包是通过嵌套函数和外部函数的变量引用来实现的,这使得内部函数可以访问和操作外部函数的局部变量。

基本定义

  • 创建方式:在Python中,当一个内部函数引用了外部函数的局部变量或参数时,就形成了闭包。内部函数拥有对外部函数作用域的访问权。
  • 调用方法:闭包可以通过外部函数返回内部函数的方式来创建,然后通过调用返回的函数来运行闭包内的代码。
    def outer_function(x):
        def inner_function(y):
            return x + y
        return inner_function
    closure = outer_function(10)
    print(closure(5))  # 输出15
    
  • 优点限制
    • 保持状态:闭包允许函数在执行结束后仍保持其内部状态,这在实现计数器、状态管理器等场景中非常有用。
    • 避免全局污染:由于闭包可以访问外部函数的局部变量,因此可以减少全局变量的使用,降低全局作用域的污染风险。
    • 内存泄漏:由于闭包会持续占用内存,如果大量使用可能导致内存泄漏,尤其是在长时间运行的程序中更为明显。
    • 性能开销:每个闭包都会携带额外的作用域链,这会增加内存消耗和降低执行效率。
  • 注意事项
    • 循环引用问题:在Python中,如果两个对象相互引用对方,可能会导致循环引用问题,这需要通过弱引用等方式来解决。
    • 可读性维护性:闭包的过度使用可能会降低代码的可读性和可维护性,因此需要谨慎使用。
    • 调试困难:闭包的复杂性可能会增加代码的调试难度,特别是在处理多级闭包和异步操作时需特别注意。

13.装饰器

装饰器(Decorators)是Python中一种强大的工具,允许在不修改原始函数代码的情况下,为函数添加新的功能或改变其行为

装饰器本质上是一个返回函数的函数,这个返回的函数通常是对原函数进行包装或增强的版本。装饰器的主要应用包括日志记录、性能分析、权限控制、缓存等场景。下面将详细介绍装饰器的基本概念、使用方法以及高级应用:

  1. 基本概念
    • 定义:装饰器是一个接收函数作为参数并返回新函数的函数。
    • 作用:可以在不改变原函数内部实现的前提下,增加或修改原函数的功能。
    • 语法:使用@符号加上装饰器名称,例如:@decorator_name
  2. 使用方法
    • 简单例子:定义一个装饰器a_new_decorator,然后在需要装饰的函数前使用@a_new_decorator即可
      def a_new_decorator(a_func):
          def wrapTheFunction():
              print("Something is happening before a_func()")
              a_func()
              print("Something is happening after a_func()")
          return wrapTheFunction
      @a_new_decorator
      def hello():
          print("Hello, world!")
      

      调用方法:当装饰后的函数被调用时,实际上是执行了装饰器返回的新函数

    • 带参数的装饰器:如果装饰器需要接收参数,可以使用一个外层函数来封装装饰器,例如@repeat(3)表示重复执行装饰的函数3次。

      def repeat(num_times):
          def decorator(func):
              def wrapper(*args, **kwargs):
                  for _ in range(num_times):
                      result = func(*args, **kwargs)
                  return result
              return wrapper
          return decorator
      @repeat(3)
      def say_hello(name):
          print(f"Hello, {name}!")
      

      保留原函数信息:使用functools.wraps装饰器可以保留原函数的元信息,如函数名、文档字符串等

      from functools import wraps
      def my_decorator(func):
          @wraps(func)
          def wrapper(*args, **kwargs):
              print("Before calling the function")
              result = func(*args, **kwargs)
              print("After calling the function")
              return result
          return wrapper
      @my_decorator
      def example():
          """This is an example function."""
          print("Hello from a function.")
      

    • 实际应用
      • 日志记录:通过装饰器自动记录函数调用信息、参数和返回值。
      • 性能分析:使用装饰器来测量函数的执行时间。
      • 权限控制:装饰器用于限制对某些函数的访问权限。
      • 缓存结果:通过装饰器实现函数结果的缓存,以提高性能。

Python中的装饰器是一种灵活且强大的工具,它能够在不修改原始函数代码的情况下,增加额外的功能或修改函数的行为。从基本的装饰器使用到高级应用,装饰器极大地提高了代码的模块化和可重用性。掌握装饰器的使用,对于编写高质量、易于维护的Python代码至关重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值