面试题答案
一键面试设计思路
- 序列化:
- 对于常见的数据类型(字符串、数字、列表、字典),采用递归的方式进行处理。
- 为了处理循环引用,使用一个集合来记录已经处理过的对象。当遇到一个对象时,先检查该对象是否在集合中,如果在,表示存在循环引用,需要特殊处理(比如用一个占位符表示)。
- 字符串直接转换为自身,数字同理。
- 列表则遍历每个元素,递归调用序列化函数处理每个元素并组成新的列表。
- 字典同样递归处理每个键值对,将键和值都进行序列化。
- 反序列化:
- 与序列化相对应,同样采用递归方式。
- 对于之前处理循环引用的占位符,在反序列化时需要恢复正确的引用关系。这里可以使用一个字典来记录已经反序列化的对象,当遇到占位符时,从该字典中获取正确的对象引用。
关键代码实现
# 用于标记循环引用的占位符
CYCLE_PLACEHOLDER = '__CYCLE__'
def custom_serialize(obj, memo=None):
if memo is None:
memo = set()
if id(obj) in memo:
return CYCLE_PLACEHOLDER
memo.add(id(obj))
if isinstance(obj, str):
return obj
elif isinstance(obj, (int, float)):
return obj
elif isinstance(obj, list):
return [custom_serialize(item, memo) for item in obj]
elif isinstance(obj, dict):
serialized_dict = {}
for key, value in obj.items():
serialized_key = custom_serialize(key, memo)
serialized_value = custom_serialize(value, memo)
serialized_dict[serialized_key] = serialized_value
return serialized_dict
else:
raise TypeError(f"Unsupported type {type(obj)}")
def custom_deserialize(obj, memo=None):
if memo is None:
memo = {}
if isinstance(obj, str) and obj == CYCLE_PLACEHOLDER:
return next(iter(memo.values()))
elif isinstance(obj, list):
return [custom_deserialize(item, memo) for item in obj]
elif isinstance(obj, dict):
deserialized_dict = {}
for key, value in obj.items():
deserialized_key = custom_deserialize(key, memo)
deserialized_value = custom_deserialize(value, memo)
deserialized_dict[deserialized_key] = deserialized_value
if deserialized_key == CYCLE_PLACEHOLDER:
memo[CYCLE_PLACEHOLDER] = deserialized_dict
return deserialized_dict
else:
return obj
你可以使用以下方式测试代码:
# 测试示例
test_dict = {'a': 1, 'b': [2, 3], 'c': {'d': 4}}
serialized = custom_serialize(test_dict)
print(serialized)
deserialized = custom_deserialize(serialized)
print(deserialized)
# 测试循环引用
circular_dict = {}
circular_dict['self_ref'] = circular_dict
serialized_circular = custom_serialize(circular_dict)
print(serialized_circular)
deserialized_circular = custom_deserialize(serialized_circular)
print(deserialized_circular)