Python有匿名类吗?

我想知道Python是否有像C#匿名类function的东西。 为了澄清,下面是一个示例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 

具体要求是能够在expression式上下文中创build具有指定字段的对象(例如,在lambdaexpression式和其他不允许使用语句的地方使用),不需要额外的外部声明,并且可以通过普通成员访问语法foo.bar 。 创build的对象还应该通过组件名称 (不是按照元组的名称 ,按元组的forms)实现结构比较。

特别是:元组不是它的组件,因为它们的组件没有被命名; 类不是因为他们需要一个声明; 字典是不是因为他们有不受欢迎的foo["bar"]语法来访问组件。

namedtuple不是它,因为即使定义了内联types,它仍然需要一个名称,比较是基于位置的,而不是基于名称的。 尤其是:

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

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

[编辑]

正因为如此,这是一个单expression解决scheme,结合了Ken和alanlcode提供的两个非常丰富的答案,在没有任何额外的外部声明的情况下产生结构性的平等:

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

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

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__ 

(但请注意,Alex在他的评论中指出,这第二个问题是有问题的!)

1)见http://uszla.me.uk/space/blog/2008/11/06 。 您可以使用type内置函数以稍微难看的语法创build一个匿名对象:

  anon_object_2 = type("", (), {})() 

第三个参数是将包含您的对象的字段的字典。

  foo = type("", (), dict(y=1))() foo.y == 1 

2)Peter Norvig在http://norvig.com/python-iaq.html上提出了另一个变体。; 这也与Ken发布的答案类似。

 class Struct: def __init__(self, **entries): self.__dict__.update(entries) >>> options = Struct(answer=42, linelen = 80, font='courier') >>> options.answer 42 

这种方法的好处是你可以通过字典的内容实现平等,这是第一个选项没有的。

看起来Python 3.3已经以types.SimpleNamespace类的formsjoin了这个东西。

types(…)forms将不符合结构比较的要求(没有变得非常难看)。 字典(…)forms不符合属性访问器要求。

这个标准似乎落在了某个地方:

 class attrdict(dict): def __init__(self, *args, **kwargs): dict.__init__(self, *args, **kwargs) self.__dict__ = self a = attrdict(x=1, y=2) b = attrdict(y=2, x=1) print ax, ay print bx, by print a == b 

但是这意味着定义一个特殊的类。

好的,我只注意到这个问题的更新。 我只会注意到,你可以指定dict的bases参数,只需要指定构造函数(在ickytypesexpression式中)。 我更喜欢标准。 🙂

我不记得如果有一个内置的,但写自己比写你的问题短。 🙂

 class record(object): def __init__(self, **kwargs): self.__dict__ = kwargs def __eq__(self, r2): return self.__dict__ == r2.__dict__ def __ne__(self, r2): return self.__dict__ != r2.__dict__ foo = record(x=1, y=2) bar = record(y=2, x=1) foo == bar # => true 

引用此页 :

  class Struct: def __init__(self, **entries): self.__dict__.update(entries) def __eq__(self, other): return self.__dict__ == other.__dict__ def __neq__(self, other): return self.__dict__ != other.__dict__ options = Struct(answer=42, linelen = 80, font='courier') options.answer >>> 42 options.answer = 'plastics' vars(options) >>> {'answer': 'plastics', 'font': 'courier', 'linelen': 80} 

如果你希望这个实例也是匿名的(直接在expression式中使用这个对象),那么你就必须使用typesexpression式。 但是,在许多情况下,实例不会是匿名的,而是分配给一个variables。 这种情况下可以通过使用元类或装饰器在python中以合理的方式处理。

一个使用装饰器的例子:

 def anonymous(cls): return cls() @anonymous class foo: x = 42 def bar(self): return self.x 

在这种情况下,装饰器导致类foo被实例化,放入variablesfoo而不是类本身。 类本身不能从任何名字空间访问,尽pipe它有一个名字:

 >>> foo <__main__.foo instance at 0x7fd2938d8320> >>> foo.bar() 42 

python中的另一个function可以适应许多用例,在本地定义类是合法的,这意味着它们将成为该函数的本地符号,从而赋予它某种程度的匿名性。