Python: ตรวจสอบว่าพจนานุกรมหนึ่งเป็นชุดย่อยของพจนานุกรมอื่นที่ใหญ่กว่าหรือไม่


108

ฉันกำลังพยายามเขียนวิธีการกรองแบบกำหนดเองที่ใช้จำนวนkwargsโดยพลการและส่งคืนรายการที่มีองค์ประกอบของรายการคล้ายฐานข้อมูลที่มีkwargsเหล่านั้น kwargs

ตัวอย่างเช่นสมมติว่าd1 = {'a':'2', 'b':'3'}และd2= สิ่งเดียวกัน d1 == d2ผลลัพธ์เป็น True แต่สมมติว่าd2= สิ่งเดียวกันบวกสิ่งอื่น ๆ อีกมากมาย วิธีการของฉันต้องสามารถบอกได้ว่าd1 ใน d2หรือไม่ แต่ Python ไม่สามารถทำได้ด้วยพจนานุกรม

บริบท:

ฉันได้เรียน Word และแต่ละวัตถุมีคุณสมบัติชอบword, definition, part_of_speechและอื่น ๆ Word.objects.filter(word='jump', part_of_speech='verb-intransitive')ฉันต้องการที่จะสามารถที่จะเรียกวิธีการกรองในรายการหลักของคำเหล่านี้เช่น ฉันไม่สามารถหาวิธีจัดการคีย์และค่าเหล่านี้ในเวลาเดียวกันได้ แต่อาจมีฟังก์ชันที่ใหญ่กว่านอกบริบทนี้สำหรับคนอื่น

คำตอบ:


113

แปลงเป็นคู่รายการและตรวจสอบการกักกัน

all(item in superset.items() for item in subset.items())

การเพิ่มประสิทธิภาพถูกปล่อยให้เป็นแบบฝึกหัดสำหรับผู้อ่าน


19
หากค่า Dict ที่มี hashable ใช้ viewitems () เป็นวิธีที่ optimizied d1.viewitems() <= d2.viewitems()ที่สุดที่ฉันสามารถคิด: การวิ่งตามเวลาแสดงให้เห็นว่ามีการปรับปรุงประสิทธิภาพมากกว่า 3 เท่า หากไม่สามารถล้างได้แม้ใช้iteritems()แทนitems()โอกาสในการขายเพื่อปรับปรุง 1.2 เท่า ทำได้โดยใช้ Python 2.7
ชาด

36
ฉันไม่คิดว่าการเพิ่มประสิทธิภาพควรถูกทิ้งไว้ให้ผู้อ่าน - ฉันกังวลว่าผู้คนจะใช้สิ่งนี้จริงโดยไม่ทราบว่ามันจะสร้างสำเนาของ superset.items () และทำซ้ำทุกรายการในชุดย่อย
robert king

5
ด้วย Python 3 items()จะส่งคืนมุมมองที่มีน้ำหนักเบาแทนที่จะเป็นสำเนา ไม่จำเป็นต้องเพิ่มประสิทธิภาพอีกต่อไป
Kentzo

3
แล้วไดเรกทอรีที่ซ้อนกันล่ะ?
Andreas Profous

5
นี่มันเฮฮา ฉันจะปล่อยให้ผู้อ่านได้รับการปรับแต่งเรื่องอารมณ์ขัน
deepelement

111

ใน Python 3 คุณสามารถใช้dict.items()เพื่อรับมุมมองที่เหมือนชุดของรายการ dict จากนั้นคุณสามารถใช้<=โอเปอเรเตอร์เพื่อทดสอบว่ามุมมองหนึ่งเป็น "ส่วนย่อย" ของอีกมุมมองหนึ่งหรือไม่:

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

ใน Python 2.7 ให้ใช้dict.viewitems()เพื่อทำสิ่งเดียวกัน:

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

ใน Python 2.6 และต่ำกว่าคุณจะต้องมีโซลูชันอื่นเช่นใช้all():

all(key in d2 and d2[key] == d1[key] for key in d1)

1
สำหรับ python3 จะกลายเป็นd1.items() <= d2.items()
radu.ciorba

ข้อแม้: หากโปรแกรมของคุณสามารถใช้กับ Python 2.6 (หรือต่ำกว่า) ได้แสดงว่าd1.items() <= d2.items()มีการเปรียบเทียบรายการทูเปิล 2 รายการโดยไม่มีคำสั่งเฉพาะดังนั้นผลลัพธ์สุดท้ายอาจไม่น่าเชื่อถือ ด้วยเหตุนี้ฉันจึงเปลี่ยนไปใช้คำตอบของ @blubberdiblub
RayLuo

1
d1.items() <= d2.items()เป็นพฤติกรรมที่ไม่ได้กำหนด ไม่มีการบันทึกไว้ในเอกสารอย่างเป็นทางการและที่สำคัญที่สุดคือไม่มีการทดสอบ: github.com/python/cpython/blob/… ดังนั้นจึงขึ้นอยู่กับการใช้งาน
Rodrigo Martins de Oliveira

2
@RodrigoMartins มีการบันทึกไว้ที่นี่ : "สำหรับมุมมองที่เหมือนชุดการดำเนินการทั้งหมดที่กำหนดไว้สำหรับคลาสฐานนามธรรมcollections.abc.Setจะพร้อมใช้งาน"
augurar

1
@RodrigoMartins หากคุณกังวลเกี่ยวกับผู้ดูแลในอนาคตให้รวมการดำเนินการไว้ในฟังก์ชันที่มีชื่อชัดเจนหรือเพิ่มความคิดเห็นเกี่ยวกับรหัส การลดมาตรฐานโค้ดของคุณให้อยู่ในระดับของนักพัฒนาที่ไร้ความสามารถเป็นความคิดที่แย่มาก
สิงหาคม

38

หมายเหตุสำหรับผู้ที่ต้องการสิ่งนี้สำหรับการทดสอบหน่วย: ยังมีassertDictContainsSubset()วิธีการในTestCaseคลาสของ Python

http://docs.python.org/2/library/unittest.html?highlight=assertdictcontainssubset#unittest.TestCase.assertDictContainsSubset

อย่างไรก็ตามมันเลิกใช้แล้วใน 3.2 ไม่แน่ใจว่าทำไมอาจมีการเปลี่ยนแทน


30
อยากรู้อยากเห็นพบสิ่งนี้ในสิ่งใหม่ใน 3.2 : เมธอด assertDictContainsSubset () ถูกเลิกใช้งานเนื่องจากใช้ผิดกับอาร์กิวเมนต์ผิดลำดับ สิ่งนี้สร้างภาพลวงตาทางแสงที่ยากต่อการแก้ไขซึ่งการทดสอบเช่น TestCase (). assertDictContainsSubset ({'a': 1, 'b': 2}, {'a': 1}) จะล้มเหลว (สนับสนุนโดย Raymond Hettinger)
Pedru

2
เดี๋ยวก่อนคาดว่าด้านซ้ายและด้านขวาเป็นจริง ... ไม่ควรล้มเหลว? สิ่งเดียวที่ผิดกับฟังก์ชั่นคืออันไหนไปในที่ที่สับสน?
JamesHutchison

21

สำหรับคีย์และค่าตรวจสอบใช้: set(d1.items()).issubset(set(d2.items()))

หากคุณต้องการตรวจสอบเฉพาะคีย์: set(d1).issubset(set(d2))


11
นิพจน์แรกจะไม่ทำงานหากไม่สามารถล้างค่าใด ๆ ในพจนานุกรมได้
Pedro Romano

6
ตัวอย่างที่สองสามารถย่อให้สั้นลงเล็กน้อยโดยการลบเซต (d2) เนื่องจาก "issubset ยอมรับการทำซ้ำ" docs.python.org/2/library/stdtypes.html#set
trojjer

สิ่งนี้ผิด: d1={'a':1,'b':2}; d2={'a':2,'b':1}-> ตัวอย่างที่สองจะกลับมาTrue...
Francesco Pasa

1
@FrancescoPasa ตัวอย่างที่สองระบุอย่างชัดเจนว่า: "ถ้าคุณต้องการตรวจสอบคีย์เท่านั้น" {'a', 'b'}เป็นส่วนย่อยของ{'a', 'b'};)
DylanYoung

20

เพื่อความสมบูรณ์คุณสามารถทำได้:

def is_subdict(small, big):
    return dict(big, **small) == big

อย่างไรก็ตามฉันไม่อ้างสิทธิ์ใด ๆ เกี่ยวกับความเร็ว (หรือขาด) หรือความสามารถในการอ่าน (หรือขาด)


หมายเหตุด้านข้าง: คำตอบอื่น ๆ ที่กล่าวถึงsmall.viewitems() <= big.viewitems()มีแนวโน้มดี แต่มีข้อแม้อย่างหนึ่ง: หากโปรแกรมของคุณสามารถใช้กับ Python 2.6 (หรือต่ำกว่า) ได้d1.items() <= d2.items()ก็จะมีการเปรียบเทียบรายการทูเปิล 2 รายการโดยไม่มีคำสั่งเฉพาะดังนั้นผลลัพธ์สุดท้ายอาจเป็นไปได้ ไม่น่าเชื่อถือ ด้วยเหตุนี้ฉันจึงเปลี่ยนไปใช้คำตอบของ @blubberdiblub โหวตแล้ว
RayLuo

สิ่งนี้ยอดเยี่ยม แต่ดูเหมือนจะใช้ไม่ได้กับพจนานุกรมที่ซ้อนกัน
Frederik Baetens

@FrederikBaetens ไม่ได้ตั้งใจ นอกจากนี้ฉันเชื่อว่าไม่มีวิธีที่เป็นที่ยอมรับโดยทั่วไปในการทำเช่นนั้นเนื่องจากมีหลายวิธีที่คุณสามารถทำได้และมีโครงสร้าง / ข้อ จำกัด ที่เป็นไปได้หลายประการที่คุณสามารถกำหนดให้กับพจนานุกรมดังกล่าวได้ คำถามที่อยู่ในใจมีดังนี้: คุณจะทราบได้อย่างไรว่าควรจะสืบเชื้อสายมาจากพจนานุกรมที่ลึกกว่านั้นหรือไม่? แล้วออบเจ็กต์ประเภทที่มีdictคลาสพื้นฐานล่ะ? จะเกิดอะไรขึ้นถ้ายังไม่มีและยังคงมีพฤติกรรมเหมือน a dict? จะเกิดอะไรขึ้นถ้าsmallและbigมีค่าประเภทต่างๆที่คีย์ที่ตรงกันซึ่งยังคงทำงานเหมือน dict
blubberdiblub

สิ่งเหล่านี้เป็นจุดที่ถูกต้อง แต่ฟังก์ชันพื้นฐานที่ทำงานร่วมกับคำสั่งซ้อนกันธรรมดาควรจะดี ฉันโพสต์ตัวอย่างที่นี่แต่วิธีแก้ปัญหาของ @ NutCracker ดีกว่า
Frederik Baetens

แน่นอนว่ามันเป็นคำถามเกี่ยวกับพจนานุกรมที่ซ้อนกัน (และมีการระบุข้อกำหนดที่แน่นอนสำหรับพจนานุกรมไว้) ฉันอาจจะมีปัญหากับมัน ประเด็นก็คือวิธีแก้ปัญหาสำหรับพจนานุกรมที่ซ้อนกันไม่ได้ให้คำตอบที่ถูกต้องเมื่อคุณต้องการทราบว่าคำสั่งเป็นคำสั่งย่อยของคำสั่งอื่นหรือไม่ (กล่าวคือเมื่อคุณต้องการให้คำตอบอย่างเคร่งครัดFalseเมื่อค่าของคำสั่งที่ส่งผ่าน จะแตกต่างกันสำหรับคีย์ที่ตรงกัน) หรืออีกนัยหนึ่ง: วิธีแก้ปัญหาสำหรับคำสั่งที่ซ้อนกันไม่จำเป็นต้องเป็นการแทนที่แบบดรอปอินขึ้นอยู่กับกรณีการใช้งาน
blubberdiblub

10
>>> d1 = {'a':'2', 'b':'3'}
>>> d2 = {'a':'2', 'b':'3','c':'4'}
>>> all((k in d2 and d2[k]==v) for k,v in d1.iteritems())
True

บริบท:

>>> d1 = {'a':'2', 'b':'3'}
>>> d2 = {'a':'2', 'b':'3','c':'4'}
>>> list(d1.iteritems())
[('a', '2'), ('b', '3')]
>>> [(k,v) for k,v in d1.iteritems()]
[('a', '2'), ('b', '3')]
>>> k,v = ('a','2')
>>> k
'a'
>>> v
'2'
>>> k in d2
True
>>> d2[k]
'2'
>>> k in d2 and d2[k]==v
True
>>> [(k in d2 and d2[k]==v) for k,v in d1.iteritems()]
[True, True]
>>> ((k in d2 and d2[k]==v) for k,v in d1.iteritems())
<generator object <genexpr> at 0x02A9D2B0>
>>> ((k in d2 and d2[k]==v) for k,v in d1.iteritems()).next()
True
>>> all((k in d2 and d2[k]==v) for k,v in d1.iteritems())
True
>>>

5

นี่คือวิธีแก้ปัญหาที่เรียกซ้ำในรายการและชุดที่มีอยู่ในพจนานุกรมอย่างถูกต้อง คุณยังสามารถใช้สิ่งนี้สำหรับรายการที่มีคำสั่ง ฯลฯ ...

def is_subset(subset, superset):
    if isinstance(subset, dict):
        return all(key in superset and is_subset(val, superset[key]) for key, val in subset.items())

    if isinstance(subset, list) or isinstance(subset, set):
        return all(any(is_subset(subitem, superitem) for superitem in superset) for subitem in subset)

    # assume that subset is a plain value if none of the above match
    return subset == superset

4

ฟังก์ชั่นของฉันเพื่อจุดประสงค์เดียวกันโดยทำสิ่งนี้ซ้ำ ๆ :

def dictMatch(patn, real):
    """does real dict match pattern?"""
    try:
        for pkey, pvalue in patn.iteritems():
            if type(pvalue) is dict:
                result = dictMatch(pvalue, real[pkey])
                assert result
            else:
                assert real[pkey] == pvalue
                result = True
    except (AssertionError, KeyError):
        result = False
    return result

ในตัวอย่างของคุณdictMatch(d1, d2)ควรคืนค่า True แม้ว่า d2 จะมีสิ่งอื่น ๆ อยู่ก็ตามนอกจากนี้ยังใช้กับระดับที่ต่ำกว่า:

d1 = {'a':'2', 'b':{3: 'iii'}}
d2 = {'a':'2', 'b':{3: 'iii', 4: 'iv'},'c':'4'}

dictMatch(d1, d2)   # True

หมายเหตุ: อาจมีวิธีแก้ปัญหาที่ดีกว่านี้ซึ่งจะหลีกเลี่ยงif type(pvalue) is dictประโยคและนำไปใช้กับกรณีที่กว้างขึ้น (เช่นรายการแฮชเป็นต้น) นอกจากนี้การเรียกซ้ำไม่ จำกัด ที่นี่ดังนั้นโปรดใช้ความเสี่ยงของคุณเอง ;)


2

ปัญหาที่ดูเหมือนตรงไปตรงมานี้ทำให้ฉันต้องใช้เวลาสองสามชั่วโมงในการค้นคว้าเพื่อหาวิธีแก้ปัญหาที่เชื่อถือได้ 100% ดังนั้นฉันจึงบันทึกสิ่งที่ฉันพบในคำตอบนี้

  1. "Pythonic พันธมิตร" พูดsmall_dict <= big_dictจะเป็นวิธีที่ง่ายที่สุด แต่เลวร้ายเกินไปว่ามันจะไม่ทำงาน {'a': 1} < {'a': 1, 'b': 2}ดูเหมือนจะใช้งานได้ใน Python 2 แต่ไม่น่าเชื่อถือเนื่องจากเอกสารอย่างเป็นทางการเรียกมันออกมาอย่างชัดเจน ไปที่การค้นหา "ผลลัพธ์อื่นที่ไม่ใช่ความเท่าเทียมได้รับการแก้ไขอย่างสม่ำเสมอ แต่ไม่ได้กำหนดไว้เป็นอย่างอื่น" ในส่วนนี้ ไม่ต้องพูดถึงการเปรียบเทียบ 2 dicts ใน Python 3 ทำให้เกิดข้อยกเว้น TypeError

  2. สิ่งที่สองที่มากที่สุดที่ใช้งานง่ายเป็นsmall.viewitems() <= big.viewitems()สำหรับ Python 2.7 เท่านั้นและsmall.items() <= big.items()สำหรับหลาม 3. แต่มีหนึ่งคำเตือน: มันเป็นที่อาจเกิดขึ้นรถ หากโปรแกรมของคุณสามารถใช้กับ Python <= 2.6 ได้แสดงว่าโปรแกรมของคุณd1.items() <= d2.items()กำลังเปรียบเทียบ 2 รายการของสิ่งที่เพิ่มขึ้นโดยไม่มีลำดับที่เฉพาะเจาะจงดังนั้นผลลัพธ์สุดท้ายจะไม่น่าเชื่อถือและกลายเป็นจุดบกพร่องที่น่ารังเกียจในโปรแกรมของคุณ ฉันไม่กระตือรือร้นที่จะเขียนการนำไปใช้งานอื่นสำหรับ Python <= 2.6 แต่ฉันยังไม่สบายใจที่โค้ดของฉันมาพร้อมกับข้อบกพร่องที่ทราบ (แม้ว่าจะอยู่บนแพลตฟอร์มที่ไม่รองรับก็ตาม) ดังนั้นฉันจึงละทิ้งแนวทางนี้

  3. ฉันปักหลักกับคำตอบของ @blubberdiblub (เครดิตไปที่เขา):

    def is_subdict(small, big): return dict(big, **small) == big

    เป็นมูลค่าการชี้ให้เห็นว่าคำตอบนี้อาศัยอยู่กับ==พฤติกรรมระหว่าง dicts ซึ่งกำหนดไว้อย่างชัดเจนในเอกสารอย่างเป็นทางการจึงควรจะทำงานในทุกรุ่นหลาม ไปค้นหา:

    • "พจนานุกรมเปรียบเทียบค่าเท่ากันก็ต่อเมื่อมีคู่ (คีย์ค่า) เหมือนกัน" เป็นประโยคสุดท้ายในหน้านี้
    • "การแมป (อินสแตนซ์ของ dict) เปรียบเทียบค่าเท่ากันก็ต่อเมื่อมีคู่ (คีย์ค่า) เท่ากันการเปรียบเทียบคีย์และองค์ประกอบที่เท่าเทียมกันจะทำให้เกิดการสะท้อนกลับ" ในหน้านี้

2

นี่คือวิธีแก้ปัญหาแบบวนซ้ำทั่วไปสำหรับปัญหาที่ได้รับ:

import traceback
import unittest

def is_subset(superset, subset):
    for key, value in subset.items():
        if key not in superset:
            return False

        if isinstance(value, dict):
            if not is_subset(superset[key], value):
                return False

        elif isinstance(value, str):
            if value not in superset[key]:
                return False

        elif isinstance(value, list):
            if not set(value) <= set(superset[key]):
                return False
        elif isinstance(value, set):
            if not value <= superset[key]:
                return False

        else:
            if not value == superset[key]:
                return False

    return True


class Foo(unittest.TestCase):

    def setUp(self):
        self.dct = {
            'a': 'hello world',
            'b': 12345,
            'c': 1.2345,
            'd': [1, 2, 3, 4, 5],
            'e': {1, 2, 3, 4, 5},
            'f': {
                'a': 'hello world',
                'b': 12345,
                'c': 1.2345,
                'd': [1, 2, 3, 4, 5],
                'e': {1, 2, 3, 4, 5},
                'g': False,
                'h': None
            },
            'g': False,
            'h': None,
            'question': 'mcve',
            'metadata': {}
        }

    def tearDown(self):
        pass

    def check_true(self, superset, subset):
        return self.assertEqual(is_subset(superset, subset), True)

    def check_false(self, superset, subset):
        return self.assertEqual(is_subset(superset, subset), False)

    def test_simple_cases(self):
        self.check_true(self.dct, {'a': 'hello world'})
        self.check_true(self.dct, {'b': 12345})
        self.check_true(self.dct, {'c': 1.2345})
        self.check_true(self.dct, {'d': [1, 2, 3, 4, 5]})
        self.check_true(self.dct, {'e': {1, 2, 3, 4, 5}})
        self.check_true(self.dct, {'f': {
            'a': 'hello world',
            'b': 12345,
            'c': 1.2345,
            'd': [1, 2, 3, 4, 5],
            'e': {1, 2, 3, 4, 5},
        }})
        self.check_true(self.dct, {'g': False})
        self.check_true(self.dct, {'h': None})

    def test_tricky_cases(self):
        self.check_true(self.dct, {'a': 'hello'})
        self.check_true(self.dct, {'d': [1, 2, 3]})
        self.check_true(self.dct, {'e': {3, 4}})
        self.check_true(self.dct, {'f': {
            'a': 'hello world',
            'h': None
        }})
        self.check_false(
            self.dct, {'question': 'mcve', 'metadata': {'author': 'BPL'}})
        self.check_true(
            self.dct, {'question': 'mcve', 'metadata': {}})
        self.check_false(
            self.dct, {'question1': 'mcve', 'metadata': {}})

if __name__ == "__main__":
    unittest.main()

หมายเหตุ: รหัสเดิมจะล้มเหลวในบางกรณีเครดิตสำหรับการแก้ไขจะไปที่@ olivier-melançon


รหัสล้มเหลวด้วยซูเปอร์เซ็ตที่มีคำสั่งซ้อนอยู่ในรายการในบรรทัดif not set(value) <= set(superset[key])
Eelco Hoogendoorn

2

หากคุณไม่ทราบใช้pydash มีis_matchมีที่ไม่ตรงที่:

import pydash

a = {1:2, 3:4, 5:{6:7}}
b = {3:4.0, 5:{6:8}}
c = {3:4.0, 5:{6:7}}

pydash.predicates.is_match(a, b) # False
pydash.predicates.is_match(a, c) # True

1

ฉันรู้ว่าคำถามนี้เก่า แต่นี่คือทางออกของฉันในการตรวจสอบว่าพจนานุกรมที่ซ้อนกันเป็นส่วนหนึ่งของพจนานุกรมที่ซ้อนกันอื่นหรือไม่ การแก้ปัญหาเป็นแบบวนซ้ำ

def compare_dicts(a, b):
    for key, value in a.items():
        if key in b:
            if isinstance(a[key], dict):
                if not compare_dicts(a[key], b[key]):
                    return False
            elif value != b[key]:
                return False
        else:
            return False
    return True

0

ฟังก์ชันนี้ใช้ได้กับค่าที่ไม่สามารถแฮชได้ ฉันยังคิดว่ามันชัดเจนและง่ายต่อการอ่าน

def isSubDict(subDict,dictionary):
    for key in subDict.keys():
        if (not key in dictionary) or (not subDict[key] == dictionary[key]):
            return False
    return True

In [126]: isSubDict({1:2},{3:4})
Out[126]: False

In [127]: isSubDict({1:2},{1:2,3:4})
Out[127]: True

In [128]: isSubDict({1:{2:3}},{1:{2:3},3:4})
Out[128]: True

In [129]: isSubDict({1:{2:3}},{1:{2:4},3:4})
Out[129]: False

0

การใช้งานแบบเรียกซ้ำสั้น ๆ ที่ใช้ได้กับพจนานุกรมที่ซ้อนกัน:

def compare_dicts(a,b):
    if not a: return True
    if isinstance(a, dict):
        key, val = a.popitem()
        return isinstance(b, dict) and key in b and compare_dicts(val, b.pop(key)) and compare_dicts(a, b)
    return a == b

สิ่งนี้จะใช้คำสั่ง a และ b หากใครทราบวิธีที่ดีในการหลีกเลี่ยงโดยไม่ต้องใช้วิธีแก้ปัญหาซ้ำ ๆ บางส่วนเหมือนคำตอบอื่น ๆ โปรดบอกฉัน ฉันต้องการวิธีแยกคำสั่งออกเป็นส่วนหัวและส่วนหางตามคีย์

โค้ดนี้มีประโยชน์มากกว่าแบบฝึกหัดการเขียนโปรแกรมและอาจช้ากว่าโซลูชันอื่น ๆ ในที่นี้ซึ่งผสมผสานการเรียกซ้ำและการวนซ้ำ วิธีแก้ปัญหาของ @ Nutcrackerค่อนข้างดีสำหรับพจนานุกรมที่ซ้อนกัน


1
มีบางอย่างหายไปในรหัส เพียงแค่ลงไปตามค่าแรกที่เริ่มต้นในa(และค่าแรกที่ตามมา) popitemจะพบ นอกจากนี้ยังควรตรวจสอบรายการอื่น ๆ ในระดับเดียวกัน ฉันมีคู่ของคำสั่งที่ซ้อนกันซึ่งส่งคืนคำตอบที่ผิด (ยากที่จะนำเสนอตัวอย่างที่พิสูจน์ได้ในอนาคตที่นี่เนื่องจากขึ้นอยู่กับคำสั่งของpopitem)
blubberdiblub

ขอบคุณควรแก้ไขเดี๋ยวนี้ :)
Frederik Baetens

0

ใช้ออบเจ็กต์ Wrapper นี้ที่ให้การเปรียบเทียบบางส่วนและความแตกต่างที่ดี:


class DictMatch(dict):
    """ Partial match of a dictionary to another one """
    def __eq__(self, other: dict):
        assert isinstance(other, dict)
        return all(other[name] == value for name, value in self.items())

actual_name = {'praenomen': 'Gaius', 'nomen': 'Julius', 'cognomen': 'Caesar'}
expected_name = DictMatch({'praenomen': 'Gaius'})  # partial match
assert expected_name == actual_name  # True
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.