No estoy seguro de por qué .items () devuelve un resultado diferente que .viewitems () al comparar dos diccionarios como una lista.

# python 2.7
d1 = {'1': '10', '2': '20'}  # two key-value pairs
d2 = {'3': '30', '4': '40', '5': '50'}  # three key-value pairs
print d1 <= d2  # True
print d1.items() <= d2.items()  # True
print d1.viewitems() <= d2.viewitems()  # False
print d1.items()  # [('1', '10'), ('2', '20')]
print d1.viewitems()  # dict_items([('1', '10'), ('2', '20')])

Parece que la principal diferencia entre .items () y .viewitems () es que .items () devuelve una lista y viewitems () devuelve una cosa dict_items.

¿Se recomienda usar d1 <= d2 en lugar de elementos de vista o elementos al comparar el tamaño entre los diccionarios?

Además, ¿cómo hacer que esto sea compatible con Python 3?

2
Aeternus 8 oct. 2019 a las 20:57

3 respuestas

La mejor respuesta
d1 <= d2  # True

Es complicado. Y es detalle de implementación. Consulte ¿Qué hacen los operadores de comparación en los diccionarios? TL; DR: un diccionario más corto siempre es más pequeño que uno más largo en Python 2 .x, pero los dictados no se pueden ordenar en Python 3.x.

d1.items() <= d2.items()  # True

Esta es una comparación lexicográfica de listas. Ese resultado True es confiable, ya que cada clave en d1 es menor que cualquier clave de d2. Para hacer que este código sea compatible de forma cruzada, tendría que convertirlo a la lista explícitamente.

d1.viewitems() <= d2.viewitems()  # False

Esta es una comprobación de tipo subconjunto. Ese resultado False es confiable, porque d1 no es un "subdivisión" de d2. Para hacer que este código sea compatible, use six.viewitems o similar.

¿Se recomienda usar d1 <= d2 en lugar de elementos de vista o elementos al comparar el tamaño entre los diccionarios?

Tampoco, use len(d1) <= len(d2) para comparar el tamaño entre los diccionarios.

5
wim 8 oct. 2019 a las 18:20

Su propósito declarado es comparar los tamaños de diccionario ... lo cual no ha hecho en absoluto. Necesitas usar len para eso.

Lo que hizo es comparar elementos de dos tipos muy diferentes. items devuelve una lista de tuplas, que se comparan fácilmente con los algoritmos conocidos: verifique los elementos en el orden dado para obtener un valor relativo. La comparación de tuplas es familiar para la mayoría de nosotros.

Sin embargo, un dict_view es un objeto de vista dinámica, no una simple lista de valores. Estás comparando un objeto más complejo, no simplemente ejecutando una lista obvia de valores. La definición de ordenamiento y comparación no es fácilmente visible para nosotros, simples mortales.

0
Prune 8 oct. 2019 a las 18:06

He respondido una pregunta similar aquí: Comportamiento inconsistente entre dict.values () y dict.keys () igualdad en Python 3.xy Python 2.7

La clave a tener en cuenta es que dict.viewitems() es un objeto Set-like. Lo que significa que cuando haces d1.viewitems() <= d2.viewitems() estás comparando verificar si d1.viewitems() es un subconjunto de d2.viewitems(), no la comparación de longitud que esperabas. Consulte la documentación aquí: https://docs.python.org/2.7 /library/sets.html#set-objects

Operation         Equivalent  Result
s.issubset(t)     s <= t      test whether every element in s is in t
s.issuperset(t)   s >= t      test whether every element in t is in s

Nota: porque dict.viewitem() es un objeto collections.Set, no tiene métodos .issubset o .issuperset como set.

Observe lo siguiente:

>>> d1 = {'a': 0}
>>> d2 = {'a': 1}
>>> d3 = {'a': 0, 'b': 1}
>>> d1.viewitems() <= d3.viewitems()
True     # because [('a', 0)] is a subset of [('a', 0), ('b', 1)]
>>> d2.viewitems() <= d3.viewitems()
False    # because [('a', 1)] is not a subset of [('a', 0), ('b', 1)]

Sin embargo, para responder a su pregunta, como han mencionado otros, para comparar el tamaño, use len(d1) <= len(d2) en su lugar.

1
r.ook 8 oct. 2019 a las 19:26
58291713