对于Python结构,使用具有有意义的字段名值的数组不是pythonic吗?

2024-09-29 00:13:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我看到了一些关于如何在Python中实现Cstruct之类的问题。通常人们推荐一个namedtuple,但问题是,它的字段是不可变的,而且我认为拥有一个不可变的结构没有多大意义,所以如果需要的话,那么推荐一个dictionary,在我看来,它太冗长了-你必须用引号将字段名括起来,而且,它一定非常慢-你必须搜索字段值。你知道吗

我从来没有看到过一个自然的解决方案:

i = -1

i += 1
FIELD_A = i

i += 1
FIELD_B = i

i += 1
FIELD_C = i

structure = [ 0, "foo", "bar" ]
structure[FIELD_A] = 1

之所以使用i操作,是因为它允许复制和粘贴,而不可能两次指定相同的值或浪费空间。之所以使用大写字母是为了使这些值突出显示为“常量”。你知道吗

我是不是太天真了,有什么不对劲的地方,或者说不是Python?你知道吗


Tags: fielddictionaryfoobar解决方案namedtuplestructure结构
3条回答

我认为,以Python的方式,与C-struct最接近的类比应该是具有命名属性的Python对象。你知道吗

繁琐的方式:

class mystruct:
    def __init__(self):
        self.FIELD1 = None
        self.FIELD2 = None
        self.FIELD3 = None

x = mystruct()
x.FIELD1 = 42
x.FIELD3 = "aap" 

可以使用type函数生成具有多个属性的匿名对象:

y = type('', (), {'FIELD1': None, 'FIELD2':None})()
y.FIELD1 = 42

但这仍然很麻烦。但这可以通过编写一个返回函数的函数来简单地概括,该函数将创建一个对象的实例。你知道吗

# 'objmaker' takes a list of field names and returns a function
# which will create an instance of an object with those fields, their
# values initially set to None
objmaker = lambda *fields: type('', (), {field: None for field in fields})

# Now it's trivial to define new 'structs' - here we 'define' two
# types of 'structs'
mystruct_maker = objmaker('FIELD1', 'FIELD2', 'FIELD3')
yourstruct_maker = objmaker('x', 'y')

# And creating instances goes like this:
my_str1 = mystruct_maker()
my_str2 = mystruct_maker()
yr_str  = yourstruct_maker()

yr_str.x = 42
my_str1.FIELD1 = yr_str.x

“它一定很慢-您必须搜索字段值。”如果您认为字典查找很慢,那么python会给您带来一系列的心脏病发作。考虑

foo = 'somestring'
bar = bar
baz = someobj.variable

Python计算了'somestring'的哈希值,因为它在创建所有字符串时都是这样做的。每次我们提到它们时,它都会在模块的命名空间foobar中查找它们。访问对象变量需要在对象的dict中查找它们。你知道吗

获得类似结构的行为的两种方法是定义类级变量或使用__slots__为对象定义一组固定的变量。你知道吗

class MyStruct(object):

    FIELD1 = 0
    FIELD2 = 'foo'
    FIELD3 = 'bar'

print(MyStruct.FIELD2)
s = MyStruct()
s.FIELD2 = 'baz'
print(s.FIELD2)    

class MySlots(object):

    __slots__ = ['FIELD1', 'FIELD2', 'FIELD3']

    def __init__(self, FIELD1=0, FIELD2='foo', FIELD3='bar'):
        self.FIELD1 = FIELD1
        self.FIELD2 = FIELD2
        self.FIELD3 = FIELD3

s = MySlots()
print(s.FIELD2)

这些可能是令人愉快的,但它们并不比使用dict快。你知道吗

使用dict替代您的代码:

structure = {}
structure["FIELD1"] = 0
structure["FIELD2"] = "foo"
structure["FIELD3"] = "bar

在我看来,代码行更少,可读性更高,因为您不必怀疑i到底发生了什么。实际上,我在使用MATLAB时使用了上述方法,因为没有方便的dict替代方法。你知道吗

此外,如果你觉得大写字母更容易阅读,那么没有什么可以阻止你使用大写字母。你知道吗

相关问题 更多 >