0
点赞
收藏
分享

微信扫一扫

python函数详解(定义、参数、返回值、高级函数、偏函数、装饰器)

python函数详解(定义、参数、返回值、高级函数、偏函数、装饰器)

一.说明

这是python中的基础系列中的关于函数部分,来开始我们今天日拱一卒!对python函数部分进行详细整理和学习。

二.定义

  1. 在Python中,函数是通过 def 关键字来定义函数;
  2. 函数定义的结构如下

def function_name(parameters):
    """函数的文档字符串,可选"""
    # 函数体
    return value  # 可选

  1. function_name 是函数的名称,遵循标识符命名规则
  2. parameters 是函数的输入参数,可以有多个,也可以没有
  3. 函数体是实现具体功能的代码块
  4. return语句用于返回结果,若没有,则默认返回 None

三.特性

  1. 封装性:函数将特定功能的代码封装在一起,便于复用
  2. 可读性:通过函数名称和文档字符串,提升代码的可读性
  3. 模块化:可以将复杂的任务分解为多个简单的函数,便于管理和调试

四.函数参数

在各类语言中函数参数一般都分为形参和实参!这个概念,很多时候被忽略,因为就算不理解这一概念,也照样使用,那么什么是形参和实参,很简单,让我来概括。

形参:函数定义是的参数就是形参;

实参:函数调用时传入的参数就是实参;

就这么简单?在python中这一概念可不这么简单!!让我来细细整理,这是核心!!

1.位置参数

参数的定义和调用,按顺序传递

def greet(name):
    print(f"Hello, {name}!")
greet("Alice")  # 输出: Hello, Alice!

2.关键字参数

调用时,通过参数名称传递

def greet(name, age):
    print(f"{name} is {age} years old.")
greet(age=30, name="Bob")  # 输出: Bob is 30 years old.

3.默认参数

可以为参数指定默认值,注意,这里又有一个隐藏概念!指定默认值的行参必须放在未指定默认值的形参后面

def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")
greet("Alice")  # 输出: Hello, Alice!

########
def greet(greeting="Hello",name):
    print(f"{greeting}, {name}!")   #报错
greet("Alice")

4.可变参数

使用 *args**kwargs 处理不定数量的参数

*args:传入参数被当作元组处理

**kwargs:传入参数被当作字典处理

def summarize(*args):
    return sum(args)

def show_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

summarize(1, 2, 3)  # 输出: 6
show_info(name="Alice", age=30)  # 输出: name: Alice, age: 30

可变参数 是不是觉得很简单,一看就会?等会一练就废!大家看看下面的代码,输出结果是什么?

def demo(a,b,*args):
    print("a:",a)
    print("b:",b)
    print("arg:",args)
demo(1,2,3)
demo(1,2,3,4,5)


def demo1(a,**args):
    print("a",a)
    print("args",args)
demo1(1,name='bob',age=33)

def demo3(a,b,c=0,*args,**kwargs):
    print("a:",a)
    print("b:",b)
    print("c:",c)
    print("arg:",args)
    print("kwargs:",kwargs)
    
    
demo3(1,2,k=3)
demo3(1,2,3,4,5)
demo3(1,b=2,c=3,d=4)
demo3(*(1,2,3),**{'age':4}) 


def custom_function(a, b, c=0, *args, **kwargs):
    print("a:", a)
    print("b:", b)
    print("c:", c)
    print("args:", args)
    print("kwargs:", kwargs)


custom_function(1, 2)                             
custom_function(3, 4, 5, 6, 7, name="Alice")

5.函数参数默认值计算方式

先看一下这个案例:

def test(a=[]):
      a.append('end')
      print(a)
test([1,2,3]) #[1,2,3,'end']
test()  #['end']
test()  #['end','end']
test([4,5,6]) #[4,5,6,'end']

请问为啥会出现['end','end']?为什么会出现这种情况!

这个与python语言特性和 python中函数的参数默认值实现逻辑有关!

函数参数的默认值只在函数定义时计算一次,而不是每次调用时,这意味着如果你使用可变对象(如列表或字典)作为默认值,它会在后续调用中保持修改状态。

好那么还有一个疑问,如何避免这个问题?

def test(a=None):
    if a is None:
           a = []
    a.append('end')
    print(a)

五.返回值

  1. return 语句返回 函数的计算结果,也可以没有return 默认返回 None

def demo1():
    pass

a = demo1()
print(a)   #None

  1. return 可以返回一个值,也可返回多个值,当返回多个值 那么返回的是一个元组

def demo1():
    return 1,2,3,4

a = demo1()
print(a)   #(1, 2, 3, 4)

六.文档字符串

函数的文档字符串,其实就是函数的帮助文档,包含函数的基础信息、函数的功能简介、函数的形参类型,使用等

文档字符串规则:

  1. 必须在函数首行定义文档字符串;
  2. 使用三个引号 注解;

#Google 风格
def multiply(x, y):
    """Multiply two numbers.

    Args:
        x (int or float): The first number.
        y (int or float): The second number.

    Returns:
        int or float: The product of x and y.
    """
    return x * y

#NumPy 风格
def divide(x, y):
    """Divide x by y.

    Parameters
    ----------
    x : int or float
        The numerator.
    y : int or float
        The denominator.

    Returns
    -------
    float
        The result of x divided by y.
    """
    return x / y

七.函数的类型

  1. 空函数
    函数体不完成任何功能,只有一个pass

def demo1():
    pass

a = demo1()
print(a)   #None

  1. 匿名函数

不再使用def 函数名()这种形式定义函数,而是使用lambda来创建匿名函数

lambda函数:

  1. lambda 函数只能包含一个表达式,即只有一行,不能包含多个语句或复杂逻辑
  2. lambda函数是匿名的,但可以将其赋值给一个变量,以便后续使用

add = lambda x, y: x + y
print(add(3, 5))  # 输出: 8

#过滤
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 输出: [2, 4, 6]
#映射
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers)  # 输出: [1, 4, 9, 16, 25, 36]
#排序
people = [
    {'name': 'Alice', 'age': 30},
    {'name': 'Bob', 'age': 25},
    {'name': 'Charlie', 'age': 35}
]

# 按年龄排序
sorted_people = sorted(people, key=lambda person: person['age'])
print(sorted_people)
# 输出: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie', 'age': 35}]

八.高级函数

高阶函数是指可以接受其他函数作为参数或返回一个函数的函数

def high_order_function(func):
    return func(10)

def square(x):
    return x * x

result = high_order_function(square)  # 输出: 100
print(result)

九.偏函数

偏函数(Partial Function)是指通过固定一个函数的部分参数来创建一个新的函数。在Python中,可以使用 functools 模块中的 partial() 函数来实现偏函数。这种方式特别有用,可以使函数更加灵活和简洁。

from functools import partial

def calculate_price(original_price, discount_rate):
    """计算折后价格"""
    return original_price * (1 - discount_rate)



# 固定折扣率为 20%
calculate_discounted_price = partial(calculate_price, discount_rate=0.20)


# 示例商品价格
prices = [100, 200, 300, 400]

# 计算折后价格
discounted_prices = [calculate_discounted_price(price) for price in prices]

# 打印结果
for original, discounted in zip(prices, discounted_prices):
    print(f"原价: {original},折后价: {discounted:.2f}")

'''
原价: 100,折后价: 80.00
原价: 200,折后价: 160.00
原价: 300,折后价: 240.00
原价: 400,折后价: 320.00
'''

十.装饰器

这个为函数这一概念中的重点的重点,在现实开发中使用场景非常多,想学习python必须掌握装饰器,这一概念!不然根本不算入门!

当然学习函数装饰器也很简单,静下来,看完慢慢缕一缕!

  1. 概念
    装饰器本质上是一个函数,它接受另一个函数作为参数,并返回一个新的函数。这个新的函数通常是在原始函数的基础上,增加了一些额外的功能。
  2. 装饰器语法
    装饰器使用 @decorator_name 语法来应用于函数。下面是一个简单的示例:

def my_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
@my_decorator
def say_hello():
     print("Hello!")
#调用
say_hellosay_hello()


'''
输出:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.
'''

  1. 定义装饰器
  • my_decorator 是装饰器,它接受一个函数 func 作为参数。
  • wrapper 是内部函数,执行装饰器的额外逻辑,调用原始函数 func
  1. 使用装饰器
  • @my_decoratorsay_hello 函数传递给 my_decorator
  • say_hello 实际上变成了 wrapper 函数。
  1. 调用函数
  • 当你调用 say_hello() 时,实际上是在调用 wrapper()
  1. 带参数装饰器
    如果你想要装饰器接受参数,可以通过定义一个装饰器工厂来实现:

def repeat(num_times):
     def decorator_repeat(func):
         def wrapper(*args, **kwargs):
             for _ in range(num_times):
                 func(*args, **kwargs)
           return wrapper
     return decorator_repeat
@repeat(3)
def greet(name): 
    print(f"Hello, {name}!")
greet("Alice")

'''
输出:
Hello, Alice!
Hello, Alice!
Hello, Alice!
'''

  1. 使用场景
  1. 日志记录:在函数执行前后记录日志
  2. 权限验证:检查用户是否有权调用某个函数
  3. 缓存:存储函数结果以减少计算时间
  1. 保持原函数的元数据
    使用 functools.wraps 可以确保装饰器不会丢失原函数的元数据(如名称和文档字符串)

from functools import wraps
def my_decorator(func): 
  @wraps(func) 
  def wrapper(): 
      print("Before") 
      func() 
      print("After") 
  return wrapper

  1. 总结
    装饰器是一个非常强大的特性,可以在不修改函数本身的情况下,增加或改变其行为。它们在许多框架和库中被广泛使用,例如 Flask 和 Django,常用于路由、请求处理和权限控制。。
    其实要掌握也很简单,照抄写法就行 主要是带参数的装饰器。。

十一.总结

其实函数还有一大模块,变量和作用域,这一概念需要单独提出来写,函数这一概念 重点注意 参数传递/调用/返回值/装饰器,特别是装饰器 这东西实在太强大了,相比其他语言想要实现这一功能就要复杂很多!

创作整理不易,请大家多多关注 多多点赞,有写的不对的地方欢迎大家补充,我来整理,再次感谢!

举报

相关推荐

0 条评论