相同的Python代码为相同的输入字典返回不同的结果

相同的Python代码为相同的输入字典返回不同的结果,python,python-3.x,dictionary,python-3.5,Python,Python 3.x,Dictionary,Python 3.5,我有一本名为dico的字典,其中包含以下信息: ('libc6-i386', '1.06') : lib32tinfo5 ('lib32c-dev', '') : lib32tinfo-dev ('libc6-x32', '2.16') : libx32tinfo5 ('libc6-i386', '2.4') : lib32ncursesw5 ('libc-dev', '') : libncursesw5-dev ('libncurses5-dev', '5.9+201505

我有一本名为dico的字典,其中包含以下信息:

('libc6-i386', '1.06')  :  lib32tinfo5
('lib32c-dev', '')  :  lib32tinfo-dev
('libc6-x32', '2.16')  :  libx32tinfo5
('libc6-i386', '2.4')  :  lib32ncursesw5
('libc-dev', '')  :  libncursesw5-dev
('libncurses5-dev', '5.9+20150516-2ubuntu1')  :  libncurses5-dbg
('libc6-dev', '')  :  libncursesw5-dev
('libc6-dev-x32', '')  :  libx32tinfo-dev
('libc6-i386', '2.16')  :  lib32tinfo5
('libncursesw5-dev', '5.9+20150516-2ubuntu1')  :  libncursesw5-dbg
当我调用comparePackages(dico)时,对于相同的输入,我会不断得到不同的结果,例如:

('lib32c-dev', 'Not Specified') lib32tinfo-dev
('libc6-dev', 'Not Specified') libncursesw5-dev
('libc-dev', 'Not Specified') libncursesw5-dev
('libc6-i386', '2.4') lib32ncursesw5
('libc6-x32', '2.16') libx32tinfo5
('libncurses5-dev', '5.9+20150516-2ubuntu1') libncurses5-dbg
('libc6-dev-x32', 'Not Specified') libx32tinfo-dev
('libc6-i386', '2.16') lib32tinfo5
('libncursesw5-dev', '5.9+20150516-2ubuntu1') libncursesw5-dbg

这是我的comparePackages函数

import apt_pkg
apt_pkg.init_system()

"""
    Function that compares package versions and keeps the most recent one.
    @param : dictionary
        package_dictionary :
            keys : tuple
            values : string
"""

def comparePackages(package_dictionary):
    if(type(package_dictionary) is dict):
        list_keys = list(package_dictionary.keys()) #list of tuples
        list_values = list(package_dictionary.values()) #list of strings
        #list_keys, list_values = list(package_dictionary.items())
        dic = {}

        for x,y in zip(range(0,len(list_keys)-1),range(0,len(list_values)-1)):
            #if 2 tuples have the same package name
            if(list_keys[x][0] == list_keys[x+1][0]):
                print("Start comparing")

                #second element of the tuple x
                a = str(list_keys[x][1])

                #second element of the tuple x+1
                b = str(list_keys[x+1][1])

                #compare versions
                vc = apt_pkg.version_compare(a,b)

                if vc > 0:
                    #a>b
                    print("a>b")
                    max_version = a

                elif vc == 0:
                    #a==b
                    print("a==b")
                    max_version = a 

                elif vc < 0:
                    #a<b
                    print("a<b")
                    max_version = b

                if(max_version is '') :
                    max_version = 'Not Specified'
                #create a dict that for each package name has the most recent version
                dic[(list_keys[x][0],max_version)] = list_values[y]

            else:
                version = list_keys[x][1]
                if(version is '') :
                    version = 'Not Specified'
                dic[(list_keys[x][0],version)] = list_values[y]

        for k,v in dic.items():
            print(k,v)

    else:
        raise TypeError("Argument of comparePackages must be a dictionary.")

我想知道为什么以及如何纠正它。最后,我所需要的是一个字典,它为元组中的每个包提供最新版本。为同一个包丢失2个值中的1个不是问题。谢谢。

这不是对您的问题的直接回答,但您需要解决该问题,以获得工作和可复制的行为。(如果您的bug在修复后消失,我也不会感到震惊)

在代码中:

for key, value in zip(dic.keys(), dic.values())
以及:

这假设键和值按相同顺序排序。这不一定是真的,这会导致基于返回订单的执行差异。 您应该使用
项目

for key, value in dict.item())
以及:

因此:

成为:

for idx, (x, y) in enumerate(zip(list_keys, list_values)):
或者,更像蟒蛇:

for k, v in package_dictionary.items():

另一个解决方案是使用OrderedDict。

这不是问题的直接答案,但您需要解决该问题,以获得工作和可复制的行为。(如果您的bug在修复后消失,我也不会感到震惊)

在代码中:

for key, value in zip(dic.keys(), dic.values())
以及:

这假设键和值按相同顺序排序。这不一定是真的,这会导致基于返回订单的执行差异。 您应该使用
项目

for key, value in dict.item())
以及:

因此:

成为:

for idx, (x, y) in enumerate(zip(list_keys, list_values)):
或者,更像蟒蛇:

for k, v in package_dictionary.items():
另一个解决方案是使用订购的ICT。

我得到了答案

“”“ 比较软件包版本并保留最新版本的函数。 @参数:字典 套装词典: 关键字:元组 值:字符串 “”“

导入apt\u软件包
apt_pkg.init_系统()
def比较外翻(x,l):
如果(类型(l)为列表):
最大版本=l[0]
对于范围(1,透镜(l)-1内的e:
#vc=结果反比较版本
vc=apt\u包装版本\u比较(l[e],l[e+1])
如果((vc>0)和(apt软件包版本比较(l[e],最大版本))>0:
#a> b
最大版本=l[e]
elif((vc==0)和(apt软件包版本比较(l[e],最大版本))>0):
#a==b
最大版本=l[e]
elif((vc<0)和(apt软件包版本比较(最大版本,l[e+1]))<0):
#我得到了答案

“”“ 比较软件包版本并保留最新版本的函数。 @参数:字典 套装词典: 关键字:元组 值:字符串 “”“

导入apt\u软件包
apt_pkg.init_系统()
def比较外翻(x,l):
如果(类型(l)为列表):
最大版本=l[0]
对于范围(1,透镜(l)-1内的e:
#vc=结果反比较版本
vc=apt\u包装版本\u比较(l[e],l[e+1])
如果((vc>0)和(apt软件包版本比较(l[e],最大版本))>0:
#a> b
最大版本=l[e]
elif((vc==0)和(apt软件包版本比较(l[e],最大版本))>0):
#a==b
最大版本=l[e]
elif((vc<0)和(apt软件包版本比较(最大版本,l[e+1]))<0):

#a您需要向我们展示—符合您的数据格式的最小dict文本、此数据的预期结果以及当前代码返回的输出。字典是无序的,每次运行Python解释器都会生成一个新的随机哈希种子,以防止恶意的DOS攻击(攻击者很容易使您的Python进程过载). 因此,将键与“下一个”键进行比较是行不通的。@MartijnPieters-。。。一个新的随机散列种子被产生,以防止一类恶劣的拒绝服务攻击。。。我想更好地理解这一点。可以提供一些详细解释这一点的资源链接吗?@JasonEstibeiro:请参阅中的方框注释。我注意到我无法比较两个键,这就是为什么我创建了一个键列表和一个值列表。我必须比较字典键中存在多次的包的版本。您需要向我们显示-符合您的数据格式的最小dict文本、此数据的预期结果以及代码当前返回的输出。字典无序,每次运行Python解释器都会生成一个新的随机散列种子,以防止恶意的DOS攻击(攻击者很容易使Python进程过载)。因此,将键与“下一个”键进行比较是行不通的。@MartijnPieters-。。。一个新的随机散列种子被产生,以防止一类恶劣的拒绝服务攻击。。。我想更好地理解这一点。可以提供一些详细解释这一点的资源链接吗?@JasonEstibeiro:请参阅中的方框注释。我注意到我无法比较两个键,这就是为什么我创建了一个键列表和一个值列表。我必须比较字典密钥中存在多次的包的版本。谢谢您的回答。我按照你的建议做了,但是当我列出\u键,list\u values=list(package\u dictionary.items())时,我得到了一个ValueError:太多的值无法解包(预期为2个)。键和值按相同的顺序排序,前提是没有对字典进行编辑。但是,在解释器的两次运行之间,它们的顺序将不同。@Marc:请按照此答案中所述更新
for
循环。然而,这个答案并不能解决你的问题;如果您每次都以相同的顺序将条目传递到
OrderedDict
中,则可能会对您有所帮助。事实上,我做了一个测试,以验证条目是否已排序,并且是否正确。x和y的值相同。但是我确实用@aluriak建议的一切更新了我的代码。对于zip中的x,y(范围(0,len(list_键)-1),范围(0,len(list_值)-1))必须保留,因为我需要访问typle内容和
for idx, (x, y) in enumerate(zip(list_keys, list_values)):
for k, v in package_dictionary.items():
import apt_pkg
apt_pkg.init_system()

def compareVersion(x,l):
    if(type(l) is list):
        max_version = l[0]
        for e in range(1, len(l)-1):
            #vc = resultat de compare versions
            vc = apt_pkg.version_compare(l[e],l[e+1])

            if ((vc > 0) and (apt_pkg.version_compare(l[e],max_version)) > 0):  
                #a>b
                max_version = l[e]

            elif ((vc == 0) and (apt_pkg.version_compare(l[e],max_version)) > 0):
                #a==b
                max_version = l[e] 

            elif ((vc < 0) and (apt_pkg.version_compare(max_version,l[e+1])) < 0):
                #a<b
                max_version = l[e+1]

        if(max_version is '') :
            max_version = 'Not Specified'
                #create a dict that for each package name has the most recent version
        #print(x,l,max_version)
        return max_version
    else:
        raise TypeError("Argument must be a list.")


def comparePackages(package_dictionary):
    if(type(package_dictionary) is dict):
        list_keys = list(package_dictionary.keys()) #list of tuples
        list_values = list(package_dictionary.values()) #list of strings

        dic = {}

        for x in list_keys: #for each element in the list
            l = []
            for h in list_keys:
                if x[0] == h[0]: #if nom package x == nom package h
                    a = str(x[1]) #a = version du package x
                    b = str(h[1]) #b = version du package y
                    if(l.count(a) == 0):
                        l.append(a)
                    if(l.count(b) == 0):
                        l.append(b)
            max_version = compareVersion(x,l)   
            dic[(x[0],max_version)] = list_values[list_keys.index(x)]

        return dic    
    else:
        raise TypeError("Argument of comparePackages must be a dictionary.")