函数

章节目录:

    • 一、定义一个函数
      • 1.1 相关概述
      • 1.2 句式规则
    • 二、参数传递
      • 2.1 变量类型
      • 2.2 可变与不可变
      • 2.3 传不可变对象实例
      • 2.4 传可变对象实例
    • 三、参数
      • 3.1 必需参数
      • 3.2 关键字参数
      • 3.3 默认参数
      • 3.4 不定长参数
    • 四、匿名函数
    • 五、强制位置参数
    • 六、结束语

一、定义一个函数

1.1 相关概述

  • 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
  • 函数能提高应用的模块性,和代码的重复利用率。你已经知道 Python 提供了许多内建函数,比如 print()。但你也可以自己创建函数,这被叫做用户自定义函数

1.2 句式规则

  • 句式
def 函数名(参数列表):
    函数体
  • 代码示例
"""
1.`def`为定义函数的关键字。
2.`get_max`为参数名。
3.`(num1, num2)` 为参数列表,即输入。
4.`return` 关键字设置返回值。
"""


def get_max(num1, num2):
    if num1 > num2:
        return num1
    else:
        return num2


a = 4
b = 5
# 调用函数并接收返回值。
max_value = get_max(a, b)
print(max_value)
# 5

  • 你可以定义一个由自己想要功能的函数,以下是简单的规则:
    • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ( )。
    • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
    • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
    • 函数内容以冒号 : 起始,并且缩进。
    • return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None

二、参数传递

2.1 变量类型

  • 在 python 中,类型属于对象,对象有不同类型的区分,变量是没有类型的:
a=[1,2,3]

a="abc"
  • 以上代码中,[1,2,3] 是 List 类型,“abc” 是 String 类型,而变量 a 是没有类型,它仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。

2.2 可变与不可变

  • 在 python 中,字符串元组数值不可更改的对象,而列表字典等则是可以修改的对象。

    • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
    • 可变类型:变量赋值 elements=[1,2,3,4] 后再赋值 elements[2]=5 则是将列表 elements 的第三个元素值更改,本身 elements 没有动,只是其内部的一部分值被修改了。
  • python 函数的参数传递:

    • 不可变类型类似 C++ 的值传递。如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
    • 可变类型类似 C++ 的引用传递。如 列表,字典。如 fun(elements),则是将 elements 真正的传过去,修改后 fun 外部的 elements 也会受影响
  • python 中一切都是对象严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

2.3 传不可变对象实例

  • 代码示例
def change(num):
    # 指向的是同一个对象。
    print("形参接收:", id(num))
    # 形参接收: 1700425564400

    num = 10
    # 新对象。(地址值发生变化。)
    print("修改变量值:", id(num))
    # 修改变量值: 1700425564688


a = 1
print("实参传入:", id(a))
# 实参传入: 1700425564400
change(a)

  • 在函数内部修改形参后(新生成),形参指向的是不同的地址。

2.4 传可变对象实例

  • 代码示例
def changeme(mylist):
    mylist.append([1, 2, 3, 4])
    print("函数内取值: ", mylist)
    # 函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
    print("操作集合之后地址值:", id(mylist))
    # 操作集合之后地址值: 2402473934336
    return


# 定义一个集合。
mylist = [10, 20, 30]
print("当前集合地址值:", id(mylist))
# 当前集合地址值: 2402473934336

# 调用函数。
changeme(mylist)
print("函数外取值: ", mylist)
# 函数外取值: [10, 20, 30, [1, 2, 3, 4]]

  • 可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。

三、参数

  • 以下是调用函数时可使用的正式参数类型:
    • 必需参数。
    • 关键字参数。
    • 默认参数。
    • 不定长参数。

3.1 必需参数

必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

  • 代码示例
def print_num(a):
    print(a)

    
# 调用报错。
print_num()
# TypeError: print_num() missing 1 required positional argument: 'a'

3.2 关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

  • 代码示例
def print_user_info(name, age):
    print("name:", name)
    print("age:", age)
    return


# 通过关键字传入参数。(此时顺序与函数列表不一致。)
print_user_info(age=18, name="jan")
# name: jan
# age: 18

3.3 默认参数

调用函数时,如果没有传递参数,则会使用默认参数。

  • 代码示例
def print_user_info(name, age=35):
    print("name:", name)
    print("age:", age)
    return


print_user_info(age=18, name="jan")
# name: jan
# age: 18

print("------------")

# 不传 age(使用默认值)。
print_user_info(name="jan")
# name: jan
# age: 35

3.4 不定长参数

在 Python 中,可以使用不定长参数来处理函数接受可变数量参数的情况。Python 提供了两种类型的不定长参数:*args 和 **kwargs。

  • 加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数:
def print_info(arg1, *args):
    print(arg1)
    print(args)


# 后面的参数被封装为了一个元组。
print_info(70, 60, 50)
# 70
# (60, 50)

print("----------")

# 如果在函数调用时没有指定参数,它就是一个空元组。
print_info(10)
# 10
# ()

  • **kwargs 表示接受任意数量的关键字参数(也就是以键值对形式传递的参数),这些参数会被封装成一个字典(dict):
def print_info(arg1, **kwargs):
    print(arg1)
    print(kwargs)


# 后面的参数被封装为了一个字典。
print_info(70, a=60, b=50)
# 70
# {'a': 60, 'b': 50}

四、匿名函数

所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

  • Python 使用 lambda 来创建匿名函数。

  • lambda 只是一个表达式,函数体比 def 简单很多。

  • lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。

  • lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。

  • 虽然 lambda 函数看起来只能写一行,却不等同于 C 或 C++ 的内联函数,内联函数的目的是调用小函数时不占用栈内存从而减少函数调用的开销,提高代码的执行速度。

  • 句式

lambda [arg1 [,arg2,.....argn]]:expression
  • 代码示例
# lambda 变量名 : 方法体。
sum_lambda = lambda a, b: a + b

print(sum_lambda(1, 2))
# 3

  • 可以将匿名函数封装在一个函数内,这样可以使用同样的代码来创建多个匿名函数:
def do_operation(operation, num1, num2):
    result = operation(num1, num2)
    return result


# 使用匿名函数进行加法操作。
addition = lambda x, y: x + y
print(do_operation(addition, 5, 3))
# 8

# 使用匿名函数进行乘法操作。
multiplication = lambda x, y: x * y
print(do_operation(multiplication, 5, 3))
# 15

五、强制位置参数

在Python中,函数默认情况下是允许使用关键字参数的,也就是说,参数可以按任意顺序进行传递。

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

  • 使用函数形参语法 * 表示只能限定关键字形参。

  • 代码示例

"""
  1.a, b为限定位置形参。
      2.斜杠(/)与普通形参分隔。
  3.m, n为普通参数。(兼容位置或关键字)
      4.星号(*)与普通形参分隔。
  5.kw1, kw2为限定关键字形参。
  """


def my_func(a, b, /, m, n, *, kw1, kw2):
    pass


my_func(1, 2, 3, n=4, kw1=5, kw2=6)

六、结束语


“-------怕什么真理无穷,进一寸有一寸的欢喜。”

微信公众号搜索:饺子泡牛奶

你可能感兴趣的:(Python,python,开发语言)