【问题标题】:Is there a way to make "X() in [X(), Y(), Z()]" return True?有没有办法让 [X(), Y(), Z()] 中的“X()”返回 True?
【发布时间】:2018-02-21 12:15:05
【问题描述】:

我在this project of mine 中有一个自定义对象,名为 Page。页面的识别功能是其title。页面通常通过调用Wiki.pageWiki.categoryWiki.template 或通过其他方法(如Wiki.random)生成它们来创建。 (我建议你在继续之前先看看那是什么。)

有时,此模块的用户可能希望生成一些页面并将该生成器转换为普通的list。在他们获得页面列表后,他们可能想要检查他们获得的另一个页面是否在该列表中中。但是,这个:

>>> wp = mw_api_client.Wiki('https://en.wikipedia.org/w/api.php')
>>> wp.page('title') in [wp.page('title'),
                         wp.page('not this'),
                         wp.page('not this either')]
False

应该是 True,而不是 False,因为 是一个带有 title“标题”的页面。有没有一种神奇的方法可以让我做到这一点?我已经尝试过使用__eq__(用于相等)和__hash__(用于哈希检查)(commit),但似乎都没有成功。列表是否仅使用身份?还是我还缺少其他东西?我该如何正确地做到这一点?

【问题讨论】:

  • 您的__eq__ 可能已损坏。如果你有它应该可以工作。
  • __eq__ 确实可以解决问题。您是否尝试过调试它,例如在返回之前打印两个页面对象的 url 和比较的结果?可能对象没有按照您的预期进行初始化,或者其他原因。

标签: python operators contains


【解决方案1】:

我原来的答案走错了兔子洞……(见历史)。

总是值得实现破坏的简化版本...见下文(使用这些 1,2,3,4 作为灵感)

#!/usr/bin/env python3

from pprint import pprint

class Page(object):
    def __init__(self, wiki, **data):
        self.wiki = wiki
        self.title = None
        self.__dict__.update(data)

    def __eq__(self, other):
        return self.title == other.title

class Wiki(object):
    def __init__(self, api_url):
        self.api_url = api_url

    def page(self, title, **evil):
        if isinstance(title, Page):
            return title;
        return Page(self, title=title, **evil)

w = Wiki('url')
pprint(w)
pprint(w.__dict__)

p1 = w.page('testing')
pprint(p1)
pprint(p1.__dict__)

p2 = w.page('testing')
pprint(p2)
pprint(p2.__dict__)

p3 = w.page('testing something else')
pprint(p3)
pprint(p3.__dict__)

pprint(p1 == p2)
pprint(p1 == p3)
pprint(p1 in [ p2 ])
pprint(p1 in [ p2, p3 ])

输出:

<__main__.Wiki object at 0x7f2891957d30>
{'api_url': 'url'}
<__main__.Page object at 0x7f2891957dd8>
{'title': 'testing', 'wiki': <__main__.Wiki object at 0x7f2891957d30>}
<__main__.Page object at 0x7f2891957e48>
{'title': 'testing', 'wiki': <__main__.Wiki object at 0x7f2891957d30>}
<__main__.Page object at 0x7f289190cf60>
{'title': 'testing something else',
 'wiki': <__main__.Wiki object at 0x7f2891957d30>}
True
False
True
True

如您所见,这行得通...

我不确定我对你使用 self.__dict__.update(data) 的感觉如何......它第一次让我措手不及......我目前怀疑它的使用 herehere(两者都是行做同样的事情...)

class Page(object):
    def __init__(self, wiki, getinfo=None, **data):
        # ...
        if getinfo is None:
            getinfo = GETINFO
        if getinfo:
            self.__dict__.update(self.info())

    def info(self):
        # ...
        self.__dict__.update(page_data)
        return page_data

您能否确保这些调用不会覆盖title

【讨论】:

  • 我认为 OP 也在问他如何使这两个 Page 实例在使用 in [list] 构造时比较相等(例如,通过实现 __eq__ 或类似方法
  • 很好的答案! +1
  • 赞成只是为了指出我的怪异之处。我使用 dict.update 因为 MediaWiki API 数据是相当动态的,我宁愿不处理每个单独的信息位。我可以确保调用不会覆盖标题:P 编辑:done
【解决方案2】:

等一下,现在可以了!

>>> w = mw.Wiki('https://en.wikipedia.org/w/api.php')
>>> a = [w.page('hi'), w.page('ih'), w.page('ij')]
>>> w.page('hi') in a
True

好的,我不知道之前出了什么问题。现在解决了。不过,我会记住 Attieanswer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 2012-01-07
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多