为何在Boto3 DynamoDB序列化代码中使用三元运算符?
关于DynamoDB序列化代码中三元运算符的疑问
我看到一段将常规JSON对象序列化为DynamoDB JSON格式的代码,疑问在于:代码中的serialize函数使用了三元运算符vars(item) if hasattr(item, '__dict__') else item,但我在Lambda环境测试发现,直接将Python对象传入serialize方法即可正常运行,为何还要使用该三元运算符?是否是开发者不确定__dict__属性是否存在?
代码示例
from boto3.dynamodb.types import TypeSerializer, TypeDeserializer import json serializer = TypeSerializer() deserializer = TypeDeserializer() # for building a DynamoDB JSON from a Python object def serialize(item): serialized_item = serializer.serialize(vars(item) if hasattr(item, '__dict__') else item) return item if 'M' not in serialized_item else serialized_item['M'] # for building a plain JSON from a DynamoDB JSON def deserialize(dynamodb_json_string): return deserializer.deserialize({'M': dynamodb_json_string}) class MyItem: def __init__(self, some_string_value=None, some_numeric_value=None): self.my_key = some_string_value self.my_other_key = some_numeric_value def __str__(self): return json.dumps(self, default=lambda x: x.__dict__) if __name__ == '__main__': my_classy_item = MyItem("my_string_value", 5) my_string_item = json.loads('{"my_key": "my_string_value", "my_other_key" : 5}') print(serialize(my_classy_item)) print(serialize(my_string_item))
解答
这个三元运算符的存在主要是为了兼容自定义类实例和原生Python数据类型两种输入场景,同时避免潜在报错,具体原因如下:
- 自定义类实例无法直接被序列化:
boto3的TypeSerializer只支持序列化Python原生数据类型(如dict、str、int、list)和DynamoDB专属类型,没法直接处理自定义类的实例。比如直接把MyItem对象传给serializer.serialize(),会抛出TypeError。而vars(item)(等价于item.__dict__)能把自定义实例的属性转换成TypeSerializer能处理的dict格式。 - 兼容多种输入类型:这段代码的
serialize函数需要同时处理两种输入——自定义类实例(需要转成dict)和原生数据类型(比如代码里的my_string_item这种dict,或者直接传入的字符串、数字等)。三元运算符可以自动判断输入类型,对自定义实例转dict,对原生类型直接传入,保证函数的通用性。 - 避免
__dict__不存在的报错:不是所有Python类都有__dict__属性——比如用__slots__定义的类,会禁止自动生成__dict__来节省内存。hasattr(item, '__dict__')就是为了判断这种情况,避免直接调用vars(item)时抛出AttributeError。
你测试时直接传Python对象能运行,大概率是因为测试的自定义类刚好带有__dict__属性,或者误将已经转成dict的对象当成了原始实例。如果换成用__slots__定义的类,直接传实例给serializer.serialize()就会报错,这时候三元运算符的作用就体现出来了。
内容的提问来源于stack exchange,提问作者adethefirst
相关产品推荐
相关产品推荐

