1

バイナリファイル形式(〜15の異なる構造)のリーダー/ライターを実装していますが、使用するデザインパターンに少しジレンマがあります。

  1. 各構造には、パック/アンパックのメソッドが含まれています。

    class Struct1:  
        def pack():
            struct.pack(self.foo)
            ...
        def unpack():  
            self.foo = struct.unpack()
            ...
    class Struct2:  
        def pack():
            struct.pack(self.foo)
            ...
        def unpack():  
            self.foo = struct.unpack()
            ...
    ...
    

    対。

  2. 構造ごとに読み取り/書き込みメソッドを持つReader/Writerクラスがあります。

    class Reader:
        def read_struct1():
            s = Struct1()
            s.foo = struct.unpack()
            ...
            return s
        def read_struct2():
            s = Struct2()
            s.foo = struct.unpack()
            ...
            return s
        ...
    class Writer:
        def write_struct1(s):
            struct.pack(s.foo)
            ...
        def write_struct2(s):
            struct.pack(s.foo)
            ...
        ...
    
4

4 に答える 4

2

個別のReader/Writerクラスを作成する目的は、コンソールへの書き込み、バイトへの書き込み、JSON文字列への書き込みなど、さまざまな出力処理をサポートすることです。重要なことは、Struct1、Struct2などの各クラスが、状態を保存するために重要な属性を認識していることです。これは、ピクルスモジュールで使用される哲学です。

class Struct1(object):
    fields = ('a','b','c')
    ...

class Struct2(object):
    fields = ('foo', 'bar', 'baz')
    ...

これで、クラス固有のコードを記述しなくても、このメタデータを使用してさまざまなライタークラスを記述できます。

class StructWriter(object):
    packTypeMap = {int:'i', float:'f', str:'s'}

    def write(self, obj):
        fields = obj.fields
        packstring = ''.join(packTypeMap[type(f)] for f in fields)
        packargs = (getattr(obj,f) for f in fields)
        return struct.pack(packstring, *packargs)

class DictWriter(object):
    def write(self, obj):
        return dict((f, getattr(obj,f)) for f in obj.fields)

class JSONWriter(object):
    jsonTypeMap = {str:lambda s:"'"+s+"'"}
    defaultJsonFunc = lambda x:str(x)
    def write(self, obj):
        # not really recommended to roll your own strings, but for illustration...
        fields = obj.fields
        outargs = (getattr(obj,f) for f in fields)
        outvals = (jsonTypeMap.get(type(arg),defaultJsonFunc)(arg) 
                       for arg in outargs)
        return ('{' +
            ','.join("'%s':%s" % field_val for field_val in zip(fields, outvals))
            '}')

class ZipJSONWriter(JSONWriter):
    def write(self, obj):
        import zlib
        return zlib.compress(super(ZipJSONWriter,self).write(obj))        

class HTMLTableWriter(object):
    def write(self, obj):
        out = "<table>"
        for field in obj.fields:
            out += "<tr><td>%s</td><td>%s</td></tr>" % (field, getattr(obj,field))
        out += "</table>"
        return out
于 2012-12-27T14:59:51.207 に答える
1

前者の方がはるかに理にかなっているようです。構造はであるため、オブジェクトとして表現する方が理にかなっています。2番目の方法に本当の利点はありません。

于 2012-12-27T14:02:38.500 に答える
0

それらはオブジェクトである必要がありますか?pack管理の目的で、 /unpack文字列をdict((名前付き)タプルを値として)に入れて、それを別のモジュールに入れることを検討したくなるでしょう...

some_file.py:

structs = {
    'struct1': ('unpack', 'pack'),
    'struct2': ('other unpack', 'other pack')
...
}

そして、必要に応じて、PackerUnPackerそれを取得して使用するクラスが必要です...

于 2012-12-27T14:23:20.273 に答える
0

重要なのは、コードの重複を避けるために、クラスの継承をどのように最大限に活用できるかということです。pack私はcommon /unpackメソッドの抽象クラスを定義しようとします:

class PackUnpack(object):  
    def pack(self):
        struct.pack(self.foo)
        ...
    def unpack(self):  
        self.foo = struct.unpack()
        ...

class Struct1(object, PackUnpack):
    ...

class Struct2(object, PackUnpack):
    ...

しかし、これが不可能である(または実装するのが面倒である)場合でも、最初の選択肢はより自然で、何らかの形で保守が容易であるように思われます。

于 2012-12-27T14:34:55.830 に答える