كيفية التأكد من أن الإملاء يحتوي على إملاء آخر دون تأكيد ديكتكونتينزسوبسيت في بيثون؟

StackOverflow https://stackoverflow.com//questions/21058230

سؤال

أنا أعرف assertDictContainsSubset يمكن القيام بذلك في python 2.7، ولكن لسبب ما تم إهماله في python 3.2.فهل هناك أي طريقة لتأكيد أن الإملاء يحتوي على إملاء آخر بدونه assertDictContainsSubset?

هذا لا يبدو جيدًا:

for item in dic2:
    self.assertIn(item, dic)

أي طريقة جيدة أخرى؟شكرًا

هل كانت مفيدة؟

المحلول

>>> d1 = dict(a=1, b=2, c=3, d=4)
>>> d2 = dict(a=1, b=2)
>>> set(d2.items()).issubset( set(d1.items()) )
True

وعلى العكس من ذلك:

>>> set(d1.items()).issubset( set(d2.items()) )
False

الحد: يجب أن تكون قيم القاموس قابلة للتجزئة.

نصائح أخرى

على الرغم من أنني أستخدم pytest، فقد وجدت الفكرة التالية في ملف تعليق.لقد كان الأمر رائعًا بالنسبة لي، لذلك اعتقدت أنه قد يكون مفيدًا هنا:

assert dict1.items() <= dict2.items()

لبيثون 3 و

assert dict1.viewitems() <= dict2.viewitems()

لبيثون 2.

إنه يعمل مع العناصر غير القابلة للتجزئة، لكن لا يمكنك معرفة العنصر الذي فشل في النهاية بالضبط.

المشكلة الكبيرة في الإجابة المقبولة هي أنها لا تعمل إذا كانت لديك قيم غير قابلة للتجزئة في قيم الكائنات الخاصة بك.والشيء الثاني هو أنك لن تحصل على أي نتائج مفيدة - ينجح الاختبار أو يفشل ولكنه لا يخبرك بالمجال المختلف داخل الكائن.

على هذا النحو، من الأسهل إنشاء قاموس فرعي ثم اختباره.بهذه الطريقة يمكنك استخدام TestCase.assertDictEquals() الطريقة التي ستمنحك مخرجات منسقة مفيدة جدًا في عداء الاختبار الخاص بك والتي توضح الفرق بين الفعلي والمتوقع.

أعتقد أن الطريقة الأكثر إمتاعًا وبيثونية للقيام بذلك هي من خلال فهم القاموس البسيط على هذا النحو:

from unittest import TestCase


actual = {}
expected = {}

subset = {k:v for k, v in actual.items() if k in expected}
TestCase().assertDictEqual(subset, expected)

ملاحظة: من الواضح أنه إذا كنت تجري الاختبار الخاص بك بطريقة تنتمي إلى فئة فرعية ترث من TestCase (كما ينبغي أن تكون بالتأكيد) فهذا مجرد self.assertDictEqual(subset, expected)

لقد نجح حل John1024 بالنسبة لي.ومع ذلك، في حالة الفشل فإنه يخبرك فقط False بدلاً من إظهار المفاتيح غير المتطابقة.لذا، حاولت تجنب طريقة التأكيد المهملة باستخدام طرق تأكيد أخرى ستنتج رسائل فشل مفيدة:

    expected = {}
    response_keys = set(response.data.keys())
    for key in input_dict.keys():
        self.assertIn(key, response_keys)
        expected[key] = response.data[key]
    self.assertDictEqual(input_dict, expected)

إليك المقارنة التي تعمل حتى لو كان لديك قوائم في القواميس:

superset = {'a': 1, 'b': 2}
subset = {'a': 1}

common = { key: superset[key] for key in set(superset.keys()).intersection(set(subset.keys())) }

self.assertEquals(common, subset)

يجيب هذا على سؤال أوسع قليلاً مما تطرحه ولكنني أستخدم هذا في أدوات الاختبار الخاصة بي لمعرفة ما إذا كان container يحتوي القاموس على شيء يشبه contained قاموس.هذا يتحقق المفاتيح والقيم.بالإضافة إلى ذلك يمكنك استخدام الكلمة الأساسية 'ANYTHING' للإشارة إلى أنك لا تهتم بكيفية تطابقها.

def contains(container, contained):
    '''ensure that `contained` is present somewhere in `container`

    EXAMPLES:

    contains(
        {'a': 3, 'b': 4},
        {'a': 3}
    ) # True

    contains(
        {'a': [3, 4, 5]},
        {'a': 3},
    ) # True

    contains(
        {'a': 4, 'b': {'a':3}},
        {'a': 3}
    ) # True

    contains(
        {'a': 4, 'b': {'a':3, 'c': 5}},
        {'a': 3, 'c': 5}
    ) # True

    # if an `contained` has a list, then every item from that list must be present
    # in the corresponding `container` list
    contains(
        {'a': [{'b':1}, {'b':2}, {'b':3}], 'c':4},
        {'a': [{'b':1},{'b':2}], 'c':4},
    ) # True

    # You can also use the string literal 'ANYTHING' to match anything
        contains(
        {'a': [{'b':3}]},
        {'a': 'ANYTHING'},
    ) # True

    # You can use 'ANYTHING' as a dict key and it indicates to match the corresponding value anywhere
    # below the current point
    contains(
        {'a': [ {'x':1,'b1':{'b2':{'c':'SOMETHING'}}}]},
        {'a': {'ANYTHING': 'SOMETHING', 'x':1}},
    ) # True

    contains(
        {'a': [ {'x':1, 'b':'SOMETHING'}]},
        {'a': {'ANYTHING': 'SOMETHING', 'x':1}},
    ) # True

    contains(
        {'a': [ {'x':1,'b1':{'b2':{'c':'SOMETHING'}}}]},
        {'a': {'ANYTHING': 'SOMETHING', 'x':1}},
    ) # True
    '''
    ANYTHING = 'ANYTHING'
    if contained == ANYTHING:
        return True

    if container == contained:
        return True

    if isinstance(container, list):
        if not isinstance(contained, list):
            contained = [contained]
        true_count = 0
        for contained_item in contained:
            for item in container:
                if contains(item, contained_item):
                    true_count += 1
                    break
        if true_count == len(contained):
            return True

    if isinstance(contained, dict) and isinstance(container, dict):
        contained_keys = set(contained.keys())
        if ANYTHING in contained_keys:
            contained_keys.remove(ANYTHING)
            if not contains(container, contained[ANYTHING]):
                return False

        container_keys = set(container.keys())
        if len(contained_keys - container_keys) == 0:
            # then all the contained keys are in this container ~ recursive check
            if all(
                contains(container[key], contained[key])
                for key in contained_keys
            ):
                return True

    # well, we're here, so I guess we didn't find a match yet
    if isinstance(container, dict):
        for value in container.values():
            if contains(value, contained):
                return True

    return False

يمكنك استخدام أسلوب AssurerGreaterEqual() بدلاً من ذلك.

users = {'id': 28027, 'email': 'chungs.lama@gmail.com','created_at': '2005-02-13'}

data = {"email": "chungs.lama@gmail.com"}

self.assertGreaterEqual(user.items(), data.items())

في Python 3 وPython 2.7، يمكنك إنشاء "عرض عنصر" يشبه المجموعة للإملاء دون نسخ أي بيانات.يتيح لك ذلك استخدام عوامل المقارنة لاختبار علاقة مجموعة فرعية.

في بايثون 3، يبدو هذا كما يلي:

# Test if d1 is a sub-dict of d2
d1.items() <= d2.items()

# Get items in d1 not found in d2
difference = d1.items() - d2.items()

في Python 2.7 يمكنك استخدام viewitems() طريقة بدلا من items() لتحقيق نفس النتيجة.

في Python 2.6 والإصدارات الأقدم، أفضل رهان لك هو التكرار على المفاتيح الموجودة في الإملاء الأول والتحقق من تضمينها في الثاني.

# Test if d1 is a subset of d2
all(k in d2 and d2[k] == d1[k] for k in d1)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top