シリアライズ

新スタイルクラスでやりたい放題。

Pythonのクラスには、
class A:
    ...
と書き始める「古い」スタイルのクラスと、
class A(object):
    ....
と書き始める「新しい」スタイルのクラスがあります。
下のスタイルで追加された変数を用いると、色々と面白いことができます。
まずは__class__。このオブジェクトがどのクラスのインスタンスか知りたければ、
a = A()
b = A()
if a.__class__ == b.__class__:
    print "Onaji!"
else :
    print "Chigau!"
みたいに使えます。JavaだとinstanceOfってのがありますね。 さらにこわいことに、この__class__に代入することによって、動的にどのクラスのインスタンスか変えることができます。こわいこわい…
あと、メンバ変数に値を追加したいけど、その変数の名前が変数に入ってる… というとき、C++やJavaだとswitchで変数ごとの振り分けを書かなければいけません。 でも、pythonの__dict__を使うと一発です。
class A(object):
    def __init__(self):
        self.temperature = 20

a = A()
a.__dict__["weather"] = "fine"
print a.weather

いつの間にかaにweatherという変数が追加されています。こわいこわい。

シリアライズのサンプル (新)

シリアライズのサンプルを作ってみました。適当なクラスをmyObjectを継承して書くと、 save()とload()が使えるようになるはずです。(セキュリティ的にはだめだめです)
class myObject(object):
    def load(self, fn):
        fd = open(fn, "r")
        lines = fd.readlines()
        cursor = 0
        while cursor < len(lines):
            key = eval(lines[cursor])
            value = eval(lines[cursor+1])
            self.__dict__[key] = value
            cursor += 2
        fd.close()


    def save(self, fn):
        fd = open(fn, "w")
        for key,value in self.__dict__.items():
            print >> fd, repr(key)
            print >> fd, repr(value)
        fd.close()
こんなふうにつかう。
class A(myObject):
    def __init__(self, fn = None):
        if fn is None:
            self.A = {"a":123, "b":234, "c":345}
            self.B = "ancde"
        else:
            self.load(fn)

a = A()
a.save("x")
ax = A("x")
print ax.A, ax.B

シリアライズのサンプル (旧)

ちょっと古いやつ。上のが高機能。
シリアライズのサンプルを作ってみました。文字列型のメンバ変数しかサポートしていません。
[変数名の長さ][変数名][値の長さ][値]というバイト列に変換します。
import struct

class A(object):
    def __init__(self, **args):
        if "fromHost" in args:
            self.fromHost = args["fromHost"]
            self.toHost   = args["toHost"]
            self.filename = args["filename"]
            
        elif "str_expr" in args:
            self.deserialize(args["str_expr"])
        else :
            raise "Unsupported way to construct"


    def deserialize(self, msg):
        tip = struct.calcsize('l')
        cnt = 0
        while len(msg) > cnt :
            keylen = struct.unpack('l', msg[cnt:(cnt+tip)])[0]
            cnt += tip
            key = msg[cnt:(cnt + keylen)]
            cnt += keylen
            valuelen = struct.unpack('l', msg[cnt:(cnt+tip)])[0]
            cnt += tip
            value = msg[cnt:(cnt + valuelen)]
            cnt += valuelen
            self.__dict__[key] = value
        

    def serialize(self) :
        ret = ""
        for key in ["fromHost", "toHost", "filename"]:
            value = self.__dict__[key]
            ret += struct.pack('l', len(key)) + key
            ret += struct.pack('l', len(value)) + value
        return ret


    def write(self) :
        for key in self.__dict__:
            value = self.__dict__[key]
            print "  %s = %s"%(key, value)


a = A(fromHost = "192.169.0.1", toHost = "192.168.0.2", filename = "hoge.c")
msg = a.serialize()
b = A(str_expr = msg)
b.write()