当前位置: 首页 > 编程日记 > 正文

3.3.2 函数参数不得不说的几件事

  函数定义时圆括号内是使用逗号分隔开的形式参数列表(parameters),一个函数可以没有参数,但是定义和调用时一对圆括号必须要有,表示这是一个函数并且不接受参数。函数调用时向其传递实参(arguments),根据不同的参数类型,将实参的值或引用传递给形参。

  定义函数时,对参数个数并没有限制,如果有多个形参,则需要使用逗号进行分隔。例如,下面的函数用来接受2个参数,并输出其中的最大值。

1 def printMax(a,b):
2     if a > b :
3         print(a,'is the max')
4     else:
5         print(b,'is the max')

注意:这里只是为了,演示,忽略了一些细节,如果输入的参数不支持比较运算符,则会出错,可以参考后面第7章中介绍的异常结构来解决这个问题。

  对于绝大多数情况下,在函数内部直接修改形参的值不会影响实参。例如:

 1 def addOne(a):
 2     print(a)   #输出原变量 a 的值
 3     a += 1
 4     print(a)   #这条语句会得到一个新的变量a
 5 
 6 a = 3
 7 addOne(3)
 8 
 9 # 3
10 # 4
11 
12 print(a)
13 # 3

  从运行结果可以看出,在函数内部修改了形参a的值,但是当函数运行结束以后,实参a的值并没有被修改。然而,在有些情况下,可以通过特殊的方式在函数内部修改实参的值,例如:

 1 >>> def modify(v):             #修改列表元素值
 2     v[0] += 1
 3 
 4     
 5 >>> a = [2]
 6 >>> modify(a)
 7 >>> a
 8 [3]
 9 >>> 
10 >>> 
11 >>> def modify(v,item):       #为列表增加元素
12     v.append(item)
13 
14     
15 >>> a = [2]
16 >>> modify(a,3)
17 >>> a
18 [2, 3]
19 >>> 
20 >>> 
21 >>> 
22 >>> def modify(d):            #修改字典元素值或为字典增加元素
23     d['age'] = 38
24 
25     
26 >>> a = {'name':'Dong','age':37,'sex':'Male'}
27 >>> 
28 >>> modify(a)
29 >>> 
30 >>> a
31 {'name': 'Dong', 'sex': 'Male', 'age': 38}
32 >>> 

  也就是说,如果传递给函数的是Python可变序列,并且在函数内部使用下标或序列自身支持的方式为可变序列增加、删除元素或修改元素值时,修改后的结果是可以反映到函数之外的,即实参也得到了相应的修改。

1 默认值参数

  在定义函数时,Python支持默认参数,即在定义函数时为形参设置默认值。在调用带有默认值参数的函数时,可以不用为设置了默认值的参数进行传值,此时函数将会直接使用函数定义时设置的默认值,也可以通过显式赋值来替换其默认值。也就是说,在调用函数时是否为默认值参数传递实参是可选的,具有较大的灵活性。带有默认值参数的函数定义语法如下:

1 def 函数名(...,形参名 = 默认值):
2     函数体

  可以使用 函数名.__defaults__ 随时查看函数所有默认值参数的当前值,其返回值为一个元组,其中的元素依次表示每个默认值参数的当前值。

 1 >>> def say(message,times = 1):
 2     print((message + ' ')* times)
 3 
 4     
 5 >>>
 6 >>> 
 7 >>> dir(say)
 8 ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', 
'__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__',
'__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] 9 >>> 10 >>> say.__defaults__ 11 (1,) 12 >>>

  调用该函数时,如果只为第一个参数传递实参,则第二个参数使用默认值 1 ;如果为第二个参数传递参数,则不再使用默认值 1 ,而是使用调用者显式传递的值。

1 >>> say('hello')
2 hello 
3 >>> 
4 >>> say('hello',3)
5 hello hello hello 
6 >>> 
7 >>> say('hi',5)
8 hi hi hi hi hi 
9 >>> 

注意:在定义带有默认值参数的函数时,默认值参数必须出现在函数参数列表的最右端,任何一个默认值参数右边都不能再出现非默认值参数。

注意:一般情况下,都是调用函数时为其传递参数,这时形参的值由调用函数时实参的值确定。但如果函数的默认值参数不是调用时传递的,而是通过其他方式对其赋值,那么默认值参数的值可能会在函数定义是确定,而不是函数调用时。例如:

 1 >>> i = 5
 2 >>> def demo(v):
 3     print(v)
 4 
 5     
 6 >>> i = 6
 7 >>> demo(i)
 8 6
 9 >>> 
10 >>> i = 5
11 >>> 
12 
13 >>> def demo(v = i):     #等价于def demo(v = 5):
14     print(v)             #相当于定义函数时设置默认值参数 5 
15  
16     
17 >>> i = 6
18 >>> 
19 >>> demo()
20 5
21 >>> 

注意:多次调用函数并且不为默认值参数传递值时,默认值参数只在第一次调用时进行解释,对于列表,字典这样可变类型的默认值参数,这一点可能会导致很严重的逻辑错误,而这种错误或许会耗费大量精力来定位和纠正。例如:

 1 >>> 
 2 >>> def demo(newitem,old_list=[]):
 3     old_list.append(newitem)
 4     return old_list
 5 
 6 >>> 
 7 >>> print(demo('5',[1,2,3,4]))
 8 [1, 2, 3, 4, '5']
 9 >>> 
10 >>> print(demo('aaa',['a','b']))
11 ['a', 'b', 'aaa']
12 >>> 
13 >>> print(demo('a'))
14 ['a']
15 >>> 
16 >>> print(demo('b'))
17 ['a', 'b']
18 >>> 
19 >>> print(demo('c'))
20 ['a', 'b', 'c']
21 >>> 

  上面的函数使用列表作为默认值参数,由于其可记忆性,连续多次调用该函数而不给该参数传值,再次调用时将保留上一次调用的结果,从而导致很难发现的错误。下面的代码就不存在这个问题:

1 >>> 
2 >>> def demo(newitem,old_list=None):
3     if old_list is None:
4         old_list = []
5     old_list.append(newitem)
6     return old_list
7 
8 >>> 

2 关键字参数

  关键字参数主要指调用函数时的参数传递方式,与函数定义无关。通过关键字参数可以按参数名字传递值,实参顺序可以和形参顺序不一致,但不影响参数值的传递结果,避免了用户需要牢记参数位置和顺序的麻烦,使得函数的调用和参数传递更加灵活方便。

 1 >>> 
 2 >>> def demo(newitem,old_list=None):
 3     if old_list is None:
 4         old_list = []
 5     old_list.append(newitem)
 6     return old_list
 7 
 8 >>> 
 9 >>> 
10 >>> 
11 >>> 
12 >>> def demo(a,b,c = 5):
13     print(a,b,c)
14 
15     
16 >>> 
17 >>> demo(3,7)
18 3 7 5
19 >>> 
20 >>> demo(a=7,b=3,c=6)
21 7 3 6
22 >>> 
23 >>> demo(c=8,a=9,b=0)
24 9 0 8
25 >>> 

3 可变长度参数

  可变长度参数在定义函数时主要有两种形式:*parameter 和 **parameter,前者用于接受任意多个实参并将其放在一个元组中,后者接受类似于关键字参数一样显式赋值形式的多个实参并将其放入字典中。

  下面代码演示了第一种形式可变长度参数的用法,即无论调用该函数时传递了多少实参,一律将其放入元组中:

 1 >>> 
 2 >>> def demo(*p):
 3     print(p)
 4 
 5     
 6 >>> demo(1,2,3)
 7 (1, 2, 3)
 8 >>> 
 9 >>> #其实 1,2,3 本身就是元组
10 >>> a = 1,2,3
11 >>> type(a)
12 <class 'tuple'>
13 >>> 
14 >>> demo(1,2,3,4,5,6,7)
15 (1, 2, 3, 4, 5, 6, 7)
16 >>> 

  下面的代码演示了第二种形式可变长度参数的用法,即在调用函数时自动将接收的参数转换为字典:

 1 >>> 
 2 >>> def demo(**p):
 3     for item in p.items():
 4         print(item)
 5 
 6         
 7 >>> demo(x = 1,y = 2,z = 3)
 8 ('y', 2)
 9 ('z', 3)
10 ('x', 1)
11 >>> 

注意:Python定义函数时可以同时使用位置参数、关键字参数、默认值参数和可变长度参数,但是除非真的很必要,否则请不要这样用,因为这会使得代码非常混乱而严重降低可读性,并导致程序查错非常困难。另外,一般而言,一个函数如果可以接受很多不同类型参数的话,很可能是函数设计得不好,例如函数功能过多,需要进行必要的拆分和重新设计,以满足模块高内聚的要求。

4 传递参数时的序列解包

  调用含有多个参数的函数时,可以使用Python列表、元组、集合、字典以及其他可迭代对象作为实参,并在实参名称前加一个星号,Python解释器将自动进行解包,然后传递给多个单变量形参。

 1 >>> 
 2 >>> seq = [1,2,3]
 3 >>> 
 4 >>> demo(*seq)
 5 6
 6 >>> 
 7 >>> tup = (1,2,3)
 8 >>> 
 9 >>> demo(*tup)
10 6
11 >>> 
12 >>> 
13 >>> dic = {1:'a',2:'b',3:'c'}
14 >>> demo(*dic)
15 6
16 >>> 
17 >>> set = {1,2,3}
18 >>> demo(*set)
19 6
20 >>> 
21 >>> demo(*dic.values())
22 abc
23 >>> 
24 >>> demo(*dic.keys())
25 6
26 >>> 
27 >>> demo(*dic.items())
28 (1, 'a', 2, 'b', 3, 'c')
29 >>> 

小提示:

(1)字典对象作为实参时默认使用字典的“键”,如果需要将字典中的“键:值”元素作为参数则需要使用items()方法明确说明,如果需要将字典的“值”作为参数则需要调用字典的values()方法明确说明;

(2)实参中元素个数与形参个数必须相等,否则将出现错误。

注意:调用函数时如果对实参使用一个星号(*)进行序列解包,那么这些解包后的实参将会被当做普通位置参数对待,并且会在关键参数和使用两个星号(**)进行序列解包的参数之前进行处理。

 1 >>>  
 2 >>> def demo(a,b,c):   #定义函数
 3     print(a,b,c)
 4 
 5     
 6 >>> 
 7 >>> demo(*(1,2,3))     #调用,序列解包
 8 1 2 3
 9 >>> 
10 >>> demo(1,*(2,3))     #位置参数和序列解包同时使用
11 1 2 3
12 >>> 
13 >>> demo(1,*(2,),3)
14 1 2 3
15 >>> 
16 >>> 
17 >>> demo(a = 1,*(2,3))          #序列解包相当于位置参数,优先处理
18 Traceback (most recent call last):
19   File "<pyshell#47>", line 1, in <module>
20     demo(a = 1,*(2,3))          #序列解包相当于位置参数,优先处理
21 TypeError: demo() got multiple values for argument 'a'
22 >>> 
23 >>> demo(b = 1,*(2,3))
24 Traceback (most recent call last):
25   File "<pyshell#49>", line 1, in <module>
26     demo(b = 1,*(2,3))
27 TypeError: demo() got multiple values for argument 'b'
28 >>> 
29 >>> 
30 >>> demo(c = 1,*(2,3))
31 2 3 1
32 >>> 
33 >>> 
34 >>> 
35 >>> 
36 >>> demo(**{'a':1,'b':2},*(3,))   #序列解包相当于位置参数,优先处理
37 SyntaxError: iterable argument unpacking follows keyword argument unpacking
38 >>> 
39 >>> 
40 >>> 
41 >>> 
42 >>> 
43 >>> demo(*(3,),**{'a':1,'b':2})
44 SyntaxError: invalid character in identifier
45 >>> 
46 >>> demo(*(3,),**{'a':1,'b':2})
47 Traceback (most recent call last):
48   File "<pyshell#72>", line 1, in <module>
49     demo(*(3,),**{'a':1,'b':2})
50 TypeError: demo() got multiple values for argument 'a'
51 >>> 
52 >>> 
53 >>> demo(*(3,),**{'c':1,'b':2})
54 3 2 1
55 >>> 

转载于:https://www.cnblogs.com/avention/p/8597775.html

相关文章:

wpf 对控件进行截图,获取快照

有时候我们项目&#xff0c;在执行某个操作后&#xff0c;会生成一些数据结果&#xff0c;如报表一类的东西&#xff0c;我们需要对结果进行保存&#xff0c;甚至是生成word文档。 那么首先获取到控件快照就最基本的条件。 生成快照的静态方法类 using System; using System.Co…

【java】兴唐第二十一节(LinkedList和泛型)

LinkedList知识点 1、实现了Iterable接口的类具有迭代功能。 2、List接口为Collection的子类&#xff0c;表示线形数据列表&#xff0c;其实现类有&#xff1a;ArrayList(数组线性表)与LinkedList(链表) 算了不多说了&#xff0c;上图吧 3、ArrayList是一个可变数组&#xff…

Elgg网站迁移指南

转载地址&#xff1a; http://blog.sina.com.cn/s/blog_84068de60100vr21.html Elgg官方文档上的网站迁移部分是有问题的——缺少了一些重要步骤&#xff0c;而且过程更麻烦。正确的方法如下&#xff1a; 备份网站文件&#xff0c;包括uploads文件夹导出数据库在数据库文件中&a…

INFO:在InstallShield中修改安装包压缩.cab包的大小

如果我们用InstallShield打包一个数据非常大的安装包&#xff08;Basic MSI和InstallScript MSI工程类型&#xff09;&#xff0c;默认情况下安装包会产生多个.cab文件&#xff0c;这里简单说明我们如何修改安装包中.cab文件的大小。首先&#xff0c;有个信息大家需要知道&…

MEF依赖注入实例

什么是MEF 先来看msdn上面的解释&#xff1a;MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展&#xff0c;而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码&#xff0c;避免生成脆弱的硬…

Data - 数据思维 - 上篇

1 - 概念与定义 如果分析思维是一种结构化思考的体现&#xff0c;那么数据分析思维&#xff08;简称数据思维&#xff09;则是以数据为依托的结构化分析方式。 不同于“我觉得”、“以前是怎样”、“其他人如何”这些直觉化、经验化、类比化的思考方式&#xff0c;数据思维是以…

新生选课系统使用指南

建议选用IE6或者IE7浏览器。 打开浏览器&#xff0c;地址栏输入202.200.112.200&#xff0c; 或者202.200.112.202&#xff0c; 或者202.200.112.210。按回车键。 输入学号和身份证号&#xff08;如果修改过密码&#xff0c;则输入新密码&#xff09;。点“登录”。 点 “学生…

【java】兴唐第二十三节课(暑期第一节TreeSet)

预警&#xff1a;进入暑期培训的博主即将高产似母猪&#xff0c;敬请博友期待。 1、给类添加构造方法 alt shift s 选择Generate Construct using Fields 2、map两种遍历方法 方法一&#xff1a; 获取所有的key值&#xff0c;根据key值获取value值 代码实现&#xff1a; Se…

程序设计分析(开篇)——混沌初开,顿悟设计

一直以来&#xff0c;不断的进行着项目的设计、开发&#xff0c;然而&#xff0c;差的设计&#xff0c;痛苦的维护、编码&#xff0c;让我不断的审视自己的设计是否有问题&#xff0c;在最近的一些思考、理解中&#xff0c;终于有了一些领悟&#xff0c;总结一下过去的设计&…

源代码管理工具调查

任务说明&#xff1a; 一、找出并了解当前较为流行的几种源代码管理工具&#xff08;至少三种&#xff09;&#xff1b; 1、 Visual Source Safe( 简称 VSS )2、 SVN(Subversion) - CVS(Concurrent Version System)的替代和升级版本3、 ClearCase 二、建立表格对这些源代码管理…

从零开始学Go之接口(一):接口

接口是双方约定的一种合作协议。接口实现者不需要关心接口会被怎样使用&#xff0c;调用者也不需要关心接口的实现细节。 接口是一种类型&#xff0c;也是一种抽象结构&#xff0c;不会暴露所含数据的格式、类型及结构。 声明&#xff1a; 接口类型是由一组方法签名定义的集合 …

【java】兴唐第二十四节课

HashMap中put函数的源码分析&#xff1a; &#xff08;一&#xff09;知识点&#xff1a; 1、方法resize&#xff08;&#xff09;的作用是扩容 2、 if ((p tab[i (n - 1) & hash]) null)其中n-1代表最后一个元素的下标&#xff0c;经过和hash的&后获取当前存储nod…

找不到可安装的ISAM”的问题

问题描述&#xff1a; 在 Access 或Sql Server中收到“Could not find installable ISAM”&#xff08;找不到可安装的 ISAM&#xff09;错误信息或者丢失某些文件类 解决方法&#xff1a; 1.注册表编辑器使用不当可能导致严重问题&#xff0c;可能需要重新安装操作系统。Micro…

修改mysql的时间/时区

# 背景 往db中insert数据发现时间不对&#xff0c;因为是新DB&#xff0c;所以猜测是mysql设置不对 # 解决方法 方法一&#xff1a;通过mysql命令行模式下动态修改 show variables like "%time_zone%"; 查看时区 --------------------------| Variable_name | Value…

【java】兴唐第二十五节课(异常和log4j的使用)

异常 1、try catch finally语法&#xff08;附带多重catch&#xff09; 代码实现&#xff1a; public static void main(String[] args) {try {int i 1/0;}catch(ArithmeticException e){System.out.println("出现数学运算异常&#xff1a;" e);}catch(ArrayIndex…

CentOS 命令提示符颜色及样式详解

命令提示符&#xff1a;prompt CentOS下查看当前命令提示符格式&#xff1a; 1 [rootlocalhost ~]# echo $PS1 #显示当前使用的PS1样式 2 [\u\h \W]\$ 命令提示符参数如下&#xff1a; \d &#xff1a;#代表日期&#xff0c;格式为weekday month date&#xff0c;例如&#…

Max_user_connections 与Max_connections 与max_connect_errors

对于连接数的设置&#xff0c;show variables里有三个参数可以对它进行控制&#xff0c;max_connections与max_user_connections以及max_connect_errors。下面对这三个参数相关描述。 max_connections&#xff1a;针对所有的账号所有的客户端并行连接到MYSQL服务的最大并行连接…

压力变动力,存储追求高效率

企业的数据存储量每年都要大幅增长&#xff0c;但是IT预算呈现紧缩趋势。这就是企业面临的最大存储难题&#xff0c;即如何平衡数据增长与提高存储利用率和降低成本之间的关系。 非结构化数据带来的难题 存储最直接的压力来自于不断增长的数据量。今天&#xff0c;我们面对的是…

Hadoop学习之路(三)Hadoop-2.7.5在CentOS-6.7上的编译

下载Hadoop源码 1、登录官网 2、确定你要安装的软件的版本 一个选取原则&#xff1a; 不新不旧的稳定版本 几个标准&#xff1a; 1&#xff09;一般来说&#xff0c;刚刚发布的大版本都是有很多问题 2&#xff09;应该选择某个大版本中的最后一个小版本 阅读编译文档 1、准备一…

static String valueOf(XXX xxx)

1 package day01;2 /**3 * static String valueOf(XXX xxx)4 * 字符串提供了一组静态的重载的valueOf方法,作用5 * 是将其他类型转换为字符串6 * author ta7 *8 */9 public class Demo10 { 10 public static void main(String[] args) { 11 int a 123; 12 …

【java】兴唐第二十五节课小程序学生卡转账小系统(自己写的异常)

1、StuCard.java public class StuCard {public static void TransMoney(int source, int money, int target) {money - target;if(money < 0) {throw new NotEnoughMoneyException("余额不足");}System.out.println("商家的余额为&#xff1a;" sour…

【JQUBAR1.1】jQuery 插件发布

【JQUBAR1.1】jQuery 插件发布 JQUBAR1.1 简介 2010-11-22在博客园发布了柱状图JQUBar1.0 jQuery 插件。现将该插件升级为1.1版本。 1.1版本修复了部分bug&#xff0c;同时新增以下功能&#xff1a; 1.可自定义坐标颜色 2.可自定义X,Y轴坐标名称 3.Y轴动态坐标自动建立 4.Y…

ssh远程操作服务器

登录方式 ssh account192.168.xxx.xxx 输入密码 远程上传下载文件 上传&#xff1a; scp filepath acount192.168.xxx.xxx:path filepath为要上传的文件路径path为上传到服务器的储存路径 下载&#xff1a; scp acount192.168.xxx.xxx:filepath path filepath为要下载的文件路径…

【java】兴唐第二十三节课作业

已知如下&#xff1a; 下表为某班级四次考试成绩单&#xff0c; 要求使用HashMap<String, Integer>存储每次考试的成绩&#xff08;key键为姓名&#xff0c;value为成绩&#xff09;。要求使用LinkedList存储考试次数&#xff0c;有几次考试就有几个HashMap注意&#xf…

Data - 数据思维 - 中篇

6 - 模型与框架 利用现有的成熟的理论、模型与框架&#xff0c;结合实际业务情况&#xff0c;搭建分析框架&#xff0c;尽量确保数据分析维度的完整性&#xff0c;结果的有效性及正确性。 营销理论模型&#xff1a;4P、用户使用行为、STP理论、SWOT等。管理理论模型&#xff1a…

快速设置戴尔latitude笔记本的触摸板和指点杆

// TouchPadSettings.cpp : Defines the entry point for the console application.// by windviki 2010/08/31// 转载请注明出处。//// 办公用的戴尔笔记本除了触摸板&#xff0c;还在键盘中间有一个指点杆&#xff08;point stick&#xff09;// 打字很不习惯&#xff0c;经常…

Ubuntu 10.10系统安装手记

原来一直在公司用Ubuntu&#xff0c;感觉做开发是相当不错的&#xff0c;特别那种各种利用命令的方式真是太高效了。所以现在想把笔记本也装上&#xff0c;弄了半天&#xff0c;也遇到不少问题&#xff0c;记下来备忘一下。 虚拟机还是双系统 磁盘里面好多东西&#xff0c;基本…

php值传参,引用传参以及对象传参

传值&#xff1a;是把实参的值赋值给行参 &#xff0c;那么对行参的修改&#xff0c;不会影响实参的值传引用 &#xff1a;真正的以地址的方式传递参数传递以后&#xff0c;行参和实参都是同一个对象&#xff0c;只是他们名字不同而已对行参的修改将影响实参的值说明&#xff1…

用一行代码高效的求一个列表的平方和

最近看到一个笔试题&#xff0c;考察的都是 Python 中的高阶函数 题目如下&#xff1a;用一行代码高效的求一个列表的平方和(不能用 sum 函数) 分析 1.先将列表中每个值作平方&#xff1a; 立即想到 map 函数&#xff0c;假设列表是 range(10)&#xff0c;那么这个列表中平方是…

【java】第二十二节课(HashSet)

1、使用HashSet建立对象、添加元素并使用两种方法遍历 代码实现 public class SetDemo {public static void main(String[] args) {Set<String> set new HashSet();set.add("猴子");set.add("八戒");set.add("唐僧");set.add("沙僧…