添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
绅士的茴香  ·  安装cplex到python_mob64ca ...·  1 月前    · 
个性的饼干  ·  实用的 Python 之 ...·  4 周前    · 
霸气的花卷  ·  python list 错位相减 ...·  昨天    · 
憨厚的大脸猫  ·  python ...·  昨天    · 
气势凌人的香菇  ·  Ext ...·  1 年前    · 
伤情的感冒药  ·  iis ...·  1 年前    · 
乖乖的红薯  ·  教程 | ...·  1 年前    · 

Python 有匿名类吗?

88 人关注

我想知道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

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

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

命名元组不是,因为它仍然需要一个名字,即使你定义了内联类型,而且比较是基于位置的,而不是基于名字。特别是。

 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标准库或任何流行的第三方库中是否有这样的东西。

[EDIT]

为了方便起见,这里有一个单一表达式的解决方案,它结合了Ken和alanlcode的两个非常丰富的答案,产生了结构上的平等,而没有任何额外的外部声明。

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

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

5 个评论
听起来,字典应该可以完成这个工作。 我发现最好是找到 python 的方法,而不是把另一种语言装到 python 中。 BTW -- 如果你不喜欢字典,foo["bar"]的访问方法,另一种方法是使用 get 方法:foo.get("bar")
考虑到如果需要的话,这在Python中是很容易实现的,我看不出有什么特别的理由不这样做,而且绝对不认为这是 "把另一种语言装进Python"。特别是由于它似乎与现有的 namedtuple 的意图非常接近。
我觉得问一个问题,如果X语言有Y语言的特点,然后要求一切都完全一样,这很奇怪。语言并不完全相同。Python没有匿名函数,但他们有字典,而且工作得一样好。是的,访问语法是不同的。这是个大问题。
我并不要求功能完全相同--如果我这样做,我也会要求静态类型和不变性;)我只是要求采用我认为更加自然和方便的语法。
我一开始就倾向于创建对象,这样我就可以把数据贴在上面进行属性访问。你很快就会习惯于使用dict。
python
Pavel Minaev
Pavel Minaev
发布于 2009-07-14
8 个回答
Pavel Minaev
Pavel Minaev
发布于 2018-08-02
已采纳
0 人赞同

看起来Python 3.3正好增加了这个东西,其形式为 types.SimpleNamespace 类。

balu
这个答案应该放在最前面。
python有很多隐藏的部分,应该更加突出,并且像这样嵌入到语言中。似乎有一些人不愿意真正地使语言现代化,而不是增加这些附加的东西。 这个答案对我来说是有效的,我只需要在每次想做的时候继续回来看看这个答案就可以了
是否有一个匿名的类型提示来配合 SimpleNamespace ?假设我正在定义一个返回SimpleNamespace(x= ..., y= ...)的函数,我希望能够对结果进行类型提示,其方式如下。替换代码1】(但语法必须改变)。这类似于一个元组作为返回类型时的做法(即: def func() -> Tuple[int, str] )。
dF.
dF.
发布于 2018-08-02
0 人赞同

蟒蛇的方法是使用 dict

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

符合你所有的要求,除了你仍然要做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在他的评论中指出的那样,有问题!)

从问题中--"......dicts不是因为它们有不需要的foo["bar"]语法来访问组件吗?"
这样就可以了,只是在访问东西时是foo['x'],而不是foo.x
尽管如此,这个要求就是这样,而这并不能满足它。考虑到 namedtuple 的存在,我也看不出它是如何 "不符合Pythonic "的,因为它提供了我想要的大部分句法糖。
Alex Martelli
我认为 "Bunch"(第一种形式)是正确的答案(但我有偏见,因为这个名字是我8年多前创造的--见 code.activestate.com/recipes/52308 这也是谷歌搜索[bunch python]的最高点击率;-)。第二种形式有很深的、有些微妙的问题,做x=Bunch(update=23),看看x.update是什么? IS ;-)-- 你认为这很好吗?-)
dF.
@Alex:设置 __getattribute__ = dict.get 怎么样?丑陋,是的,但它仍然有问题吗?
alanlcode
alanlcode
发布于 2018-08-02
0 人赞同

1) See http://uszla.me.uk/space/blog/2008/11/06 . 你可以通过使用 type 内置函数来创建一个语法稍显丑陋的匿名对象。

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

其中第3个参数是dict,它将包含你的对象的字段。

 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

这个方法的好处是,你可以通过dict的内容来实现平等,而第一个选项没有这个功能。

我喜欢 "结构 "类。 对我来说非常有用,因为我的问题不需要任何特殊的方法或操作符。 简而言之,我正在使用suds/soap,大多数时候suds会为我建立一个'回复'对象,其结构由WSDL定义。如果你得到糟糕的XML,sax解析器会抛出一个异常,使你没有回复对象。我用上面的Struct类 "伪造 "一个回复对象(根据我的应用只设置属性 "错误 "和 "消息"),并将其传递给下游。 如果错误处理需要更多的属性(或方法),可以很容易地添加(扩展)这个类来匹配。 WIN。
ars
ars
发布于 2018-08-02
0 人赞同

type(...)形式将无法满足结构比较的要求(不会变得非常丑陋)。 dict(...)形式不符合属性访问器的要求。

The 判决 似乎是在中间的某个地方。

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 a.x, a.y
print b.x, b.y
print a == b

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

OK, I just noticed the update to the question. I'll just note that you can specify dict for the bases parameter and only need to specify the constructor then (in the icky type expression). I prefer 判决. :-)

rmmh
设置 self.__dict__ = self 会导致内存泄漏,所以我建议不要这样做。 bugs.python.org/issue1469629
替换代码0】的调用不是应该像这样 super(attrdict, self).__init__(*args, **kwargs) 吗?
Ken
Ken
发布于 2018-08-02
0 人赞同

我不记得是否有一个内置的,但自己写比打出你的问题要短。)

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
    
很好(我知道一般情况下怎么做,但没意识到有这么简单)。现在,真正的问题是:你是否愿意为上述内容提交一份PEP?)
顺便问一下, __neq__ 真的需要吗?默认的定义不是 not __eq__ 自动提供的吗?
Ken
帕维尔:我最初也是这么想的,但当我试过之后,似乎并没有那样做(尽管很可能是我搞砸了)。
替换代码0】应该是 __ne__ ,而不是自动提供。
skyking
skyking
发布于 2018-08-02
0 人赞同

如果你想让实例也是匿名的(在表达式中直接使用对象),那么你必然要使用类型表达式。然而在很多情况下,实例不会是匿名的,而是分配给一个变量。这种情况在python中可以通过使用元类或装饰器来合理地处理。

一个使用装饰器的例子。

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

在这种情况下,装饰器导致类foo被实例化并放入变量foo中,而不是类本身。尽管该类有一个名字,但它本身不会从任何名字空间中被访问。

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

python的另一个特点是,在本地定义类是合法的,这意味着它们将成为该函数的本地符号,这反过来又使它具有一定程度的匿名性。

user136565
user136565
发布于 2018-08-02
0 人赞同

Quoted from 本页 :

 class Struct:
     def __init__(self, **entries): self.__dict__.update(entries)
     def __eq__(self, other): return self.__dict__ == other.__dict__
     def __ne__(self, other): return self.__dict__ != other.__dict__
 options = Struct(answer=42, linelen = 80, font='courier')
 options.answer
 options.answer = 'plastics'
 vars(options)
 >>> {'answer': 'plastics', 'font': 'courier', 'linelen': 80}
    
it's not neq it's ne
TooGeeky
TooGeeky
发布于 2018-08-02
0 人赞同

如上所示,我从pycharm那里得到了一个很好的intellisense,我喜欢这个解决方案。

>>> def anonymous(cls):
...     return cls()
>>> class fooo:
...     @anonymous