[系統互動篇] 如何將物件序列化 (將物件儲存到檔案) - tsungjung411/python-study GitHub Wiki

numpy.NaN 不能序列化,物件位址不一樣

注意:numpy.NaN 地雷

import numpy
my_dict = {'A':1, 'B':2, 'C':numpy.NaN, 'D': None, numpy.NaN:3, None: 4}
print('C:', my_dict.get('C'))
print(' - == numpy.NaN:', my_dict.get('C') == numpy.NaN)
print(' - is numpy.NaN:', my_dict.get('C') is numpy.NaN, '<---')
print(' - numpy.isnan():', numpy.isnan(my_dict.get('C')))
print(' - hash():', hash(my_dict.get('C')))
print('D:', my_dict.get('D'))
print(' - == None:', my_dict.get('D') == None)
print(' - is None:', my_dict.get('D') is None)
print(' - hash():', hash(my_dict.get('D')))
print('numpy.NaN:', my_dict.get(numpy.NaN), '<---')
print('None:', my_dict.get(None))
import pickle
with open('my_dict.pkl', 'wb') as f:
    pickle.dump(my_dict, f)
with open('my_dict.pkl', 'rb') as f:
    my_dict = pickle.load(f)
print('C:', my_dict.get('C'))
print(' - == numpy.NaN:', my_dict.get('C') == numpy.NaN)
print(' - is numpy.NaN:', my_dict.get('C') is numpy.NaN, '<---')
print(' - numpy.isnan():', numpy.isnan(my_dict.get('C')))
print(' - hash():', hash(my_dict.get('C')))
print('D:', my_dict.get('D'))
print(' - == None:', my_dict.get('D') == None)
print(' - is None:', my_dict.get('D') is None)
print(' - hash():', hash(my_dict.get('D')))
print('numpy.NaN:', my_dict.get(numpy.NaN), '<---')
print('None:', my_dict.get(None))

測試結果1:未經過序列化

測試結果2:經過序列化

A.pwd, A._pwd, A.__pwd, A.pwd 做序列化

import pickle

class A:
    def __init__(self):
        self.name = 'TJ'
        self.age = 25
        self.pwd = '12'
        self._pwd = '34'
        self.__pwd = '56'
        self.__pwd__ = '78'
    
    def __repr__(self):
        return '{name: %s, age: %d, pwd: %s, _pwd: %s, __pwd: %s, __pwd__: %s}' % (
            self.name if hasattr(self, 'name') else None, 
            self.age if hasattr(self, 'age') else 0, 
            self.pwd if hasattr(self, 'pwd') else None, 
            self._pwd if hasattr(self, '_pwd') else None, 
            self.__pwd if hasattr(self, '_' + self.__class__.__name__ + '__pwd') else None,
            self.__pwd__ if hasattr(self, '__pwd__') else None, 
        )
    
    def __getstate__(self):
        print('serailizing...')
        state = dict((k, v) 
                     for k, v in self.__dict__.items() 
                     if self.should_pickle(k))
        print('state:', state)
        return state
    
    def hello(self):
        pass
    
    def should_pickle(self, attr):
        route = 3
        if route == 3: # __attr:
            return True # attr
        elif route == 2: # __attr
            return not attr.startswith('_' + self.__class__.__name__) \
                and not attr.startswith('__')
        elif route == 1: # _attr
            return not attr.startswith('_')
        else:
            return False
        
a = A()
print('a:', a)
print('a.__dict__:', a.__dict__)

with open('a.pkl', 'wb') as f:
    pickle.dump(a, f)

執行結果:

a: {name: TJ, age: 25, pwd: 12, _pwd: 34, __pwd: 56, __pwd__: 78}
a.__dict__: {'name': 'TJ', 'age': 25, 'pwd': '12', '_pwd': '34', '_A__pwd': '56', '__pwd__': '78'}
serailizing...
state: {'name': 'TJ', 'age': 25, 'pwd': '12', '_pwd': '34', '_A__pwd': '56', '__pwd__': '78'}
a = None
with open('a.pkl', 'rb') as f:
    a = pickle.load(f)

try:
    print('a.name:', a.name)
except AttributeError:
    print("[AttributeError] has no attribute 'name'")
    
try:
    print('a.age:', a.age)
except AttributeError:
    print("[AttributeError] has no attribute 'age'")
    
try:
    print('a._pwd:', a._pwd)
except AttributeError:
    print("[AttributeError] has no attribute '_pwd'")

try:
    print('a.__pwd:', a.__pwd) # always failed (not allowed)
except AttributeError:
    print("[AttributeError] has no attribute '__pwd'")
    
try:
    print('a.__pwd__:', a.__pwd__)
except AttributeError:
    print("[AttributeError] has no attribute '__pwd__'")

執行結果:

a.name: TJ
a.age: 25
a._pwd: 34
[AttributeError] has no attribute '__pwd'
a.__pwd__: 78