函数

  • return 语句

    return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。

  • 可更改(mutable)与不可更改(immutable)对象

    在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。

    • 不可变类型变量赋值 a=5 后再赋值 a=10**,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。

    • 可变类型:变量赋值la=[1,2,3,4]后再赋值la[2]=5则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

    python 函数的参数传递:

    • 不可变类型类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。

    • 可变类型类似C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响

      例如:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      #!/usr/bin/python3

      # 可写函数说明
      def changeme( mylist ):
      "修改传入的列表"
      mylist.append([1,2,3,4])
      print ("函数内取值: ", mylist)
      return

      # 调用changeme函数
      mylist = [10,20,30]
      changeme( mylist )
      print ("函数外取值: ", mylist)

      结果如下:

      1
      2
      函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
      函数外取值: [10, 20, 30, [1, 2, 3, 4]]
  • 强制位置参数

    Python3.8 新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。

    在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 和 f 要求为关键字形参:

    1
    2
    def f(a, b, /, c, d, *, e, f):
    print(a, b, c, d, e, f)

    以下使用方法是正确的:

    1
    f(10, 20, 30, d=40, e=50, f=60)

    以下使用方法会发生错误:

    f(10, b=20, c=30, d=40, e=50, f=60) # b 不能使用关键字参数的形式
    f(10, 20, 30, 40, 50, f=60) # e 必须使用关键字参数的形式``

  • 可变参数

    1
    2
    def fun(*args):
    # 函数操作
      例如:
    
1
2
3
4
5
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum

定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:

1
2
3
4
>>> calc(1, 2)
5
>>> calc()
0

如果已经有一个list或者tuple,要调用一个可变参数,可以加上*,

  • 方法一:

    1
    2
    3
    >>> nums = [1, 2, 3]
    >>> calc(nums[0], nums[1], nums[2])
    14
  • 方法二

1
2
3
>>> nums = [1, 2, 3]
>>> calc(*nums)
14

*nums表示把nums这个list的所有元素作为可变参数传进去。

关键字参数

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

1
2
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)

调用1

1
2
>>>person('Michael', 30)
name: Michael age: 30 other: {}

调用2

1
2
3
4
>>>person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>>person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

把组装好的字典作为关键字参数传入

  • 方法一:

    1
    2
    3
    >> extra = {'city': 'Beijing', 'job': 'Engineer'}
    >>> person('Jack', 24, city=extra['city'], job=extra['job'])
    name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
  • 方法二:

    1
    2
    3
    >>> extra = {'city': 'Beijing', 'job': 'Engineer'}
    >>> person('Jack', 24, **extra)
    name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
  • 命名关键字参数

    在函数定义中使用 * 后的参数,它们必须在调用时以 name=value 的形式显式传递。

限制关键字参数的名字,就可以用命名关键字参数,例如,只接收cityjob作为关键字参数。

示例:

1
2
def person(name, age, *, city, job):
print(name, age, city, job)
    命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。

调用方法如下:

1
2
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
   命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:
1
2
3
4
>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given

命名关键字参数可以有缺省值,从而简化调用:

参数的顺序

在 Python 中,函数的参数顺序有一个明确的规定,这有助于确保函数调用时参数的正确匹配和解读。函数参数的顺序可以分为以下几种类型:

函数参数的顺序

  1. 位置参数(Positional Arguments)

    • 这些参数在函数调用时通过位置传递。它们必须按照在函数定义中声明的顺序提供。

    • 示例:

      1
      2
      3
      4
      def func(a, b, c):
      print(a, b, c)

      func(1, 2, 3) # a=1, b=2, c=3
  2. 默认参数(Default Arguments)

    • 默认参数在函数定义时提供了一个默认值。如果调用时不提供该参数的值,则使用默认值。

    • 默认参数必须在所有非默认参数之后定义。

    • 示例:

      1
      2
      3
      4
      5
      6
      def func(a, b=2, c=3):
      print(a, b, c)

      func(1) # a=1, b=2, c=3
      func(1, c=4) # a=1, b=2, c=4
      func(1, b=5, c=6) # a=1, b=5, c=6
  3. 关键字参数(Keyword Arguments)

    • 这些参数在函数调用时通过指定名称来传递,可以改变参数的顺序。

    • 关键字参数必须在所有位置参数之后提供。

    • 示例:

      1
      2
      3
      4
      def func(a, b, c):
      print(a, b, c)

      func(a=1, c=3, b=2) # a=1, b=2, c=3
  4. 可变位置参数(*args)

    • 用于接收任意数量的位置参数,这些参数将被收集到一个元组中。

    • *args 必须在位置参数和默认参数之后定义。

    • 示例:

      1
      2
      3
      4
      def func(a, b, *args):
      print(a, b, args)

      func(1, 2, 3, 4, 5) # a=1, b=2, args=(3, 4, 5)
  5. 命名关键字参数(*)

    • 用于定义所有后续的参数必须通过关键字传递。

    • * 后面的参数称为命名关键字参数,调用时必须以 name=value 的形式指定。

    • 示例:

      1
      2
      3
      4
      def func(a, b, *, x=10, y=20):
      print(a, b, x, y)

      func(1, 2, x=30, y=40) # a=1, b=2, x=30, y=40
  6. 可变关键字参数( kwargs)**:

    • 用于接收任意数量的关键字参数,这些参数将被收集到一个字典中。

    • **kwargs 必须在所有位置参数、默认参数、*args 和命名关键字参数之后定义。

    • 示例:

      1
      2
      3
      4
      def func(a, b, **kwargs):
      print(a, b, kwargs)

      func(1, 2, x=30, y=40) # a=1, b=2, kwargs={'x': 30, 'y': 40}

总结

  • 位置参数:必须按照定义的顺序提供。
  • 默认参数:必须在所有位置参数之后定义,并且可以省略。
  • 关键字参数:可以在调用时以名称指定参数值,顺序可以不同。
  • 可变位置参数 (*args):用于接收任意数量的位置参数,定义在位置参数和默认参数之后。
  • 命名关键字参数 (*):用于将所有后续的参数设为命名关键字参数。
  • 可变关键字参数 (`kwargs`)**:用于接收任意数量的关键字参数,定义在所有其他参数之后。

函数参数的顺序确保了函数定义和调用的一致性和灵活性。

参数定义的顺序必须是:必选参数、默认参数、可变参数/命名关键字参数和关键字参数。

匿名函数

lambda 函数的语法只包含一个语句,如下:

1
lambda [arg1 [,arg2,.....argn]]:expression
  • lambda是 Python 的关键字,用于定义 lambda 函数。
  • arguments 是参数列表,可以包含零个或多个参数,但必须在冒号(:)前指定。
  • expression 是一个表达式,用于计算并返回函数的结果。

参考教程