写点什么

Python 中关于函数的那点事

作者:Java学术趴
  • 2022 年 7 月 31 日
  • 本文字数:6872 字

    阅读完需:约 23 分钟

Python中关于函数的那点事

👨‍🎓作者:Java 学术趴

🏦仓库:GithubGitee

✏️博客:CSDN掘金InfoQ云+社区

💌公众号:Java 学术趴

🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。

🙏版权声明:文章里的部分文字或者图片来自于互联网以及百度百科,如有侵权请尽快联系小编。微信搜索公众号 Java 学术趴联系小编。

☠️每日毒鸡汤:这个社会是存在不公平的,不要抱怨,因为没有用!人总是在反省中进步的!

👋大家好!我是你们的老朋友 Java 学术趴。任何的语言都离不开函数,都包括内置函数和自定义函数,函数的作用就是对功能进行封装以便于无效调用。


1. Python 中的函数

1.1 函数的基础

  • 函数就是一段含有特殊功能的代码块

  • 使用函数完成代码的复用

  • Python 中函数名是不可以重复的。

  • Python 中的函数名应该小写,函数的形参,函数中的变量名应该小写(建议)

  • Python 中存在两个一个名字的变量,其实并不是定义了一个新的变量,而是对该变量进行了重新的赋值

函数定义


def + 关键字 + 小括号 + 冒号 + 换行缩进 + 代码块(定义一个函数)def 函数名(): 代码块复制代码
复制代码

函数调用


函数名() # 直接调用复制代码
复制代码

函数说明文档


函数内容的第一行可以用字符串进行函数说明复制代码
复制代码

1.2 基本函数

  • 没有参数的函数


# Python中的函数# 定义函数。不存在返回值的# 形式参数可以不指定变量的类型,这样传递的时候可以传递任意的类型,但是主要 str + int 报错def add(a: int, b: int): # 函数的第一行可以使用字符串来说明这个函数的功能。使用 """三个双引号包裹"""    # 自动生成:点击三个双引号然后enter,自动生成函数的说明文档    """   这一个进行两个数字相加的函数   :param a:   :param b:   :return: None   """    print(a + b)# 调用函数add(1, 2)# 3# 调用函数。存在返回值# Python中的函数# 定义函数def add(a: int, b: int):    """   这一个进行两个数字相加的函数   :param a:   :param b:   :return: a+b   """    return a + b# 调用函数print(add(1, 2))复制代码
复制代码
  • 存在参数的函数


# 定义含有不同类型以及个数的参数的函数def export(string: str, height: float):    print('%s的身高是%f' % (string, height))    print('{}的身高是{}'.format(string, height))# 调用函数export('小明', 65.4)export('小张', 45.7)复制代码
复制代码

当存在参数的时候,必须保证函数的参数和传递的参数类型以及数量都一致

1.3 参数的分类

1.3.1 必选参数

形式参数是一种虚拟的变量,不占用内存空间

  • 必选参数 : 在使用的时候必须给定数量一致的实参值。形参数量 == 实参数量

  • 语法格式:


# Python中的函数# 定义函数def add(a, b):    """   这一个进行两个数字相加的函数   :param a:   :param b:   :return: a+b   """    return a + b# 可以传递字符串print(add('abc', 'bcd'))# abcbcd# 可以传递数字print(add(1, 2))# 3# 必选参数中,必须保证实参和形参的数量是一致的。否则报错# print(add(1))# 报错复制代码
复制代码

1.3.2 默认参数

  • 默认参数(缺省参数): 可以在声明函数的时候给定参数的默认值。如果调用者没有给这个参数重新赋值,那么就使用默认值。

  • 语法格式: def add(a: int = 20, b: int = 30)


# 默认参数def add(a: int = 20, b: int = 30):    return a + b# 调用函数# 当不传递实参的时候,他会使用默认值print(add())# 50# 当只传递一个值的时候,他会按照顺序进行赋值print(add(10))# 40# 即使在定义形参的时候指定了参数是int类型,其实在调用的时候也可以传递其他类型的值# 所有说在定义函数形参的时候不一定要指定参数的数据类型print(add('abc', 'bcd'))# abcbcd# 可以在一个函数中给定必选参数和默认参数"""当存在必选参数和默认参数的时候,必须把默认参数放到最后。def add(a: int = 30, b: int): 报错因为在调用的时候,实参是按照顺序进行赋值的。如果把默认参数放到前面,把必选参数放到前面的时候在调用的时候只给定一个实参,那么这个实参会赋值给默认参数,此时修改了默认参数的值,但是没有给必选参数赋值,就会报错所以在使用的时候,将默认参数写在参数的最后"""def add(a: int, b: int = 30):    return a + b# 调用函数# 这里至少需要传递一个实参,因为函数的第一个形参是必选参数print(add(10))# 40# 当传递两个的时候,他会进行顺序赋值,此时也修改了默认参数的值print(add(10, 50))# 60复制代码
复制代码

1.3.3 可选参数

  • 可选参数(不定长参数): 一个函数在调用的有时候传递的实参比当初声明的函数参数要多。这个就是不定长函数。定义函数时不用声明参数名字,加了星号(*)的变量 args 会存放所有未命名的变量参数。args 为元组; 而加( ** )的变量 kwargs 会存放命名参数,即形如 key=value 的参数,kwargs 为字典;

  • 语法格式: def show(*args)。其中这个 args 不是固定的,可以是任意的变量名,一般用 args 接收。是一个元组类型


# 可选参数# Python中的函数名应该小写def show(*args):    """   *ages代表的是一个可选参数,在调用这个函数的时候可以传递任意多个实参   args是一个元组,所有传递的实参会合成一个元组   :param args:   :return:   """    # 判断可选参数的类型以及其中的数据    print(type(args))    # <class 'tuple'>    print(args)    # (1, 2, 3, 4)    # 既然是元组据可以使用下标来获取其中的某个元素    print(args[0])    # 1    # 定义一个数组接收元组中的数据。函数中的变量名小写    char: list = []    for data in args:        char.append(data)        pass    return char    pass# 调用函数传递不同的实参。可以传递任意类型的数据print(show(1, 2, 3, 4))# [1, 2, 3, 4]# 可以传递任意类型的数据print(show([1, 2], 'abc', True))# [[1, 2], 'abc', True]复制代码
复制代码

1.3.4 关键字参数

  • 关键字可变参数: ( ** )的变量 kwargs 会存放命名参数,即形如 key=value 的参数,kwargs 为字典

  • 语法格式: def show(**kwargs)。其中这个 kwargs 不是固定的,可以是任意的变量名,一般用 kwargs 接收。是一个字典类型


# 可选参数# Python中的函数名应该小写def show(**kwargs):    """   **kwargs 代表的是一个可选参数,在调用这个函数的时候可以传递任意多个实参   args是一个字典,所以说传递的参数需要是一个字典才可以   :param kwargs:   :return:   """    # 判断可选参数的类型以及其中的数据    print(type(kwargs))    # <class 'dict'>    print(kwargs)    # {'name': '张三', 'age': 20}    # 既然是元组据可以使用下标来获取其中的某个元素    print(kwargs['name'])    # 张三    # 定义一个数组接收元组中的数据。函数中的变量名小写    char: list = []    for key in kwargs:        char.append(key)        pass    return char    pass# 第一种:传递一个字典dictionary: dict = {'name': '张三', 'age': 20}# 直接传递一个字典会报错。需要加 **print(show(**dictionary))# 第二种:直接传递# 因为 **kwargs 获取到的是一个字典形式的数据# 所以这里传递的参数比较严格,如果是直接传递的必须是 变量名=数值 形式。# 其中 变量名代表字典中的key值,数值代表字典中的value值print(show(name='张三', age=20))# ['name', 'age']复制代码
复制代码

重点:在实际开发中,一般都是可选参数、关键字参数混合使用的


# 可选参数、关键字参数混合使用def mixing(*args, **kwargs): """     可选参数必须放在关键字参数之前   :param args: 元组   :param kwargs: 字典   :return:   """    print(args)    print(kwargs)    pass# 他会自己匹配类型,将单个的数据存储到 args 中,把键值对的数据存储到 kwargs 中mixing(1, True, 'abc', 3.14, name='张三')# (1, True, 'abc', 3.14)# {'name': '张三'}# 这种赋值方式会报错,必须把普通的类型写在前面,键值对的参数写到最后# mixing(name='张三', 1, True, 3.14, 'abc')# 这种写法会报错,必须把 可选参数写到关键字参数的前面# def mix(**kwargs, *args):
复制代码


1.4 函数的返回值

  • 函数执行完之后会返回一个对象,如果函数中存在 return 就返回实际的值,否则就返回 None

  • 返回值的类型可以是任意类型:返回值类型取决于 return 返回的类型

  • 一个函数中可以存在多个 return,但是只会返回一个 return 后面的值

  • 如果执行了 return 语句,那么就代表这个函数已经结束了


# 函数的返回值# 使用 return 返回函数的计算结果def add(a, b):    return a + bprint(add(1, 2))复制代码
复制代码

1.5 函数的嵌套使用

  • 在一个函数中可以调用另一个函数。和 Java 的使用方式一样


# 函数的嵌套调用# 使用 return 返回函数的计算结果def add(a, b):    return a + bdef substruction(a, b):    c: int = add(a, b)    return c - b# 函数的嵌套调用result: int = substruction(1, 2)print(result)# 1复制代码
复制代码

列题:定义一个函数,将一个列表中奇数位的元素存储到一个新的列表中


def odd(char):    # 定义一个列表存储奇数位的数据    list_new: list = []    # 定义一个变量来对应列表的下标值    index: int = 0    for data in char:        if index % 2 == 1:            list_new.append(data)            # pass只是在书写代码跳出代码块的,并不会对代码的执行产生影响            pass        index += 1        continue        pass    return list_newprint(odd(range(1, 11)))复制代码
复制代码

例题:将一个字典中的元素赋值到一个新的元素(对 value 的要求,长度必须是小于等于 2 的)


# 只获取一个字典的value的前两位,把这个前两位作为value值传递给一个新的字典def obtain(**kwargs):    # 定义一个新字典    wordbook: dict = {}    for key, value in kwargs.items():        # 将旧字典的key以及value值赋值给新的字典        if len(value) > 2:            # 关键代码。因为向字典中添加一个新元素的时候,如果在key存在会替换value值            # 如果key不存在会添加一个新的元素            # 所提在这里使用这种方式相当于直接在字典中添加 key--value            wordbook[key] = value[:2]            pass        else:            wordbook[key] = value            pass        pass    return wordbook# 调用函数dictionary: dict = {'name': '张三','hobby': ['游泳', '健身', '打豆豆'], 'room': 'Python1105班'}print(obtain(**dictionary))# {'name': '张三', 'hobby': ['游泳', '健身'], 'room': 'Py'}复制代码
复制代码

1.6 全局变量和局部变量

  • 他的原理和 Java 中的使用方式是一样的。函数中优先使用局部变量,满足就近原则。

局部变量: 就是在函数内部定义的变量

全局变量: 定义在函数的外边,可以全部的函数使用

在函数中修改全局变量


# 如果使用全局变量的时候直接拿来使用即可。不需要使用 global 关键字声明# 只有在修改变量值的时候需要使用 global 关键字声明复制代码
复制代码
  • Java 中修改全局变量的值


public class Test {    private static String name = "张三";    public static void main(String[] args) {        add(); // 周六   }    // Java中在一个函数中可以直接修改全局变量    public static void add(){        name = "李四";        System.out.println(name);   }}复制代码
复制代码
  • Python 中修改一个局部变量

  • 错误


# 全局变量和局部变量# 定义一个全局变量name: str = '张三'# 定义一个函数修这个全局变量def modify():    """   在一个函数中修改全局变量   此时这种形式不能修改,这种形式县相当于在函数中创建了一个name的局部变量   :return:   """    name = '李四'    print(name)    passmodify()# 李四print(name)# 张三。Python中修改全局变量和Java是不一样的# Java中直接获取就可以修改,而Python不可以复制代码
复制代码
  • 正确


# 全局变量和局部变量# 定义一个全局变量name: str = '张三'# 定义一个函数修这个全局变量def modify():    """   在一个函数中修改全局变量,必须在变量名的前面加上 global 关键字   此时的 变量name就不是函数中从新声明的一个局部变量name   而是全局变量中的name变量   :return:   """    # 如果使用全局变量的时候直接拿来使用即可。不需要使用 global 关键字声明    # 只有在修改变量值的时候需要使用 global 关键字声明    print(name)    global name    name = '李四'    print(name)    passmodify()# 李四 (函数中的name代表全局变量中的name)print(name)# 李四 (全局变量的name)复制代码
复制代码
  • 不可变类型:使用 global 关键字针对的是不可变的类型修改变量的值。比如:数字、字符串、元组等

  • 可变类型:

    直接改变其中的数据的时候需要使用 global 关键字


alobal charchar = [1, 2, 3, 4]复制代码
复制代码


   	2. **使用类型中的方法修改数据直接修改即可。不需要 global 关键字**复制代码
复制代码



char.append(5)复制代码
复制代码

测试代码:


# 全局变量和局部变量# 定义一个全局变量的list列表char: list = []# 定义一个函数修这个全局变量def modify():    """   当在函数中修改一个可变类型的数据的时候如果直接赋值需要使用 global 关键字   :return:   """    # 全局的变量名可以大写,函数中的变量名字、形参、函数名一般小写    # 直接赋值需要关键字    global char    char = [1, 2, 3, 4]    return char    passdef modify2():    """   如果使用列表对应的方法可以进行直接的添加数据和修改数据,不需要 global 关键字   :return:   """    char.append(5)    return char    pass# 直接修改需要关键字 globalprint(modify())# [1, 2, 3, 4]print(char)# [1, 2, 3, 4]# 使用列表中的方法修改不需要关键字print(modify2())# [1, 2, 3, 4, 5]print(char)# [1, 2, 3, 4, 5]复制代码
复制代码

1.7 匿名函数

1.7.1 匿名函数的基本语法

在 Python 中使用 lambda 关键字创建匿名函数,所谓匿名函数即这个函数没有名字,不用 def 关键字创建标准的函数。

匿名函数特点:

  • 使用 lambda 关键字去创建函数

  • 函数没有名字

  • 匿名函数冒号后面的表达式有且只有一个。注意:是表达式,而不是语句

  • 匿名函数自带 return,而这个 return 的结果就是表达式计算之后的结果

语法格式:

lambda 参数1,参数2,参数3:执行代码语句(这个代码语句必须是表达式)复制代码
复制代码

举例:


# 这个test并不是函数名,而是变量名,相当于把这个匿名函数赋值给了一个变量# 当在调用这个函数的时候使用这个变量名调用test = lambda x,y:x+yprint(test(1,3))# 4print(test(4,5))# 9复制代码
复制代码

换成普通函数的样子


# 此时的test叫做函数名def test(x,y): reuturn x+y复制代码
复制代码

1.7.2 lambda 与三元运算符

语法格式:


if a: belse: c复制代码
复制代码

能够由以下等效的表达式模拟:


b if a else c 复制代码
复制代码



'可以参军' if age > 18 else '继续上学'复制代码
复制代码

这样的表达式(二元运算)能够在 lombda 中,他们能够在 lambda 函数中实现选择逻辑:


greater = (lambda x, y: x if x > y else y)print(greater(3, 5))# 5greater(6, 2)# 6复制代码
复制代码



# 匿名函数可以参军var = (lambda age: '可以参军' if age > 18 else '不可以参军')# 调用匿名函数print(var(20))# 可以参军复制代码
复制代码

lambda 表达式可以在声明的时候直接赋值,可以进行直接调用


# 在定义lambda表达式的时候直接调用rs = (lambda x, y: x if x > y else y)(3, 4)print(rs)# 4复制代码
复制代码

一个参数使用 lambda 表达式


# 一个参数使用 lambda 表达式parameter = lambda x: x*800+1# 返回值是一个 int 类型,不能直接与字符串拼接,需要格式化操作print('结果是:{}'.format(parameter(1)))# 结果是:801print('结果是:%d' % parameter(1))# 结果是:801复制代码
复制代码

使用 lambda 的缺点:

  • lambda 只能写一个表达式,只能在简单的逻辑中进行使用。复杂的逻辑还是需要使用 def 进行定义函数

1.8 递归函数

递归函数:如果一个函数的内部不调用其他函数,而是自己本身的话,这个函数就是递归函数。



使用递归函数的要求:

  • 递归函数必须有一个结束条件,否则递归无法结束会一直递归下去,当到达最大递归的时候会报错

  • 递归函数的内部自己调用自己,不调用其他的函数


发布于: 3 小时前阅读数: 8
用户头像

Java学术趴

关注

还未添加个人签名 2022.07.02 加入

还未添加个人简介

评论

发布
暂无评论
Python中关于函数的那点事_7 月月更_Java学术趴_InfoQ写作社区