python函数详解

本文深入解析Python函数的各种特性,包括必选参数、默认参数、可变参数、关键字参数及命名关键字参数的使用方法,探讨匿名函数、高阶函数、内置函数的高级应用,以及函数在实际编程中的灵活性和强大功能。

写在篇前

  函数能提高应用的模块性,和代码的重复利用率,是编程必须具备的基本抽象能力。python函数更是奇妙灵活,与很多特性值得探讨,本篇文章就来详细看看python 函数那些巧妙之处。首先,在篇前简单说说python函数的形式。比如说我们要实现一个函数:计算一个数m的n次方,那么函数可以定义如下:

def exponentiation(m, n):
    return m^n

# def 是函数定义关键字
# exponentiation 是函数名
# (m,n)是函数参数,后面冒号之后是函数体
# return 表示返回值,一个函数也可以没有函数体,此时返回值为None

函数参数

  • 必选参数

     必选参数,又称为位置参数,我们上面定义的函数exponentiationm, n 就是必选参数。当调用该函数时,每一个必选参数都必须传入合适的值。

  • 默认参数

     修改函数exponentiation为:

    def exponentiation(m, n=2):
        return m^n
    

     这样,n便是一个默认参数,当计算一个数的二次方时,只需要传入参数m即可:

    >>> exponentiation(3)
    9
    

     需要注意的是,必选参数必须在前,默认参数在后,否则Python的解释器会报错;为了避免不必要的坑,默认参数必须指向不变对象。 另外,在函数定义的时候就会确定默认参数的值,当我们改变x的值的时候对默认参数值并没有影响,即:

    >>> x = 42
    >>> def spam(a, b=x):
    ...     print(a, b)
    ...
    >>> spam(1)
    1 42
    >>> x = 23
    >>> spam(1)
    1 42
    >>>
    
  • 可变参数

      可变参数是python函数灵活性的表现之一,如果有这样一个需求,编写一个函数计算若干个数的和,这时可变参数便是一种好的选择:

    def calc_sum(*args):
        sum = 0
        for arg in args:
            sum += arg
        return sum
    
    
    print(calc_sum(1, 2, 3)) # 可变参数可传入0个或任意个参数,在函数调用时自动组装为一个tuple
    nums = [1, 2, 3]
    print(calc_sum(*nums))  # *nums意思是将nums中的所有元素以可变参数的形式传入函数
    
  • 关键字参数

     关键字参数允许你传入0个或任意个含参数名的参数,在函数内部会自动组装为一个dict。

    def print_info(pc_id, pc_name, **kwargs):
        print(pc_id, pc_name, kwargs, sep='\n')
    
    
    other_info = {'city': 'NanJing', 'company': 'APPLE'}
    print_info('0001', 'IMac-2018', city='NanJing', company='APPLE')
    print_info('0001', 'IMac-2018', **other_info)
    
    0001
    IMac-2018
    {'city': 'NanJing', 'company': 'APPLE'}
    0001
    IMac-2018
    {'city': 'NanJing', 'company': 'APPLE'}
    

 关键字参数可以传入任意参数名,那我们可不可以限制他传入指定的参数名呢?答案是当然可以,采用命名关键字可以实现该需求。但是这里需要搞清楚一个逻辑上的问题。这里的指定的参数名要和前面的必选参数区分开来。命名关键字参数如果有默认值可以不传入,但是如果传入就只能是已经限定的关键字参数。

def print_info(pc_id, pc_name, *, city, company):
    # 用一个 *,区分必选参数和关键字参数
    print("pc_id: %s\tpc_name: %s" % (pc_id, pc_name), end='\t')
    if city:
        print('city:%s' % city, end='\t')
    if company:
        print('company:%s' % company)


other_info = {'city': 'NanJing', 'company': 'APPLE'}

print_info('0001', 'IMac-2018', city='NanJing', company='APPLE')
print_info('0001', 'IMac-2018', **other_info)

# 但是如果函数定义中已经有了一个可变参数,命名关键字参数就不再需要分隔符*了
# def print_info(pc_id, pc_name, *args, city, company):
  • 小结

    以上四种参数可以灵活的进行组合应用,需要注意的是,参数定义的顺序必须是:必选参数、默认参数、可变参数、(命名关键字参数)关键字参数。

    def f(a, b, c=0, *args, **kw):
        print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
    

特殊函数

匿名函数

  在python中可以通过lambda来定义匿名函数,其返回一个函数表达式,类似于def,但是比def更轻巧,可以没有名字。

# 关键字`lambda`表示匿名函数,冒号前面的`x`,`y`表示函数参数
# 匿名函数有个限制:只能有一个表达式,不用写return,返回值就是该表达式的结果。
>>>add = lambda x,y: x+y
>>>add(2,3)
5

 需要注意的是,lambda表达式中的参数x、y等是自由变量, 在运行时绑定值,而不是定义时就绑定,这跟函数的默认值参数定义是不同的。 因此在下面例子中,调用这个lambda表达式的时候,x的值是执行时的值。

>>> x = 10
>>> a = lambda y: x + y
>>> x = 20
>>> b = lambda y: x + y
>>> a(10)
30
>>> b(10)
30

高阶函数

  一个函数接收另一个函数作为参数,这种函数称之为高阶函数(Higher-order Functions)。python中有几个常用的内置高阶函数:

  • filter

    filter() 函数接收两个参数,一个函数和一个序列,其中传入的函数会依次作用于序列的每一个元素,根据返回值是True或则False决定是否保留该元素。

    filter(lambda x: x>10, [1, 56, 3, 36, 9])
    
    
    >>> g = filter(lambda x: x>10, [1, 56, 3, 36, 9])
    >>> g
    <filter object at 0x10207b470>
    >>> type(g)
    <class 'filter'>
    >>> list(g)
    [56, 36]
    
  • map/reduce

      map()函数接收两个参数,一个是函数,一个是Iterablemap将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回;reduce() 把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。

    >>> r = map(lambda x:x*x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    >>> type(r)
    <class 'map'>
    >>> list(r)
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    from functools import reduce
    >>>reduce(lambda x,y: x+y, [1,2,3,4])
    10
    
  • sorted

      用于可迭代对象的排序,如:

    # 实例1
    >>> sorted([36, 5, -12, 9, -21], key=abs)
    [5, 9, -12, -21, 36]
    
  • 返回函数

      高阶函数除了可以接受函数作为参数,也可以将函数作为返回值,实现“延迟计算”。

    def calc_sum(lst):
        def lazy_sum():
            return sum(lst)
        return lazy_sum
    
    >>> f = calc_sum([1, 2, 3, 4])
    >>>f
    <function calc_sum.<locals>.lazy_sum at 0x10e9bd158>
    >>>f()
    10
    

偏函数

  偏函数的作用是为函数某些参数设置默认值,使调用更加方便,以下会是一个好的例子:

points = [ (1, 2), (3, 4), (5, 6), (7, 8) ]
import math
def distance(p1, p2):
    x1, y1 = p1
    x2, y2 = p2
    return math.hypot(x2 - x1, y2 - y1)
>>> pt = (4, 3)
>>> points.sort(key=partial(distance,p2=pt))  # 注意这里必须是p2=pt
>>> points
[(3, 4), (1, 2), (5, 6), (7, 8)]

回调函数

  在计算机程序设计中,回调函数,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。关于理解可以参考回调函数是什么。这里我们也给出一个例子辅助理解:

def greeting(name):
    print('hello %s!' % name)
    
def someone_coming(callback):
    name = input()
    callback(name)
    
def main():
    someone_coming(greeting)
    
if __name__ == '__main__':
    main()

内置函数

  这里确切的应该说是其他内置函数,因为上面也涉及很多内置函数,如sortedfiltermap等。另外,python内置函数非常之多,如果想了解更全面的内部函数,可以参考内置函数1内置函数2

  • zip()

     用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。需要注意的是,当多个可迭代数据length不同时,取最小长度,其他忽略。

    >>>a = [1,2,3]
    >>> b = [4,5,6]
    >>> c = [4,5,6,7,8]
    >>> zipped = zip(a,b)     # 打包为元组的列表
    [(1, 4), (2, 5), (3, 6)]
    >>> zip(a,c)              # 元素个数与最短的列表一致
    [(1, 4), (2, 5), (3, 6)]
    >>> zip(*zipped)          # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
    [(1, 2, 3), (4, 5, 6)]
    
  • reversed()

     用于反转序列,生成新的可迭代对象

    >>> a = reversed(range(10)) # 传入range对象
    >>> a # 类型变成迭代器
    <range_iterator object at 0x035634E8>
    >>> list(a)
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    
  • enumerate()

     enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中

    >>>seq = ['one', 'two', 'three']
    >>> for i, element in enumerate(seq):
    ...     print i, element
    
    0 one
    1 two
    2 three
    
### Python函数概述 在Python中,函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段。函数能提高应用的模块性和代码的重复利用率。 ### 函数定义 Python中使用`def`关键字来定义函数,语法如下: ```python def function_name(parameters): """函数文档字符串""" function_suite return [expression] ``` - `function_name`:函数名,遵循标识符命名规则。 - `parameters`:函数的参数,可以有零个或多个,多个参数之间用逗号分隔。 - `function_suite`:函数体,是实现函数功能的代码块。 - `return`语句:可选,用于返回函数的结果,如果没有`return`语句,函数默认返回`None`。 ### 函数参数 #### 位置参数 位置参数是最常见的参数类型,调用函数时,参数的传递顺序必须与定义时的顺序一致。 ```python def add(a, b): return a + b result = add(3, 5) print(result) # 输出: 8 ``` #### 默认参数 默认参数允许在定义函数时为参数指定默认值。如果调用函数时没有提供该参数的值,则使用默认值。 ```python def greet(name, message="Hello"): return f"{message}, {name}!" print(greet("Alice")) # 输出: Hello, Alice! print(greet("Bob", "Hi")) # 输出: Hi, Bob! ``` #### 可变参数 可变参数允许函数接受任意数量的参数。在参数名前加一个`*`表示接受任意数量的位置参数,加两个`**`表示接受任意数量的关键字参数。 ```python def sum_numbers(*numbers): total = 0 for num in numbers: total += num return total print(sum_numbers(1, 2, 3)) # 输出: 6 def print_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}") print_info(name="Alice", age=25) # 输出: # name: Alice # age: 25 ``` #### 关键字参数 调用函数时,可以通过参数名来指定参数的值,这样可以不按照参数定义的顺序传递参数。 ```python def describe_person(name, age): return f"{name} is {age} years old." print(describe_person(age=30, name="Bob")) # 输出: Bob is 30 years old. ``` ### 函数调用 定义好函数后,可以通过函数名和参数来调用函数。 ```python def square(x): return x * x result = square(4) print(result) # 输出: 16 ``` ### 函数的返回值 函数可以通过`return`语句返回一个或多个值。返回多个值时,实际上返回的是一个元组。 ```python def get_name_and_age(): return "Alice", 25 name, age = get_name_and_age() print(f"Name: {name}, Age: {age}") # 输出: Name: Alice, Age: 25 ``` ### 匿名函数 Python中可以使用`lambda`关键字创建匿名函数匿名函数通常用于简单的、一次性的操作。 ```python add = lambda a, b: a + b result = add(3, 5) print(result) # 输出: 8 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值