演员时自定义Dict放下键(Custom Dict Dropping Keys When Cast)

编程入门 行业动态 更新时间:2024-10-28 13:23:43
演员时自定义Dict放下键(Custom Dict Dropping Keys When Cast)

我有一个继承自dict的自定义类(如下所示),当我将对象转换为dict时,它会删除名为'type'的键。 有什么理由发生这种情况吗?

我期待以下结果:

dm =参数()

打印(字典(DM))

{'tags':'bar','type':'Item','title':'foo'}

我最终获得的是:

{'tags':'bar','title':'foo'}

self._map包含'type'键/值对,所以我不知道可能是什么问题。 有没有人有什么建议?

class ItemParameter(dict): """ """ def __init__(self, title, tags): super(ItemParameter, self).__init__(title=title, tags=tags) self._map = {} self._allowed_keys = {'type':'type', 'title': 'title', 'tags':'tags', 'thumbnail': 'thumbnail', 'thumbnailurl': 'thumbnailurl', 'metadata': 'metadata', 'type_keywords' : 'typeKeywords', 'description': 'description', 'snippet' : 'snippet'} self['type'] = "Item" self['title'] = title self['tags'] = tags def __iter__(self): for k, v in self.items(): yield k, v def __setitem__(self, k, v): if k in self._allowed_keys: self._map[self._allowed_keys[k]] = v def __getitem__(self, k): if k in self._map: return self._map[k] elif k in self._allowed_keys and \ self._allowed_keys[k] in self._map: return self._map[self._allowed_keys[k]] def __setattr__(self, k, v): if k in {'_map','_dynamic', '_allowed_keys', '_ipython_canary_method_should_not_exist_'}: super(ItemParameter, self).__setattr__(k,v) else: if k in self._allowed_keys.keys(): self._map[self._allowed_keys[k]] = v def __getattr__(self, k): if k == {'_map','_dynamic', '_allowed_keys', '_ipython_canary_method_should_not_exist_'}: super(ItemParameter, self).__getattr__(k) else: if k in self._allowed_keys.keys() and \ self._allowed_keys[k] in self._map: return self._map[self._allowed_keys[k]] def __delattr__(self, key): return self._map.__delitem__(key) def __contains__(self, k): return self._map.__contains__(k) def __repr__(self): return str(self._map) def __str__(self): return self.__repr__() def items(self): return self._map.items()

I have a custom class that inherit from dict (shown below) and when I cast the object to a dict, it drops the key called 'type'. Is there any reason why this is happening?

I expect the following results:

dm = Parameter()

print(dict(dm))

{'tags': 'bar', 'type': 'Item', 'title': 'foo'}

What I end up getting is:

{'tags': 'bar', 'title': 'foo'}

The self._map contains the 'type' key/value pair, so I don't know what could be the problem. Does anyone have any suggestions?

class ItemParameter(dict): """ """ def __init__(self, title, tags): super(ItemParameter, self).__init__(title=title, tags=tags) self._map = {} self._allowed_keys = {'type':'type', 'title': 'title', 'tags':'tags', 'thumbnail': 'thumbnail', 'thumbnailurl': 'thumbnailurl', 'metadata': 'metadata', 'type_keywords' : 'typeKeywords', 'description': 'description', 'snippet' : 'snippet'} self['type'] = "Item" self['title'] = title self['tags'] = tags def __iter__(self): for k, v in self.items(): yield k, v def __setitem__(self, k, v): if k in self._allowed_keys: self._map[self._allowed_keys[k]] = v def __getitem__(self, k): if k in self._map: return self._map[k] elif k in self._allowed_keys and \ self._allowed_keys[k] in self._map: return self._map[self._allowed_keys[k]] def __setattr__(self, k, v): if k in {'_map','_dynamic', '_allowed_keys', '_ipython_canary_method_should_not_exist_'}: super(ItemParameter, self).__setattr__(k,v) else: if k in self._allowed_keys.keys(): self._map[self._allowed_keys[k]] = v def __getattr__(self, k): if k == {'_map','_dynamic', '_allowed_keys', '_ipython_canary_method_should_not_exist_'}: super(ItemParameter, self).__getattr__(k) else: if k in self._allowed_keys.keys() and \ self._allowed_keys[k] in self._map: return self._map[self._allowed_keys[k]] def __delattr__(self, key): return self._map.__delitem__(key) def __contains__(self, k): return self._map.__contains__(k) def __repr__(self): return str(self._map) def __str__(self): return self.__repr__() def items(self): return self._map.items()

最满意答案

正如ShadowRanger所提到的那样,在._map属性中复制dict数据是一种糟糕的设计,而且通常情况下,如果不对内置类型进行子类化则要好得多。

我已经将你的代码减少到了重现这个“bug”的最低限度,我仍然不能完全确定它为什么会像它一样,但是我们可以通过确保__setitem__将新项添加到self以及self._map 。 例如:

def __setitem__(self, k, v): if k in self._allowed_keys: k = self._allowed_keys[k] self._map[k] = v super(ItemParameter, self).__setitem__(k, v)

这是你班级的新版本,可以完成我认为你想要的。 它使用Python(3)版本的super() ,其形式为零。

class ItemParameter(dict): allowed = { 'type':'type', 'title': 'title', 'tags':'tags', 'thumbnail': 'thumbnail', 'thumbnailurl': 'thumbnailurl', 'metadata': 'metadata', 'type_keywords' : 'typeKeywords', 'description': 'description', 'snippet' : 'snippet', } def __init__(self, title, tags): super().__init__(title=title, tags=tags) self['type'] = "Item" def __setitem__(self, k, v): if k in ItemParameter.allowed: k = ItemParameter.allowed[k] super().__setitem__(k, v) def update(self, other): for k, v in other.items(): self[k] = v # test p = ItemParameter(title='foo', tags='bar') for t in p: print(t) print(p) print(p.copy()) print(dict(p)) p['type_keywords'] = 'some thing' print(p) p['bad'] = 'other thing' print(p) p.update({'a':1, 'b':2, 'metadata': 3}) print(p)

产量

title tags type {'title': 'foo', 'tags': 'bar', 'type': 'Item'} {'title': 'foo', 'tags': 'bar', 'type': 'Item'} {'title': 'foo', 'tags': 'bar', 'type': 'Item'} {'title': 'foo', 'tags': 'bar', 'type': 'Item', 'typeKeywords': 'some thing'} {'title': 'foo', 'tags': 'bar', 'type': 'Item', 'typeKeywords': 'some thing'} {'title': 'foo', 'tags': 'bar', 'type': 'Item', 'typeKeywords': 'some thing', 'metadata': 3}

As ShadowRanger mentions, it's bad design to duplicate the dict data in the ._map attribute, and you're generally much better off not subclassing the built-in types.

I've reduced your code down to the bare minimum that reproduces this "bug", and I'm still not totally sure why it behaves exactly like it does, but we can fix the bug by making sure that __setitem__ adds the new item to self as well as to self._map. For example:

def __setitem__(self, k, v): if k in self._allowed_keys: k = self._allowed_keys[k] self._map[k] = v super(ItemParameter, self).__setitem__(k, v)

Here's a new version of your class that does what I think you want. It uses the Python 3 version of super() which has a zero args form.

class ItemParameter(dict): allowed = { 'type':'type', 'title': 'title', 'tags':'tags', 'thumbnail': 'thumbnail', 'thumbnailurl': 'thumbnailurl', 'metadata': 'metadata', 'type_keywords' : 'typeKeywords', 'description': 'description', 'snippet' : 'snippet', } def __init__(self, title, tags): super().__init__(title=title, tags=tags) self['type'] = "Item" def __setitem__(self, k, v): if k in ItemParameter.allowed: k = ItemParameter.allowed[k] super().__setitem__(k, v) def update(self, other): for k, v in other.items(): self[k] = v # test p = ItemParameter(title='foo', tags='bar') for t in p: print(t) print(p) print(p.copy()) print(dict(p)) p['type_keywords'] = 'some thing' print(p) p['bad'] = 'other thing' print(p) p.update({'a':1, 'b':2, 'metadata': 3}) print(p)

output

title tags type {'title': 'foo', 'tags': 'bar', 'type': 'Item'} {'title': 'foo', 'tags': 'bar', 'type': 'Item'} {'title': 'foo', 'tags': 'bar', 'type': 'Item'} {'title': 'foo', 'tags': 'bar', 'type': 'Item', 'typeKeywords': 'some thing'} {'title': 'foo', 'tags': 'bar', 'type': 'Item', 'typeKeywords': 'some thing'} {'title': 'foo', 'tags': 'bar', 'type': 'Item', 'typeKeywords': 'some thing', 'metadata': 3}

更多推荐

本文发布于:2023-08-04 17:29:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1420947.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自定义   演员   Dict   Custom   Keys

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!