如何比较具有相同属性的两个对象

81 阅读2分钟

在学习 Python 习题练习 49 时,需要比较两个不同的对象。需要测试的代码如下:

class ParserError(Exception):
    pass

class Sentence(object):

    def __init__(self, subject, verb, object):
        # remember we take ('noun','princess') tuples and convert them
        self.subject = subject[1]
        self.verb = verb[1]
        self.object = object[1]


def peek(word_list):
    if word_list:
        word = word_list[0]
        return word[0]
    else:
        return None


def match(word_list, expecting):
    if word_list:
        word = word_list.pop(0)  # 这里它返回来自 noun/princess 元组的 'noun'

        if word[0] == expecting:  # 这里它测试新项目是否位于 0 位置 ('noun' 在这种情况下) = 预期
            return word
        else:
            return None
    else:
        return None


def skip(word_list, word_type):
    while peek(word_list) == word_type:
        match(word_list, word_type)


def parse_verb(word_list):
    skip(word_list, 'stop')

    if peek(word_list) == 'verb':
        return match(word_list, 'verb')
    else:
        raise ParserError("Expected a verb next.")


def parse_object(word_list):
    skip(word_list, 'stop')
    next = peek(word_list)

    if next == 'noun':
        return match(word_list, 'noun')
    if next == 'direction':
        return match(word_list, 'direction')
    else:
        raise ParserError("Expected a noun or direction next.")


def parse_subject(word_list, subj):
    verb = parse_verb(word_list)
    obj = parse_object(word_list)

    return Sentence(subj, verb, obj)


def parse_sentence(word_list):
    skip(word_list, 'stop')

    start = peek(word_list)

    if start == 'noun':
        subj = match(word_list, 'noun')
        return parse_subject(word_list, subj)
    elif start == 'verb':
        # 假设主语是玩家
        return parse_subject(word_list, ('noun', 'player'))
    else:
        raise ParserError("Must start with subject, object, or verb not: %s" % start)


def test_parse_subject():
    word_list = [('verb', 'kill'), ('direction', 'north')]

    subj = ('noun', 'princess')
    verb = ('verb', 'kill')
    obj = ('direction', 'north')
    obj_sent = Sentence(subj, verb, obj)

    assert_equal(parser.parse_subject(word_list, subj), obj_sent)

在测试代码中,需要创建一个句子对象,并确保该对象与另一个句子对象相同。但是,在运行测试时,出现了以下错误:

Traceback (most recent call last):
  File "G:\Python27\lib\site-packages\nose\case.py", line 197, in runTest
    self.test(*self.arg)
  File "G:\Users\Charles\dropbox\programming\parsing_test\skeleton\tests\parser_tests.py", line 45, in test_parse_subject
    assert_equal(parser.parse_subject(word_list, subj), obj_sent)
AssertionError: <ex49.parser.Sentence object at 0x02651C50> != <ex49.parser.Sentence object at 0x02651C30>

So it's not returning the objects as the same, but I'm pretty sure they are. I gave them the right arguments. If the objects are the same, how do I confirm this? Thanks in advance
  1. 解决方案

这个问题的原因是比较了两个实例化的 Sentence 对象,而不是其各个属性。为了解决这个问题,可以按照以下步骤操作:

  1. 首先,需要导入 inspect 模块,该模块提供了用于检查对象及其属性的函数。
  2. 然后,在 test_parse_subject 函数中,可以添加以下代码:
def test_parse_subject():
    word_list = [('verb', 'kill'), ('direction', 'north')]

    subj = ('noun', 'princess')
    verb = ('verb', 'kill')
    obj = ('direction', 'north')
    obj_sent = Sentence(subj, verb, obj)

    # 获取两个对象的属性
    obj_sent_attrs = inspect.getmembers(obj_sent)
    parser_sent_attrs = inspect.getmembers(parser.parse_subject(word_list, subj))

    # 比较对象的属性
    for obj_sent_attr, parser_sent_attr in zip(obj_sent_attrs, parser_sent_attrs):
        assert obj_sent_attr[1] == parser_sent_attr[1]

使用 inspect.getmembers 函数可以获取对象的属性,并将其存储在元组列表中。然后,可以比较两个元组列表中的属性,以检查它们是否相等。

运行测试后,将不会再出现错误,因为比较的是两个对象的属性,而不是对象本身。