本文转载自:http://www.pythoner.com/13.html

Python中将两个字典进行合并操作,是一个比较常见的问题。本文将介绍几种实现两个字典合并的方案,并对其进行比较。

对于这个问题,比较直观的想法是将两个字典做相加操作,赋值给结果字典,其代码为:

方法一:

dictMerged1 = dict( dict1.items() + dict2.items() )

  然而,该方法合并时所用时间较长,效率更高的代码为:

方法二:

dictMerged2 = dict( dict1, **dict2 )

  这种方法使用的是dict()工厂方法(Python2.2以上版本)。如果输入参数是另一个字典(此处为dict1),则调用该工厂方法时会从dict1中复制内容生成新的字典。该工厂方法从Python2.3版本开始,允许接受字典或关键字参数字典进行调用。但应当注意,对于这种调用方式,dict()最多只接受一个参数(或者说是一组name=value的可变长参数),而不会再接受另一个字典。因此直观上的简单使用dict1与dict2两个参数的方法会提示如下错误:

>>> dictMerged = dict( dict1, dict2 )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: dict expected at most 1 arguments, got 2

  

这也就是我们看到上面的方法2中使用的是**dict2的原因。熟悉C的朋友应当注意,在这里*的意思并不代表指针,这是Python中可变长函数参数的写法(关于可变长函数参数的相关知识见下文)。在这里,**的意思是基于字典的可变长函数参数。

方法2执行的是如同下面方法3中的代码,即先将dict1拷贝给dictMerged,在执行update()操作:

dictMerged3 = dict1.copy()
dictMerged3.update( dict2 )

  

对于第一步的复制操作而言,这种使用内建方法copy()的复制方式,和方法2中的复制结果是一样的,但根据《Core Python Programming (2nd edition)》一书中7.3.2节所述,从已存在字典中生成新字典的方式dictNew = dict( dictOld )较内建方法dictNew = dictOld.copy()会慢一些,因此书中推荐使用copy()方法。

因此,从这几种方式看来,方法3的效率最高,并且代码也比较易读。

Python可变长度的函数参数

在编程的过程中,我们可能会遇到函数参数个数不固定的情况。这时就需要使用可变长度的函数参数来实现我们的功能。在Python中,有两种变长参数,分别是元组(非关键字参数)和字典(关键字参数)。其调用方式是:func( *tuple_grp_nonkw_args, **dict_grp_kw_args ),下面将详细介绍这两种变长参数。

1.元组变长参数

当函数调用中包括一个元组变长参数*tuple_grp_nonkw_args时,除去前面固定位置参数和关键字参数的其余参数将按顺序插入一个元组进行访问,这和C语言中的varargs的功能相同。

假设有这样一个函数(其中,positional_arg是位置固定的标准调用参数,keyword_arg是关键字参数):

示例:

def foo( positional_arg, keyword_arg='default', *tuple_arg ):
print "positional arg: ", positional_arg
print "keyword_arg: ", keyword_arg
for each_additional_arg in tuple_arg:
print "additional_arg: ", each_additional_arg

  我们使用一些示例来了解它是怎么工作的:

>>> foo(1)
positional arg: 1
keyword_arg: default >>> foo(1, 2)
positional arg: 1
keyword_arg: 2 >>> foo(1, 2, 3)
positional arg: 1
keyword_arg: 2
additional_arg: 3
>>> foo(1,2,3,4,5,6)
positional arg: 1
keyword_arg: 2
additional_arg: 3
additional_arg: 4
additional_arg: 5
additional_arg: 6
>>> foo(1,2,(3,4,5,6))
positional arg: 1
keyword_arg: 2
additional_arg: (3, 4, 5, 6)

  

  

2.字典变长参数

既然Python中允许关键字参数,那么也应该有一种方式实现关键字的变长参数,这就是字典变长参数。

字典变长参数中,额外的关键字参数被放入了一个字典进行使用。字典中,键为参数名,值为相应的参数值。其表示方式是放在函数参数最后的**开头的参数,如**dict_grp_kw_args。(需要注意的是,**被重载以不与幂运算混淆。)

以下是一个字典变长参数的示例函数:

def foo( positional_arg, keyword_arg='default', **dict_arg ):
print "positional arg: ", positional_arg
print "keyword_arg: ", keyword_arg
for each_dict_arg in dict_arg.keys():
print "dict_arg: %s=>%s" % ( each_dict_arg, str( dict_arg[each_dict_arg] ) )

  下面是一段演示结果:

>>> foo(1, 2, a="b")
positional arg: 1
keyword_arg: 2
dict_arg: a=>b

  

3.注意

函数调用的完整表达形式为:
func( positional_args, keyword_args, *tuple_grp_nonkw_args, **dict_grp_kw_args )

在使用的过程中,所有参数都是可选的,但应当注意的是:上面四种参数的位置是不可调换的!

4.扩展:C语言中的变长参数

作为一个学艺不精的人,之前一直不知道C语言中也是有可变参数的,直到在《Pointers on C》(中译名:《C和指针》,人民邮电出版社)中看到相关内容(7.6节)。

4.1 stdarg宏

在C语言中,可变参数是通过stdarg宏来实现的,它是标准库的一部分。这个头文件声明了一个类型va_list和三个宏va_startva_argva_end。我们可以声明一个类型为va_list的变量,与三个宏配合使用,访问参数的值。

下面是一个计算多个数值平均值的示例函数:

//下面是一个计算多个数值平均值的示例函数:
#include <stdarg.h> float avg( int n, ... ) {
va_list var_arg;
float sum = 0; // 准备访问变长参数
va_start( var_arg, n ); // 添加取自变长参数列表的值
for ( i = 0; i < n; i += 1) {
sum += va_arg( var_arg, int );
} // 完成处理变长参数
va_end( var_arg); return sum / n;
}

  

其中,函数参数中的...作为参数占位符,代表数量和类型不可知的一些参数。

函数中声明了一个va_list类型的变量var_arg用于访问参数列表的不确定部分。这个变量通过调用va_start进行初始化,其中,第一个参数是va_list变量的名字,第二个参数是占位符前最后一个有名字的参数。初始化过程将var_arg变量指向可变参数中的第一个参数。

va_list的使用中,包括两个参数,第一个参数是va_list变量,第二个参数是下一个参数的类型。本例中假设输入数据均为整型,因此均设置为int,而在一些情况下,下一个参数的类型会由之前的参数来决定。

最后,调用va_end结束变长参数的访问。

4.2 限制与注意事项

可变参数是从头到尾进行访问的,即可以在访问了数个参数之后结束,但不可以一开始就访问中间的参数。

另外,由于可变参数部分没有原型,因此作为可变参数传递给函数的值都做了缺省的函数类型提升。

从va_start的调用可以看出,如果使用可变参数必须有至少一个确定的参数,否则无法使用va_start。

对于这些宏,有两个基本限制:其一,无法判断实际存在的参数数量;其二,不能判断参数类型。

还需要注意的是,一旦在使用中写错下一个参数的类型,后果可能不堪设想。

【转载】Python中如何高效实现两个字典合并,三种方法比较。的更多相关文章

  1. Linux中让终端输入变为非阻塞的三种方法

    介绍 在linux下每打开一个终端,系统自动的就打开了三个文件,它们的文件描述符分别为0,1,2,功能分别是"标准输入"."标准输出"和"标准错误输出 ...

  2. python面对对象编程------3:写集合类的三种方法

    写一个集合类的三种方法:wrap,extend,invent 一:包装一个集合类 class Deck: def __init__( self ): self._cards = [card6(r+1, ...

  3. 【机器学习算法-python实现】协同过滤(cf)的三种方法实现

    (转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景       协同过滤(collaborative filtering)是推荐系统经常使用的一种方法.c ...

  4. c语言实现两数交换的三种方法

    实现变量的值互相交换的三种不同方法 方法一:利用第三个变量来实现数值的交换 int tmp; tmp = a; a = b; b = tmp; 此方法直观,简易.不易出错,推荐使用 方法二:利用两个变 ...

  5. python中打印金字塔和九九乘法表的几种方法

    # 打印九九乘法表for i in range(1,10): for j in range(1,i+1): # x=i*j # print(i,'*',j,'=',x,end=' ') print(' ...

  6. vuex中怎么把‘库’中的状态对象赋值给内部对象(三种方法)

    一.通过computed的计算属性直接赋值 import store from '@/store/store' export default{ name: 'count', data(){ retur ...

  7. java交换两个值的三种方法 经典

    1.中间变量(在开发中常用) int c=a; a=b; b=c; System.out.println("a的值: "+a+" b的值: "+b); 2.按位 ...

  8. Struts2 在Action中获取request、session、servletContext的三种方法

    首页message.jsp: <body> ${requestScope.req }<br/> ${applicationScope.app }<br/> ${se ...

  9. 关于SQLServer数据库中字段值为NULL,取出来该字段放在DataTable中,判断datatable中该字段值是否为NULL的三种方法

    1. DataTable dt;                               //假设字段为name, dt已经保存了数据dt.rows[0]["name"] == ...

随机推荐

  1. ffmpeg mp4转yuv

    mp4转yuv ffmpeg -i test.mp4 test.yuv 播放yuv ffplay.exe -f rawvideo -video_size 1280x720 -i test.yuv

  2. python下载图片

    import re import  urllib.request   def getHtml(url): page = urllib.request.urlopen(url) html = page. ...

  3. dataTables表格分页排序等交互

    官网: https://www.datatables.net/ 中文参考网站: http://datatables.club/ datatables+bootstrap示例: http://sandb ...

  4. PDO数据库

    <?php //定义数据源$dsn = "mysql:dbname=testa;host=localhost"; //造PDO对象$pdo = new PDO($dsn,&q ...

  5. Redis 网络通信及连接机制学习

    看了这篇文章 http://blog.nosqlfan.com/html/4153.html 本文所述内容基于 Redis2.6 及以上版本. 注:在客户端通过 info 命令可以查看服务器版本信息, ...

  6. JAVA反射技术的使用

    前言 在开发html使用jquery提交post的时候,可以使用jquery遍历from元素里面的input元素实现参数组合,这样就不用手动打参数了,特别是在参数很多的时候,费神费时. 我开发Andr ...

  7. HTML中多媒体的应用_Flash/MP3/设置可以活动的文字

    一.HTML中多媒体的应用_falsh动画(往网页中插入Flash动画) 1. Flash动画插入第一种方法:使用<embed>...</embed>标记动画会自动缩小 属性: ...

  8. LA 2678 Subsequence

    有一个正整数序列,求最短的子序列使得其和大于等于S,并输出最短的长度. 用数组b[i]存放序列的前i项和,所以b[i]是递增的. 遍历终点j,然后在区间[0, j)里二分查找满足b[j]-b[i]≥S ...

  9. HDU 2577 How to Type【DP】

    题意:给出一个字符串,有大写有小写,问最少的按键次数.然后打字的这个人有一个习惯,打完所有的字之后,指示灯要关闭. dp[i][j]表示打到第i个字母,j有0,1两个值表示指示灯开或者关的状态 然后就 ...

  10. linux系统查看磁盘分区使用空间

    Df命令是linux系统以磁盘分区使用空间:df -hl