ฉันไม่รู้ว่า__setstate__และ __getstate__วิธีการทำอย่างไรจึงช่วยฉันด้วยตัวอย่างง่ายๆ
ฉันไม่รู้ว่า__setstate__และ __getstate__วิธีการทำอย่างไรจึงช่วยฉันด้วยตัวอย่างง่ายๆ
คำตอบ:
นี่เป็นตัวอย่างที่ง่ายมากสำหรับงูหลามที่ควรเสริมเอกสารดอง
class Foo(object):
def __init__(self, val=2):
self.val = val
def __getstate__(self):
print("I'm being pickled")
self.val *= 2
return self.__dict__
def __setstate__(self, d):
print("I'm being unpickled with these values: " + repr(d))
self.__dict__ = d
self.val *= 3
import pickle
f = Foo()
f_data = pickle.dumps(f)
f_new = pickle.loads(f_data)
ตัวอย่างน้อยที่สุด
สิ่งที่ออกมาของจะเข้าสู่getstate setstateไม่จำเป็นต้องเป็นคำสั่ง
สิ่งที่ออกมาของgetstateต้อง pickeable เช่นสร้างขึ้นจากพื้นฐานตัว -ins เช่นint, ,strlist
class C(object):
def __init__(self, i):
self.i = i
def __getstate__(self):
return self.i
def __setstate__(self, i):
self.i = i
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1
ค่าเริ่มต้น __setstate__
ค่าเริ่มต้น__setstate__ใช้เวลา a dict.
self.__dict__เป็นทางเลือกที่ดีเช่นเดียวกับในhttps://stackoverflow.com/a/1939384/895245แต่เราสามารถสร้างขึ้นมาเองเพื่อดูว่าเกิดอะไรขึ้น:
class C(object):
def __init__(self, i):
self.i = i
def __getstate__(self):
return {'i': self.i}
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1
ค่าเริ่มต้น __getstate__
คล้ายคลึงกับ__setstate__.
class C(object):
def __init__(self, i):
self.i = i
def __setstate__(self, d):
self.i = d['i']
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1
__slots__ วัตถุไม่มี __dict__
ถ้าวัตถุมีแสดง__slots__ว่าไม่มี__dict__
หากคุณกำลังจะใช้ทั้งสองgetและsetstateวิธีเริ่มต้นคือ:
class C(object):
__slots__ = 'i'
def __init__(self, i):
self.i = i
def __getsate__(self):
return { slot: getattr(self, slot) for slot in self.__slots__ }
def __setsate__(self, d):
for slot in d:
setattr(self, slot, d[slot])
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1
__slots__ เริ่มต้นรับและตั้งค่าคาดว่าจะมีทูเพิล
หากคุณต้องการนำค่าเริ่มต้นกลับมาใช้ใหม่__getstate__หรือ__setstate__คุณจะต้องส่งสิ่งต่อไปนี้เป็น:
class C(object):
__slots__ = 'i'
def __init__(self, i):
self.i = i
def __getsate__(self):
return (None, { slot: getattr(self, slot) for slot in self.__slots__ })
assert pickle.loads(pickle.dumps(C(1), -1)).i == 1
ฉันไม่แน่ใจว่านี่คืออะไร
มรดก
ก่อนอื่นให้ดูว่าการดองทำงานตามค่าเริ่มต้น:
class C(object):
def __init__(self, i):
self.i = i
class D(C):
def __init__(self, i, j):
super(D, self).__init__(i)
self.j = j
d = pickle.loads(pickle.dumps(D(1, 2), -1))
assert d.i == 1
assert d.j == 2
ประเพณีการสืบทอด __getstate__
หากไม่มี__slots__มันเป็นเรื่องง่ายเนื่องจาก__dict__for Dมี__dict__for Cดังนั้นเราจึงไม่จำเป็นต้องแตะCเลย:
class C(object):
def __init__(self, i):
self.i = i
class D(C):
def __init__(self, i, j):
super(D, self).__init__(i)
self.j = j
def __getstate__(self):
return self.__dict__
def __setstate__(self, d):
self.__dict__ = d
d = pickle.loads(pickle.dumps(D(1, 2), -1))
assert d.i == 1
assert d.j == 2
มรดกและ __slots__
ด้วย__slots__เราจำเป็นต้องส่งต่อไปยังคลาสพื้นฐานและสามารถส่งต่อสิ่งรอบตัว:
class C(object):
__slots__ = 'i'
def __init__(self, i):
self.i = i
def __getstate__(self):
return { slot: getattr(self, slot) for slot in C.__slots__ }
def __setstate__(self, d):
for slot in d:
setattr(self, slot, d[slot])
class D(C):
__slots__ = 'j'
def __init__(self, i, j):
super(D, self).__init__(i)
self.j = j
def __getstate__(self):
return (
C.__getstate__(self),
{ slot: getattr(self, slot) for slot in self.__slots__ }
)
def __setstate__(self, ds):
C.__setstate__(self, ds[0])
d = ds[1]
for slot in d:
setattr(self, slot, d[slot])
d = pickle.loads(pickle.dumps(D(1, 2), -1))
assert d.i == 1
assert d.j == 2
น่าเสียดายที่ไม่สามารถใช้ค่าเริ่มต้น__getstate__และ__setstate__ฐานซ้ำได้: https://groups.google.com/forum/#!topic/python-ideas/QkvOwa1-pHQเราถูกบังคับให้กำหนด
ทดสอบกับ Python 2.7.12 GitHub อัปสตรีม
วิธีการเหล่านี้ใช้สำหรับควบคุมวิธีการดองและไม่หยิบวัตถุโดยโมดูลดอง โดยปกติจะได้รับการจัดการโดยอัตโนมัติดังนั้นหากคุณไม่จำเป็นต้องลบล้างวิธีการดองหรือไม่ได้รับการคัดเลือกในชั้นเรียนคุณก็ไม่จำเป็นต้องกังวลเกี่ยวกับเรื่องนี้