设为首页 加入收藏

TOP

Python之函数与变量(一)
2017-02-08 08:16:34 】 浏览:4972
Tags:Python 函数 变量

编程语言中的函数与数学中的函数是有区别的:数学中的函数有参数(输入),就会有相应的结果(输出)。编程语言中的函数有输入,不一定会返回结果。编程语言中的函数其实就是一个用于完成某个特定功能的相关代码的代码段 。那么哪些代码语句应该被整合到一起定义为一个函数呢?这取决于你想让这个函数完成的功能是什么。


为什么要将这个代码段定义成一个函数呢?这其实就是函数的作用。假设我们在编写一个可供用户选择的菜单程序,程序启动时需要打印一遍菜单列表,而且程序运行过程中用户也可以随时打印菜单列表,也就是说打印菜单列表的代码段可能要多次被用到,假设每次打印的菜单列表都是一样的,而且列表很长,那么我们是否应该每次在需要打印菜单的时候重复执行相同的代码呢?那么当我们需要增加或者减少一个菜单项时怎么办呢?显然我们需要在每个打印菜单的代码点都进行修改。如果我们把打印菜单的相关代码拿出来定义为一个函数,又会出现这样的场景呢?我们只需要在需要打印菜单列表的地方使用这个函数;当需要添加或减少一个菜单项时,只需要修改这个函数中的内容即可,程序的维护和扩展成本大大降低;同时,我们这个程序的代码会更加简洁,而且有条理性更加便于阅读,而不是一坨乱糟糟的让人看着就想重写的东西。当然,如果你要打印的是多级菜单,你可以通过函数的参数或全部变量通知该函数要打印的是几级菜单。总结一下,编程语言中的函数的作用就是实现代码的可重用性,提高代码可维护性、扩展性和可读性


高级编程语言通常会提供很多内置的函数来屏蔽底层差异,向上暴露一些通用的接口,比如我们之前用到的print()函数和open()函数。除此之外,我们也可以自定义我们需要的函数。由于函数本身也是程序代码的一部分,因此为了标识出这段代码是一个函数通常需要使用特定的格式或关键字。另外还涉及到参数、方法名称、返回值等相关问题的约束。


通常写成这个样子:


Python中函数的调用方式与其他大部分编程语言都一样(其实我目前使用过的编程语言当中,只有shell是个另类;好吧,其实它只是个脚本语言):函数名(参数)


先来说下形参和实参的概念:


重点需要说下函数的各种不同种类的参数。函数的参数可以分为以下几种:


不同编程语言对以上几种函数参数的支持各不相同,但是位置参数是最基本的参数类型,基本上所有的编程语言都支持。以下是一个常见编程语言的对比表格(Y表示支持,N表示不支持):


可见只有Python支持全部参数类型,而且只有Python支持关键字参数;另外,C、Java和Go都不支持默认参数,其中Java和Go与它们支持的方法重载特性有关(具体可以看下这个帖子),并且它们可以通过方法重载实现默认参数的功能。


下面我们以一个自定义的打印函数来对以上各种参数进行说明:


位置参数,顾名思义是和参数的顺序位置和数量有关的。函数调用时,实参的位置和个数要与形参对应,不然会报错。


默认参数:是指给函数的形参赋一个默认值,它是一个有默认值的位置参数。当调用函数时,如果为该参数传递了实参则该形参取实参的值,如果没有为该参数传递实参则该形参取默认值。


默认参数的应用场景:参数值在大部分情况下是固定/相同的。比如这里打印一个班中学生的姓名和年龄,这个班大部分为同龄人(年龄相同),这时我们就可以给“年龄”这个形参赋一个默认的值。


age取的是函数调用时传递过来的实参


函数调用时没有给形参age传值,因此age取的是默认值


可见,我们明明是想传递18给形参age的,结果18被赋给了name,而age仍然取得是默认值。上面已经提到过,位置参数只是可以让我们少传一些参数,但是不能改变参数的位置和顺序。另外,这也说明了默认参数为什么一定要放在后面:因为实参与形参是从前到后一一有序的对应关系,也就是说在给后面参数传值的时候,不论前面的参数是否有默认值,必须要先给前面的参数先赋值。


这里要说明的是:默认参数只能相应的减少实参的个数,但是不能增加实参的个数。这个很容易想明白,不做过多解释,只是为下面的可变长(参数)做铺垫。


可变(长)参数:顾名思义,是指长度可以改变的参数。通俗点来讲就是,可以传任意个参数(包括0个)。


可变(长)参数的应用场景:通常在写一个需要对外提供服务的方法时,为了避免将来添加或减少什么新的参数使得所有调用该方法的代码点都要进行修改的情况发生,此时就可以用一个可变长的形式参数。


再次强调:位置参数、默认参数、可变长参数在函数定义中的位置不能变。


方法调用时,只传递了一个实参,该实参会按照函数中参数的定义位置赋值给形参name,因此name的值为‘Tom’;而形参age没有接收到实参,但是它有默认值,因此它取的是默认值12;需要注意的是可变参数args也没有接收到传递值,但是打印出来的是一对小括号(),说明args参数在函数内部会被转换成tuple(元祖)类型,当没有接收到实参时便是一个空tuple。


与值传递一个实参的情况基本相同,只是默认参数接收到了传递值,不再取默认值。


比如,现在需要多接收并打印一个人的性别(F: 表示女,M: 表示男),可以这样用:


比如,现在需要多接收并打印一个人的性别(F: 表示女,M: 表示男)和籍贯信息,可以这样用:


当然,我们也可以直接将一个tuple或list实例传递给形参args,但是tuple实例前也要加上*号作为前缀:


你甚至可以将传递给形参name和age的实参也放到要传递的tuple实例中,但是最好不要这样做,因为很容易发生混乱:


由于args接收到实参之后会被转换成一个tuple(元祖)的实例,而tuple本身是一个序列(有序的队列),因此我们可以通过下标(args[n])来获取相应的实参。但是我们需要在函数使用文档中写明args中各实参的传递顺序及意义,并且在获取args中的元素之前应该对args做非空判断。因此函数的定义及调用结果应该是这样的:


函数定义:


函数调用及结果:


关键字参数:顾名思义,是指调用函数时通过关键字来指定是为哪个形参指定的实参,如name="Tom", age=10。


关键字参数应用场景:关键字参数一方面可以允许函数调用时传递实参的顺序与函数定义时声明形参的顺序不一致,提高灵活性;另一方面,它弥补了可变长参数的不足。想一下,如果想为上面定义了可变长参数的函数只传递“籍贯”参数就必须同时传递“性别”参数;另外还要不断地判断tuple的长度,这是相当不方便的。而关键参数可以通过关键字来判断某个参数是否有传递值并获取该参数的实参值。


方法调用时,只传递了一个实参,该实参会按照函数中参数的定义位置赋值给形参name,因此name的值为‘Tom’;而形参age没有接收到实参,但是它有默认值,因此它取的是默认值12;可变参数args也没有接收到传递值,因此args的值是一个空元组;重点需要注意的是关键字参数kwargs也没有接收到传递值,但是其打印值为一个空字典(dict)实例。


与值传递一个实参的情况基本相同,只是默认参数接收到了传递值,不再取默认值。


可以不按照形参声明的顺序传递实参


以非key=value的形式传递所有参数:


可见后面多余的两个实参都传递给了可变长参数args


最后一个addr参数以key=value的形式传递:


最后两个参数sex和addr都以key=value的形式传递:


由以上两个示例可见,对于除去传递给位置参数

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python之函数进阶 下一篇Python中的eva l()、exec()及其相..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目