Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对于Python结构,使用具有有意义的字段名值的数组是否不是pythonic?_Python_Struct - Fatal编程技术网

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

对于Python结构,使用具有有意义的字段名值的数组是否不是pythonic?,python,struct,Python,Struct,我看到了一些关于如何在Python中实现Cstruct之类的东西的问题。通常人们建议使用namedtuple,但问题是,它的字段是不可变的,我认为不可变的结构没有多大意义,因此如果需要,建议使用dictionary,在我看来,这太冗长了-必须用引号将字段名括起来,它必须非常慢-您必须搜索字段值 我从来没有看到过对我来说似乎是自然的解决方案: i = -1 i += 1 FIELD_A = i i += 1 FIELD_B = i i += 1 FIELD_C = i structure

我看到了一些关于如何在Python中实现C
struct
之类的东西的问题。通常人们建议使用
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
操作的原因是,它允许复制和粘贴,而不可能两次指定相同的值或浪费空间。使用大写字母的原因是为了使这些值成为“常量”


我是不是太天真了,上面的代码有什么问题,或者不是Pythonic?

使用dict替代您的代码:

structure = {}
structure["FIELD1"] = 0
structure["FIELD2"] = "foo"
structure["FIELD3"] = "bar
在我看来,代码行更少,可读性更高,因为您不必怀疑
i
到底在做什么。在MATLAB中工作时,我实际上使用了上述方法,因为没有方便的dict替代方法


此外,如果您发现大写字母更具可读性,那么没有什么可以阻止您使用大写字母。

使用dict的代码的替代方案:

structure = {}
structure["FIELD1"] = 0
structure["FIELD2"] = "foo"
structure["FIELD3"] = "bar
在我看来,代码行更少,可读性更高,因为您不必怀疑
i
到底在做什么。在MATLAB中工作时,我实际上使用了上述方法,因为没有方便的dict替代方法


此外,如果您觉得大写字母更具可读性,那么没有什么可以阻止您使用大写字母。

我认为最接近C-struct的类比,以Python的方式,应该是具有命名属性的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
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)

我认为,以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
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)
“它一定很慢-你必须搜索字段值。”如果你认为字典查找很慢,那么python会给你一系列心脏病发作。考虑

foo = 'somestring'
bar = bar
baz = someobj.variable
Python计算了
'somestring'
的哈希值,因为它在创建所有字符串时都会这样做。每次我们提到它们时,它都会在模块的名称空间中向上看
foo
bar
。访问对象变量需要在对象的
dict
中查找它们

获得类似结构的行为的两种方法是定义类级别的变量或使用
\uuuuu slots\uuuu
为对象定义一组固定的变量

# '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
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快多少。“它一定很慢-您必须搜索字段值。”如果您认为字典查找很慢,那么python将给您带来一连串的心脏病发作。考虑

foo = 'somestring'
bar = bar
baz = someobj.variable
Python计算了
'somestring'
的哈希值,因为它在创建所有字符串时都会这样做。每次我们提到它们时,它都会在模块的名称空间中向上看
foo
bar
。访问对象变量需要在对象的
dict
中查找它们

获得类似结构的行为的两种方法是定义类级别的变量或使用
\uuuuu slots\uuuu
为对象定义一组固定的变量

# '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
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)

这些可能令人愉快,但它们并不比使用
口述快

我感谢所有其他答案,但它们并不能真正回答问题。问题是“我的代码出了什么问题”,而不是“编码xyz的最佳方式是什么”


我发现错的是,我引入了一组“全局”常数。如果我有另一个带有
字段A
的结构,我就有麻烦了<代码>字段_A应具有结构范围,而不是全局范围。这是我所做的不符合标准的一个重要原因。

我很欣赏所有其他答案,但它们并不能真正回答问题。问题是“我的代码出了什么问题”,而不是“编码xyz的最佳方式是什么”


我发现错的是,我引入了一组“全局”常数。如果我有另一个带有
字段A
的结构,我就有麻烦了<代码>字段_A应具有结构范围,而不是全局范围。这是我所做的不符合标准的一个重要原因。

字典并不慢……它们通常实现为非常快的哈希表查找。此外,您不必将键名放在引号中,您可以使用任何不可变类型作为键…实际上,您已经将键映射到了这里的整数。最后,我不会考虑把引号作为“VBOSE”和“不是”之间的区别。@ GAREPPY当然要查找一个字符串的哈希值,你必须对整个字符串进行评估并计算哈希值,也许这是快的,但是肯定比查找数组中的值慢。这取决于你在做什么。你所拥有的实际上是一个列表,一旦列表变大,添加到列表中的速度就会变慢。无论大小,添加到dict几乎都是一个常量时间操作。为什么不使用类呢?它们将是可变的,并且比DICT快得多