【问题标题】:Python subclassing listPython子类列表
【发布时间】:2014-01-01 07:11:01
【问题描述】:

我已经对内置 Python 列表进行了子类化。

一个空列表将在 if 构造中评估为 false,但我希望我的子类评估为 true。

是否有任何可用的 dunder 方法可以在我的子类中重写以更改此行为?

【问题讨论】:

  • bool 是我需要的。谢谢。
  • 我无法理解您希望通过这样做解决什么问题。
  • 出于其他原因,我对列表进行了子类化,而不仅仅是为了让空列表返回 True。这只是我的必需品之一。

标签: python list operator-overloading overloading


【解决方案1】:

根据Python datamodel documentation, for the object.__nonzero__ method,这是可行的(但会违反rule of least surprise, or principle of least astonishment):

调用以实现真值测试和内置操作 布尔();应该返回 False 或 True,或它们的整数等价物 0 或 1、当该方法没有定义时,如果定义了,则调用len(),如果对象的结果为非零,则认为该对象为真。 如果一个类既没有定义 len() 也没有定义 nonzero(),它的所有 实例被认为是真实的。

因此假设,我们可以检查 len() == 0,如果是则返回 True,并且 然后使用默认值进行布尔检查:

class FunkyList(list):
    def __nonzero__(self):
        if self.__len__() == 0:
            return True
        else:
            return self.__len__()

    __bool__ = __nonzero__ # Python 3 uses __bool__ instead of __nonzero

但由于逻辑树的两种情况都会导致布尔值为 True,因此上述可以简化为:

class FunkyList(list):
    def __nonzero__(self):
        return True

    __bool__ = __nonzero__ # Python 3 uses __bool__ instead of __nonzero

我们看到它有效并且看起来像一个列表:

>>> fl = FunkyList()
>>> fl
[]
>>> isinstance(fl, list)
True

现在空 FunkyList 的 bool() 返回 True

>>> bool(fl)
True

而且它没有破解__len__ 方法。

>>> len(fl)
0

无论如何,我不明白您为什么希望 len 0 的列表返回 True。

感谢您提出如此有趣的问题,但我希望这是学术问题,而不是实际问题。执行此检查是 Python 的惯用做法:

>>> if fl:
...     print True
... 
True

并且任何有 Python 经验的人都会期望如果列表为空,则返回 False,而实现它的结果可能会让任何用户对你非常不满。

【讨论】:

  • 因为很多人都好奇我为什么需要这个,所以就这样吧。我正在编写一个 INI 文件解析器,其中我使用列表的一个子类(比如部分)来表示 ini 文件中的一个部分。 section 类在所有方面都像一个列表,但支持更多的方法。另一个对象(将文件本身表示为inifile)正在保存一个节列表。该部分又包含 cmets 和键值对。在测试 inifile 对象中是否存在某个部分时,我总是得到 False,然后我意识到这是因为该部分是空的。
  • 该部分完全由我的模块使用,所以我相信没有其他人会直接使用它。我确实相信还有其他 pythonic 方式可以做同样的事情,但我只是在尝试。现在一切都按我的预期工作。
  • len(smthing)==0 增加了不必要的执行开销
  • @AaronHall,not mylistlen(mylist)==0 快两倍多。我认为可以安全地假设前者没有隐含地使用后者。
  • @Akilesh 检查timeit 模块
【解决方案2】:

我不知道它是否对你有帮助,但我试过了...... list_1= [["a","b"]] 其中 ''list_1' 是列表名称,而 '["a","b"]' 是列表的子集。 如果你执行以下代码

list_1 = [["a","b"]];
if "a" in list_1:
     print ("true");
else:
     print ("false");

会给你“假”.....

如果你执行这段代码

list_1 = [["a","b"]];
if "a" in list_1[0]:
     print ("true");
else:
     print ("false");

它会给你“真实”

通过这种方式你可以访问列表中的子列表...

【讨论】:

  • OP 是关于子类化的;这个答案是针对未提出的问题(并且是对伤害的侮辱-也是 C 风格)
  • ... 现在您必须在想要使用该列表时写入 [0]。并且 len(list) 始终为 1。你对这个 Yogesh 是认真的吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 1970-01-01
  • 2013-11-18
相关资源
最近更新 更多