是否有一种方法可以方便地在Python中定义类c结构?我厌倦了写这样的东西:
class MyStruct():
def __init__(self, field1, field2, field3):
self.field1 = field1
self.field2 = field2
self.field3 = field3
是否有一种方法可以方便地在Python中定义类c结构?我厌倦了写这样的东西:
class MyStruct():
def __init__(self, field1, field2, field3):
self.field1 = field1
self.field2 = field2
self.field3 = field3
当前回答
这里有一个快速而肮脏的技巧:
>>> ms = Warning()
>>> ms.foo = 123
>>> ms.bar = 'akafrit'
它是如何工作的?它只是重用内置类警告(从异常派生),并使用它,因为它是你自己定义的类。
优点是您不需要首先导入或定义任何东西,“警告”是一个简短的名称,并且它还清楚地表明您正在做一些肮脏的事情,不应该在其他地方使用,而应该在您的小脚本中使用。
顺便说一下,我试图找到一些更简单的东西,如ms = object(),但不能(最后一个例子是不工作)。如果你有的话,我很感兴趣。
其他回答
也许你正在寻找没有构造函数的struct:
class Sample:
name = ''
average = 0.0
values = None # list cannot be initialized here!
s1 = Sample()
s1.name = "sample 1"
s1.values = []
s1.values.append(1)
s1.values.append(2)
s1.values.append(3)
s2 = Sample()
s2.name = "sample 2"
s2.values = []
s2.values.append(4)
for v in s1.values: # prints 1,2,3 --> OK.
print v
print "***"
for v in s2.values: # prints 4 --> OK.
print v
一本字典怎么样?
就像这样:
myStruct = {'field1': 'some val', 'field2': 'some val'}
然后你可以使用这个来操作值:
print myStruct['field1']
myStruct['field2'] = 'some other values'
值不一定是字符串。它们可以是其他任何物体。
更新:数据类
随着Python 3.7中数据类的引入,我们已经非常接近了。
下面的示例与下面的NamedTuple示例类似,但是生成的对象是可变的,并且允许使用默认值。
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
z: float = 0.0
p = Point(1.5, 2.5)
print(p) # Point(x=1.5, y=2.5, z=0.0)
如果您想使用更特定的类型注释,这可以很好地配合新的类型模块。
我一直在绝望地等待这一刻!要我说,Data Classes和新的NamedTuple声明,再加上typing模块,简直就是天赐之物!
改进的NamedTuple声明
自从Python 3.6以来,它变得非常简单和美丽(恕我直言),只要你能忍受不变性。
引入了一种声明NamedTuples的新方法,它也允许类型注释:
from typing import NamedTuple
class User(NamedTuple):
name: str
class MyStruct(NamedTuple):
foo: str
bar: int
baz: list
qux: User
my_item = MyStruct('foo', 0, ['baz'], User('peter'))
print(my_item) # MyStruct(foo='foo', bar=0, baz=['baz'], qux=User(name='peter'))
我能想到的最干净的方法是使用一个类装饰器,它可以让你声明一个静态类,并将其重写为一个具有正常命名属性的结构体:
from as_struct import struct
@struct
class Product():
name = 'unknown product'
quantity = -1
sku = '-'
# create instance
p = Product('plush toy', sku='12-345-6789')
# check content:
p.name # plush toy
p.quantity # -1
p.sku # 12-345-6789
使用以下装饰器代码:
def struct(struct_class):
# create a new init
def struct_init(self, *args, **kwargs):
i = 0 # we really don't need enumerate() here...
for value in args:
name = member_names[i]
default_value = member_values[i]
setattr(self, name, value if value is not None else default_value)
i += 1 # ...we just need to inc an int
for key,value in kwargs.items():
i = member_names.index(key)
default_value = member_values[i]
setattr(self, key, value if value is not None else default_value)
# extract the struct members
member_names = []
member_values = []
for attr_name in dir(struct_class):
if not attr_name.startswith('_'):
value = getattr(struct_class, attr_name)
if not callable(value):
member_names.append(attr_name)
member_values.append(value)
# rebind and return
struct_class.init = struct_init
return struct_class
它的工作原理是获取类,提取字段名及其默认值,然后重写类的__init__函数,根据知道哪个参数索引映射到哪个属性名来设置self属性。
你可以用元组来做很多你在C语言中使用结构体的事情(比如x,y坐标或RGB颜色)。
对于其他任何东西,你可以使用字典,或像这样的实用程序类:
>>> class Bunch:
... def __init__(self, **kwds):
... self.__dict__.update(kwds)
...
>>> mystruct = Bunch(field1=value1, field2=value2)
我认为“权威”的讨论在这里,在Python Cookbook的出版版本中。