本文转载自: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. lua简化cocos2dx的Action动画序列

    情景 今天写代码时,又要写一个很常见的动画,就是变大变小模拟那个弹性的赶脚,很常用但写起来挺麻烦,封装一下用起来就简单多了. 当然我也知道有缓动动画(EaseAction)可以实现反弹效果,但这不是重 ...

  2. HDU 4622 Reincarnation 后缀自动机

    模板来源:http://blog.csdn.net/zkfzkfzkfzkfzkfzkfzk/article/details/9669747 解法参考:http://blog.csdn.net/dyx ...

  3. Linux下scp的用法

    scp就是secure copy,一个在linux下用来进行远程拷贝文件的命令.有时我们需要获得远程服务器上的某个文件,该服务器既没有配置ftp服务器,也没有做共享,无法通过常规途径获得文件时,只需要 ...

  4. Spring Injection with @Resource, @Autowired and @Inject

    August 1st, 2011 by David Kessler Overview I’ve been asked several times to explain the difference b ...

  5. Android电源管理-休眠简要分析

    一.开篇 1.Linux 描述的电源状态 - On(on)                                                 S0 -  Working - Standb ...

  6. 第十篇 PO核心功能及流程详解

    详见链接:http://bbs.erp100.com/thread-272866-1-1.html1. P2P lifecycleP2P是procure to pay的缩写,p2p循环值得就是采购到付 ...

  7. Selenium系列教程(2)

    Selenium RC(Selenium远程控制) Selenium RC是一个用Java编写的,允许用户使用无论哪种编程语言对基于Web的应用程序构建测试脚本的工具.Selenium RC克服了Se ...

  8. hibernate学习笔记6--Criteria查询方式、完整小练习(开发步骤)

    一.Criteria查询方式没有sql语了,因此更加面向对象一些.Criteria是一种比HQL更面向对象的查询方式:Criteria的创建方式: Criteria c = s.createCrite ...

  9. Android uiautomator gradle build system

    This will guide you through the steps to write your first uiautomator test using gradle as it build ...

  10. HDU 1158 Employment Planning

    又一次看题解. 万事开头难,我想DP也是这样的. 呵呵,不过还是有进步的. 比如说我一开始也是打算用dp[i][j]表示第i个月份雇j个员工的最低花费,不过后面的思路就完全错了.. 不过这里还有个问题 ...