更优雅的二进制转换?
这里有一个例子,展示了我们很多类是如何返回它们自己的二进制表示(可以被C++读取)的。
def to_binary(self):
'Return the binary representation as a string.'
data = []
# Binary version number.
data.append(struct.pack('<I', [2]))
# Image size.
data.append(struct.pack('<II', *self.image.size))
# Attribute count.
data.append(struct.pack('<I', len(self.attributes)))
# Attributes.
for attribute in self.attributes:
# Id.
data.append(struct.pack('<I', attribute.id))
# Type.
data.append(struct.pack('<H', attribute.type))
# Extra Type.
if attribute.type == 0:
data.append(struct.pack('<I', attribute.typeEx))
return ''.join(data)
我不喜欢的地方:
- 每一行都以
data.append(struct.pack(
开头,这让人分心,没法专注于这一行的重点。 - 字节顺序(
'<'
)重复出现,让人觉得烦。 - 你得记得返回那段固定的代码
''.join(data)
。
我喜欢的地方:
- 格式说明符靠近属性名,这样很容易看出
self.image.size
是用两个无符号整数表示的。 - 这些行(大部分)是独立的。比如,要从一个“属性”中移除Id字段,你只需要改一行代码。
有没有更易读、更符合Python风格的方法来做到这一点呢?
8 个回答
2
你觉得谷歌的 协议缓冲区 怎么样?它是一种可以在不同编程语言之间共享数据的格式和协议,功能非常强大。
4
你可以尝试为你的数据实现一种类似于声明式语法的东西。
这样可能会得到像下面这样的结果:
class Image(SomeClassWithMetamagic):
type = PackedValue(2)
attribute = PackedValue('attributes') # accessed via self.__dict__
#or using decorators
@pack("<II")
def get_size():
pass
#and a generic function in the Superclass
def get_packed():
stuff
等等...
其他的例子包括SQLAlchemy的declarative_base、ToscaWidgets和sprox。
4
在编程中,有时候我们会遇到一些问题,可能是因为代码写得不够好,或者是我们对某些概念理解得不够透彻。比如,有人可能会在使用某个功能时,发现它的表现和预期不一样。这种情况通常需要我们仔细检查代码,看看哪里出了问题。
另外,编程语言和工具的使用也会影响我们的代码运行效果。有些功能在不同的环境下表现可能会有所不同,所以我们需要了解这些工具的特性,才能更好地使用它们。
总之,编程是一门需要不断学习和实践的技能,遇到问题时不要气馁,仔细分析,逐步解决,才能不断进步。
from StringIO import StringIO
import struct
class BinaryIO(StringIO):
def writepack(self, fmt, *values):
self.write(struct.pack('<' + fmt, *values))
def to_binary_example():
data = BinaryIO()
data.writepack('I', 42)
data.writepack('II', 1, 2)
return data.getvalue()