ฉันไม่รู้ว่า__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
, ,str
list
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 อัปสตรีม
วิธีการเหล่านี้ใช้สำหรับควบคุมวิธีการดองและไม่หยิบวัตถุโดยโมดูลดอง โดยปกติจะได้รับการจัดการโดยอัตโนมัติดังนั้นหากคุณไม่จำเป็นต้องลบล้างวิธีการดองหรือไม่ได้รับการคัดเลือกในชั้นเรียนคุณก็ไม่จำเป็นต้องกังวลเกี่ยวกับเรื่องนี้