本文转载自: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. 分析函数(Analytic Functions)

    在OLAP这类系统或者DW这类数据库中,作为某份报表的数据源,我们常常需要在某个存储过程中编写复杂的运算代码来汇总数据.分析函数便具备这样的能力,引用多行的数据值来进行多层面的聚合运算,在数据子集中进 ...

  2. IOS系统中使用zepto的live事件绑定不了的一个办法

    IOS系统中使用zepto的live事件绑定不了的一个办法: 对事件对象添加样式:cursor:pointer

  3. angularjs transclude demo

    <!doctype html> <html lang="en" ng-app="expanderModule"> <head> ...

  4. 一些practice和总结(转载)

    转自 http://boundary.cc/2013/05/java-app-server-develop/ by JOKER on 2013/05/05 最近状态不是很好,负能量堆到积爆表,静下心来 ...

  5. Python 学习记录

    记录一些 学习python 的过程 -------------------------------------- 1. 初始学习 @2013年10月6日 今天开始学习python 了 遇到好多困难但是 ...

  6. 【ACM】魔方十一题

    0. 前言打了两年的百度之星,都没进决赛.我最大的感受就是还是太弱,总结起来就是:人弱就要多做题,人傻就要多做题.题目还是按照分类做可能效果比较好,因此,就有了做几个系列的计划.这是系列中的第一个,解 ...

  7. 头文件中的#ifndef/#define/#endif 的作用

    在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量重定义的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定 ...

  8. [ionic开源项目教程] - 第4讲 通Service层获取数据列表

    第4讲:通Service层获取数据列表 上一讲中页面的基本架构已完成,这一讲介绍如何通过service层从服务器请求数据,在通过controller层为载体,显示到视图层. 1.在services.j ...

  9. 使用Phalcon开发工具碰到的数据库问题"Table 'XXX' doesn't exist in database when dumping meta-data for XXX"

    使用Phalcon开发工具,通过命令行生成程序框架 设置好config.php,在对数据库进行读取.保存数据的时候出现了问题“Table 'XXX' doesn't exist in database ...

  10. HDU pog loves szh II (数的处理)

    题意: 给一个序列,找出两个数字a和b(可以相等但不可相同),要求(a+b)%p的结果最大. 思路: 先将所有元素模p,再排序.要找出a和b,分两种情况,a+b>p和a+b<p.第一种,肯 ...