我想将可迭代的 Python 类编码为 JSON,但是 JSON-Pickle 在解码时将其作为列表生成器返回。这是我的代码:
from typing import Iterable
from Helper import Helper
from RCEnum import RCEnum
import jsonpickle
class InnerTable:
def __init__(self, rows, cols):
if not Helper.lio(int, rows, cols) or rows<1 or cols<1: raise Exception("Invaild rows and or cols")
ret={"rows":[[None]*(cols+1)], "cols":[[None]*(rows+1)]}
tid=[]
self.rows=rows
self.cols=cols
for r in range(1, rows+1):
ret["rows"].append([None])
for c in range(1, cols+1):
f=str(r)+"&"+str(c)
tid.append((r, c))
ret["rows"][-1].append(f)
if c==len(ret["cols"]):
ret["cols"].append([None, f])
else:
ret["cols"][c].append(f)
self.table=ret
self.tid=tid
self.element=0
def __iter__(self):
return self
def __next__(self):
try:
i=self.element
self.element+=1
return self[self.tid[i]]
except IndexError:
self.element=0
raise StopIteration
def __len__(self):
return self.cols*self.rows
def __getitem__(self, item):
if item=="rows":
return self.table["rows"]
elif item=="cols":
return self.table["cols"]
elif isinstance(item, Iterable) and len(item)==2:
if isinstance(item[0], bool) and isinstance(item[1], int):
if item[0]:
return self[self.tid[item[1]]]
else:
return self[self.tid[-item[1]]]
if Helper.lio(int, item):
return self[item[0]][item[1]]
else:
return self.table["rows"][item]
def changeElement(self, a, b, nv, loc="rows"):
try:
if not (loc.lower()==RCEnum.C.value or loc.lower()==RCEnum.R.value): raise IndexError("not a valid location ")
loc2=RCEnum.C.value if loc.lower()==RCEnum.R.value else RCEnum.R.value
self[loc][a][b]=nv
self[loc2][b][a]=nv
except Exception as e:
print("Not changed. Reason "+str(e))
def getNFieldsInRoCAC(self, roc, l, direct=1, loc="rows"):
if not (loc.lower()==RCEnum.C.value or loc.lower()==RCEnum.R.value): raise IndexError("not a valid location ")
fields=self[loc][roc] if direct>0 else [None]+list(reversed(self[loc][roc]))[:-1]
ret=[]
alwaysNotIn=[]
for ni in range(1, len(self[loc])):
if ni==roc: continue
alwaysNotIn.extend(self[loc][ni][1:])
for i in range(1, len(fields)+1):
if i+l>len(fields): break
current=fields[i:i+l]
currentNonFields=fields[1:i]+fields[i+l:]+alwaysNotIn
ret.append([current, currentNonFields])
return ret
def __repr__(self):
return "InnerTable "+str(self.rows)+"*"+str(self.cols)
def __str__(self):
rs=""
for ri in self["rows"][1:]:
rs+=str(ri[1:])+"\n "
return rs
def toJSON(self):
return jsonpickle.encode(self)
助手主要实现了 flatten-Method 和一个方法,它可以让我检查列表中的每个元素是否都属于某种类型:
from typing import Iterable
class Helper:
@staticmethod
def flatten(items, useValues=True):
"""Yield items from any nested iterable; see Reference."""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
for sub_x in Helper.flatten(x.values() if isinstance(x, dict) and useValues else x):
yield sub_x
else:
yield x
@staticmethod
def lio(cl, *inst):
inst=list(Helper.flatten(inst))
return all(map(lambda i:isinstance(i, cl), inst))
RCEnum 是惊喜,惊喜一个简单的枚举:
from enum import Enum
class RCEnum(Enum):
R="rows"
r="row"
C="cols"
c="col"
但现在到了重要的部分:
it=InnerTable(1, 4)
it2=jsonpickle.decode(it.toJSON())
由于某种原因 it2 不是 InnerTable 而是一个 list_iterator 对象,为什么?我能做些什么来纠正这个问题?(请注意,出于时间原因,从 InnerTable 中删除可迭代函数对我来说是非常不愉快的,因为我认为这两个函数不应该一起使用。)