回答问题

我想知道 Python 是否有类似 C# 匿名类功能的东西。为了澄清,这里有一个示例 C# 片段:

var foo = new { x = 1, y = 2 };
var bar = new { y = 2, x = 1 };
foo.Equals(bar); // "true"

在 Python 中,我会想象这样的事情:

foo = record(x = 1, y = 2)
bar = record(y = 2, x = 1)
foo == bar  # true

具体要求是能够在表达式上下文中创建具有指定字段的对象(例如,可用于 lambda 和其他不允许使用语句的地方),无需额外的外部声明,并且能够通过普通成员按名称访问各个组件访问语法foo.bar。创建的对象还应该实现结构比较_按组件名称_(而不是像元组那样按位置)。

特别是:元组不是因为它们的组件没有命名;类不是因为它们需要声明; dicts 不是因为它们具有不需要的foo["bar"]语法来访问组件。

namedtuple不是,因为即使你定义了 inline 类型,它仍然需要一个名称,并且比较是基于位置的,而不是基于名称的。尤其是:

 def foo(): return namedtuple("Foo", "x y")(x = 1, y = 2)
 def bar(): return namedtuple("Foo", "y x")(x = 1, y = 2)
 foo() == bar()   # False because fields are compared in order, and not by name
                  # True would be desired instead

如果需要,我知道如何在 Python 中编写这样的东西。但我想知道 Python 标准库或任何流行的第三方库中是否有类似的东西。

[编辑]

仅仅为了它,这里有一个单一的表达式解决方案,它结合了 Ken 和 alanlcode 的两个非常有用的答案,在没有任何额外外部声明的情况下产生结构相等:

type("", (), { \
    "__init__": (lambda self, **kwargs: self.__dict__.update(kwargs)), \
    "__eq__": (lambda self, other: self.__dict__ == other.__dict__) } \
)(x = 1, y = 2)

从技术上讲,它满足了问题的所有要求,但我真诚地希望没有人使用它(我绝对不会)。

Answers

pythonic方式是使用dict:

>>> foo = dict(x=1, y=2)
>>> bar = dict(y=2, x=1)
>>> foo == bar
True

满足您的所有要求,除了您仍然必须执行foo['x']而不是foo.x

如果这是一个问题,您可以轻松定义一个类,例如:

class Bunch(object):
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

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

或者,一个漂亮而简短的

class Bunch(dict):
    __getattr__, __setattr__ = dict.get, dict.__setitem__

(但请注意,正如亚历克斯在评论中指出的那样,第二个存在问题!)

Logo

Python社区为您提供最前沿的新闻资讯和知识内容

更多推荐