2016-04-13 8 views
0

誰かがこの小さな問題で私を助けてくれれば幸いです。複雑なPythonデータ構造(dict、list、tuple、strings、bytes、...)を繰り返し、すべてのバイト(バイト文字列)をbase64でエンコードされたバージョンに置き換えたいと思います。これは、JSONがバイナリデータをサポートしていないため、元の複合データ構造をJSON(たとえばjson.dumps(complex_data_structure))に変換するために必要です。私のコードはすでに正しいことをしていますが、Python固有の問題が1つあります。ここに私のコードは次のとおりです。複雑な辞書の反復処理中にPythonオブジェクトへの参照を取得する

import sys 
import json 
import base64 


def iter_object(obj): 
    if type(obj) is tuple: 
     iter_tuple(obj) 
    elif type(obj) is dict: 
     iter_dict(obj) 
    elif type(obj) is list: 
     iter_list(obj) 
    else: # non iterable types except of string and bytes etc. 
     if type(obj) is bytes: 
      # THE PROBLEM IS THE COPY OF OBJ! 
      obj = base64.b64encode(obj).decode("ascii") 
     else: 
      pass # we don't care about other data types 


def iter_tuple(obj_tuple): 
    for t in obj_tuple: 
     iter_object(t) 


def iter_list(obj_list): 
    for l in obj_list: 
     iter_object(l) 


def iter_dict(obj_dict): 
    for k, v in obj_dict.items(): 
     iter_object(v) 


def main(): 

    test_dict = { 
     "foo": [1, 3, 4, 5, 6, 7], 
     "bar": 1, 
     "baz": (1, 2), 
     "blub": { 
      "bla": b"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41", 
      "ble": { 
       "blu": [ 
        1, 3, b"\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42", 
        (1, [b"\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43"]) 
       ] 
      } 
     } 
    } 

    iter_object(test_dict) 

    print(json.dumps(test_dict)) 

    return 0 


if __name__ == "__main__": 
    sys.exit(main()) 

それはコピーではありません参照に取り組んでいますので、問題は(C++でそれを言うために)ラインobj = base64.b64encode(obj).decode("ascii")です。ここに私の質問です:上記のコードを動作させる回避策はありますか?

ありがとうございました!

答えて

1

コピーで動作しますか?いいえ。何が起こっているのかは、関数がその値を変更する代わりに値を返すことです。これは、バイト文字列が不変であるためです。 pythonの値渡しや参照渡しの概念はありません。変数はオブジェクトを保持するボックスではなく、あるオブジェクトのという名前のです。機能は、それが別のオブジェクトを返すことがある不変オブジェクトに作用するのであればtuplestrbytes

からlistsetdict

  • 不変 - オブジェクトが

    1. 変更可能なことができます。メモリ使用量が最適化されています。そして、これはHaskellのような言語におけるデファクト・ウェイです。

  • +0

    おかげで、あなたが答えるために。上記のコードが意図したとおりに正しく動作するように、問題の解決策はありますか?私はPythonの問題を解決する方法がないとは想像できません。私は別のアプローチを取ることができますか、それに対して回避策がありますか?前もって感謝します! – metaphysicalmarty

    0

    私は私の問題への解決策を見つけた:

    import sys 
    import json 
    import base64 
    
    class BinaryToBase64Encoder(json.JSONEncoder): 
        def default(self, o): 
         if isinstance(o, bytes): 
          return base64.b64encode(o).decode("ascii") 
         return super(BinaryToBase64Encoder, self).default(o) 
    
    
    def main(): 
    
        test_dict = { 
         "foo": [1, 3, 4, 5, 6, 7], 
         "bar": 1, 
         "baz": (1, 2), 
         "blub": { 
          "bla": b"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41", 
          "ble": { 
           "blu": [ 
            1, 3, b"\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42", 
            (1, [b"\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43"]) 
           ] 
          } 
         } 
        } 
    
        print(json.dumps(test_dict, cls=BinaryToBase64Encoder)) 
    
        return 0 
    
    
    if __name__ == "__main__": 
        sys.exit(main()) 
    

    JSON出力は次のとおりです。

    { 
        "foo": [1, 3, 4, 5, 6, 7], 
        "baz": [1, 2], 
        "bar": 1, 
        "blub": { 
         "ble": { 
          "blu": [ 
           1, 
           3, 
           "QkJCQkJCQkJCQkJCQkJCQkJCQkI=", 
           [ 
            1, 
            ["Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0M="] 
           ] 
          ] 
         }, 
         "bla": "QUFBQUFBQUFBQUFBQUFBQUFBQUE=" 
        } 
    }