python中的struct对象

时间:2009-12-10 04:55:04

标签: python

我想创建一个一次性的“struct”对象来保存各种状态标志。我的第一个方法就是这个(javascript风格)

>>> status = object()
>>> status.foo = 3  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'

绝对不是我的预期,因为这有效:

>>> class Anon: pass
... 
>>> b=Anon()
>>> b.foo = 4

我想这是因为object()没有__dict__。我不想使用字典,假设我不想创建Anon对象,还有其他解决方案吗?

8 个答案:

答案 0 :(得分:23)

制作“可以指定/获取属性的通用对象”的最简洁方法可能是:

b = lambda:0

正如大多数其他答案所指出的那样,还有很多其他的方法,但是为了简明起见很难击败这一个(lambda:0object()完全相同的字符数...... ;-)

答案 1 :(得分:15)

来自Python Official Documentation

  

9.7。赔率和结束

     

有时获取数据很有用   类似于Pascal“记录”或类型   C“struct”,捆绑在一起   命名数据项。一个空课   定义会做得很好:

class Employee:
    pass

john = Employee() # Create an empty employee record

# Fill the fields of the record 
john.name = 'John Doe' 
john.dept = 'computer lab' 
john.salary = 1000

这似乎很自然而简单:Pythonic。 Remember the Zen!“简单比复杂更好”(编号3)和“如果实施容易解释,那可能是个好主意”(编号11)

此外,struct只是公共成员的class(即struct{};class{public:};完全相同(例如,C ++) )。您是否应该考虑这一点并避免在Python程序中使用人工构造? Python应该是可读的,可维护的,易于理解的。

答案 2 :(得分:9)

我曾经有过同样的问题。我在邮件列表中问过它,Alex Martelli指出object是Python中所有继承的基础;如果object()使用自己的字典创建了一个类实例,那么Python中的每个对象都必须有自己的字典,这会浪费内存。例如,TrueFalse是对象;显然他们对自己的词典没有任何需要!

如果有某种内置的Python功能,我会很高兴我可以说:

x = struct()
x.foo = 1
x.bar = 2

但是写struct()

是微不足道的
class struct(object):
    pass

或者你可以稍微复杂一点:

class struct(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

更复杂的一个允许你这样做:

x = struct(foo=1, bar=2)
print(x.foo) # prints 1
print(x.bar) # prints 2
x.baz = 3
print(x.baz) # prints 3

但写struct()是如此微不足道,我想这不值得添加到语言中。也许我们应该推动将标准功能添加到collections模块或其他内容。

答案 3 :(得分:4)

我个人认为最干净的解决方案是你已经猜到的:

class Scratch(object):
    pass

s = Scratch()
s.whatever = 'you want'

我知道你说你不想要__dict__,但这让我感到困惑,因为我看不出有理由关心这一点。您不必引用__dict__,这是内部Python实现细节。无论如何,Python中允许动态添加属性的任何实例都将具有__dict__,因为这就是Python执行动态属性的方式。即使实例是以非常聪明的方式创建的,它也会有__dict__

如果你还没有这样做,我建议你阅读PEP 20和PEP 8(没有声望,所以对我来说只有一个链接。)并不是说PEP与你的问题直接相关,但我认为它有用开始以 Pythonic 方式使用Python。

答案 4 :(得分:3)

试试这个

>>> status=type('status',(object,),{})()
>>> status.foo=3
>>> status.foo
3

如果您不想

,则无需为该课程命名
>>> status=type('',(object,),{})()
>>> status.__class__.__name__
''

答案 5 :(得分:2)

这里的谜团是 对象 类实例 之间的区别。

在Python中,一切都是对象。类是对象,整数是对象,类型是对象,类实例是对象。当你说object()时,你得到一个简单的基础对象。没什么。完全没用。比您在Python中可以引用的任何其他级别更低级别。

您可能认为调用object()会为您提供一个类实例。这是可以理解的,因为您可能认为object是一个类。不是。即使您可能这么认为,因为它是用于新式类定义的基础“类”,如:

class MyClass(object):
    pass

object实际上是 类型 (类似于strint类型)。当您调用object()时,您没有构建类实例,而是实例化一种特殊类型的对象。但是在object的情况下,它完全是 blah 的特殊之处。

只有类实例具有使用点表示法处理事物的特殊能力。这不是所有对象的一般属性。想象一下,如果是这样的话!你可以做一些疯狂的事情,比如在字符串中添加属性:

s = "cat"
s.language = "english"

显然你不能这样做。

答案 6 :(得分:2)

当然总有namedtuple。它既便宜又快速,但不可变 - 您必须事先知道您的属性名称和值,并且以后不能更改它们的值。但至少它有struct / object属性getters。它适用于Python 2和3

>>> from collections import namedtuple
>>> Status = namedtuple('Status', 'a b')
>>> s = Status(a=1, b=2)
>>> s.a + s.b
3

答案 7 :(得分:1)

如果您想要Javascript对象的语义,可以考虑使用namespaces library。您只需先pip install namespaces

>>> import namespaces as ns
>>> b = ns.Namespace()
>>> b.foo = 4
>>> b
Namespace(foo=4)

完整免责声明:我是namespaces库的作者。