昨天的3分钟我说了3种用Python做JSON序列化的方法。
最后提到了一种不仅自己可以直接被JSON化,还可以在list, map或者其他自己不可控的框架中被序列化的方法。就是下面这种:
class Food(dict):
def __init__(self, name, origin, calories, price):
dict.__init__(self, name=name, origin=origin, calories=calories, price=price)
self.name = name
self.origin = origin
:.calories = calories
self.price = price
def to_json(self):
return self.__dict__
print('...此处省略2500行推荐算法代码...')
food1 = Food('胡辣汤', '山东', 25, 2)
food2 = Food('油条', '山东', 88, 1)
food3 = Food('豆腐脑', '山东', 35, 2.5)
food4 = Food('焖饼', '山东', 65, 10)
recommend = [food1, food2, food3, food4]
import json
recommend_json = json.dumps(recommend, indent=4, ensure_ascii=False)
print(recommend_json)
这种方法看似比较理想,但是有位**@江河**提出了这个方案的一个致命缺陷!
它的缺陷在于:
看个例子:
food1 = Food('胡辣汤', '山东', 25, 2)
food1.price = 999
print(json.dumps(food1, indent=4, ensure_ascii=False))
food1的价格是2,后来被改成了999,但是dumps出来的结果还是2:
{
"name": "胡辣汤",
"origin": "山东",
"calories": 25,
"price": 2
}
也就是说,这种方法只能用于值一旦初始化就不会改变的对象。
无解了!
完了,无解了。
要实现理想的目标,似乎是无解了!
我研究过中文世界和英文世界里的各种相关讨论,至少我没有找到一种理想的解决方法。
山不过来,我就过去
既然无法让对象直接在列表中序列化,为了做序列化,就只好迁就json库,把对象都转成字典再传给它。
这里要用到一个函数叫做:vars(),它可以以字典的形式返回当前对象中所有的属性。
看代码:
class Food(dict):
def __init__(self, name, origin, calories, price):
dict.__init__(self, name=name, origin=origin, calories=calories, price=price)
self.name = name
self.origin = origin
self.calories = calories
self.price = price
def to_json(self):
return self.__dict__
food1 = Food('胡辣汤', '山东', 25, 2)
food2 = Food('油条', '山东', 88, 1)
food3 = Food('豆腐脑', '山东', 35, 2.5)
food4 = Food('焖饼', '山东', 65, 10)
food1.price = 999
recommend = [vars(food1), vars(food2), vars(food3), vars(food4)]
import json
recommend_json = json.dumps(recommend, indent=4, ensure_ascii=False)
print(recommend_json)
这里的要点在于,构建recommend字典的时候传入的是vars(foodx)而不是直接传入对象,这就是:山不过来,我就过去。
看看结果,新的价格999可以被成功序列化:
[
{
"name": "胡辣汤",
"origin": "山东",
"calories": 25,
"price": 999
},
{
"name": "油条",
"origin": "山东",
"calories": 88,
"price": 1
},
{
"name": "豆腐脑",
"origin": "山东",
"calories": 35,
"price": 2.5
},
{
"name": "焖饼",
"origin": "山东",
"calories": 65,
"price": 10
}
]
就像人生一样,很多东西看似是无解的,其实是因为我们陷入了思维定式,打破思维定式,办法总是有的。
再分享一个上周发生在我身边的故事吧:
这也是一个打破思维定式的例子,说了要3月底上线,为了实现这个目标,我们可以调整其他变量,比如增加资源,减少范围,当然也包括加班加点。
今天的思维有点扩散,上面的例子可以引出一点项目管理的知识点:
- 项目管理的3个要素:范围,资源和时间。这是书本上的,大路边的知识,下面这个点我多年的心得体会。
- 当3要素出现冲突的时候,我们要尽量保持时间不变,调整资源和范围。因为按时上线,完成的少一点,要好过没有完成,也好过过多的增加投入。