Python Protocol Buffers中是否有Map Fields的复制构造函数?

6
Python生成的代码解释了protobuf中大多数使用场景,包括在Python中使用映射字段,但没有说明如何将一个映射复制到另一个映射。
给定一个简单的映射:
message Src {
    map<string, string> properties = 1;
    ...
}

message Dst {
    map<string, string> properties = 1;
    ...
}

你无法给嵌入式消息字段赋值,所以无法进行如下操作:

# Will not work.
dst = Dst()
dst.properties = src.properties

因为 map 不是消息本身,而是消息内的一个字段,所以也没有 CopyFrom 的实现。

# Will not work.
dst = Dst()
dst.properties.CopyFrom(src.properties)

我只想获取地图,所以无法复制整个消息。

# Copies unwanted fields!
dst = Dst()
dst.CopyFrom(src)

我希望不必逐个迭代所有键并逐个分配!
# Iterate over map keys
for key in src.properties:
    dst.properties[key] = src.properties[key]

1
你尝试过MergeFrom吗?我很好奇想知道它是否有效。 - Anagha
2个回答

4

在Python protobuf生成的代码中,映射字段(Map fields)与Python字典几乎相同,因此您可以使用.update()方法进行复制:

dst.properties.update(src.properties)

1
这个实际上不起作用:ValueError:不允许直接分配子消息 - yuzhoul
这个解决方案对我有用,我的映射是<string,int32>。也许你的类型存在其他问题? - Ertai87

3
如果地图的值是简单类型,dst.properties.update(src.properties)应该可以工作。但是,如果您有一个带有消息类型值的地图,例如:
message Prop {
  optional string value = 1;
  optional bool is_public = 2;
}

message Src {
    map<string, Prop> properties = 1;
    ...
}

message Dst {
    map<string, Prop> properties = 1;
    ...
}

如果使用.update(或任何类型的直接赋值),将会抛出异常:

ValueError: Direct assignment of submessage not allowed

相反,你需要做类似这样的事情:

for k, v in src.properties.items():
  dst.properties[k].CopyFrom(v)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接