【转载】Python中如何高效实现两个字典合并,三种方法比较。

本文转载自: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。

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

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

时间: 2024-12-20 08:00:32

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

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

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景 协同过滤(collaborative filtering)是推荐系统常用的一种方法.cf的主要思想就是找出物品相似度高的归为一类进行推荐.cf又分为icf和ucf.icf指的是item collaborative filtering,是将商品进行分析推荐.同理ucf的u指的是user,他是找出知趣相似的人,进行推荐.通常来讲icf的准确率可能会高一些,通过这次参加天猫大数据比赛,我觉得只有在数据量非

Struts学习笔记(三)struts2中获得request、response和session的三种方法

struts2中获得request.response和session的三种方法   (1)非IoC方式 方法一:使用org.apache.struts2.ActionContext类,通过它的静态方法getContext()获取当前Action的上下文对象. ActionContext ctx = ActionContext.getContext(); ctx.put("liuwei", "andy"); //request.setAttribute("l

交换两个整数的三种方法

package com.zby.bubble; /** * <class description> 三种方法交换两个整数的值 * * @author zby * */ public class Exchange { public static void main(String[] args) { splitLine(); exchange1(Integer.MAX_VALUE, Integer.MAX_VALUE - 1); exchange1(99, 100); exchange1(Inte

Swift中,把NSData转换为Byte数组的三种方法

最近做IOS开发需要从一个NSData中读出数据.但是找不到相关文档.网上搜索也有人问,我看到有Objective-C的答案,但基本上没有Swift的方案. NSData的bytes是UnsafePointer<Void>类型,我不知道怎样直接获取到他的值(如果你知道,请一定要告诉我). 所以我自己摸索了一下把NSData转换为[Byte]的方法,希望起到抛砖引玉的作用. 下面直接在PlayGround中演示: 最后我采用的当然是第三种方法: import Foundation var b:[

php求两数组交集的三种方法

题目: 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1],nums2 = [2,2]输出: [2]示例 2: 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]输出: [9,4]说明: 输出结果中的每个元素一定是唯一的. 我们可以不考虑输出结果的顺序. 解法一:迭代一个数组 思路分析: 迭代一个数组,判断是否存在另外一个数组 PHP 代码实现: /** * @param Integer[] $nums1 * @pa

Java小案例——交换两个数值的三种方法

要求: 互换两个数的值 方法一:借助第三方变量 /** * 借助第三方变量对两个值进行互换 * @author Administration * */ public class ExchangeValue { public static void main(String[] args) { int a = 10; int b = 15; System.out.println("a的值:"+a+",\tb的值:"+b); System.out.println(&quo

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

1. DataTable dt;                               //假设字段为name, dt已经保存了数据dt.rows[0]["name"] == System.DBNull.Value;  //判断第一行数据的name字段是否为空 2. DataTable dt;                          //假设字段为name, dt已经保存了数据   dt.rows[0]["name"].ToString() == &

php保留两位小数的三种方法

around:a.代码: <?php $num1 = round(5,2); $num2 = round(5.123,2); echo $num1.PHP_EOL; echo $num2.PHP_EOL; b.输出: 5 5.12 sprintf:a.代码: <?php $num1 = sprintf('%.2f',5); $num2 = sprintf('%.2f',5.123); echo $num1.PHP_EOL; echo $num2.PHP_EOL; b.输出: 5.00 5.12

Win7系统与它的Virtualbox中安装的Ubuntu14.04共享信息的几种方法

虚拟机是每个程序员必备的工具.本文根据最新版VirtualBox用户手册的提示,通过自己的亲自实践,给出了Win7系统与运行在其中的VirtualBox 5.0.2中的Ubuntu 14.04共享信息的三种方法,而不仅仅是建立二者的共享文件夹. 在学习新的技术时,或者做不同的测试时,为了节省硬件的目的,我们常常安装虚拟机,并在其中安装不同的操作系统.我们把运行在硬件的本来的那个操作系统称为主操作系统 (host OS),而把运行在虚拟机上面的操作系统称为客操作系统 (guest OS).这时,在