Python:如何禁用在属性字典中创建新键?
Posted
技术标签:
【中文标题】Python:如何禁用在属性字典中创建新键?【英文标题】:Python: how to disable creation of new keys in attribute dict? 【发布时间】:2020-01-20 10:05:14 【问题描述】:这里是一个简单的属性dict代码:
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
更多上下文: https://***.com/a/14620633/1179925
我可以像这样使用它:
d = AttrDict('a':1, 'b':2)
print(d)
我希望这成为可能:
d.b = 10
print(d)
但我希望这是不可能的:
d.c = 4
print(d)
是否有可能在创建新密钥时抛出错误?
【问题讨论】:
你为什么不创建一个包含字典的对象。这样就无法添加新属性,但可以更改现有属性。 Prevent creating new attributes outside __init__的可能重复 也看看这里:***.com/questions/39440190/… @Chognificent Class in python 不保证这一点。 【参考方案1】:你可以检查他们是否已经在那里
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dict__ = self
def __setattr__(self, key, value):
if key not in [*self.keys(), '__dict__']:
raise KeyError('No new keys allowed')
else:
super().__setattr__(key, value)
def __setitem__(self, key, value):
if key not in self:
raise KeyError('No new keys allowed')
else:
super().__setitem__(key, value)
首先,我认为这是一个坏主意,因为无法添加初始值,但从内置函数中它指出以下内容: dict(iterable) -> 新字典的初始化就像通过: d = 对于可迭代的 k,v: d[k] = v
因此,这确实允许您更改方法而不影响 Class 的初始化,因为它从 而不是从它自己的实例创建一个新方法。
尽管如此,他们将能够始终更改 __ dict __..
【讨论】:
你能详细说明为什么我们检查key
和'__dict__'
和__setattr__
吗?
为了让您实际使用 dict 值作为属性,需要 self.__dict__ = self 调用。如果 setattr 中不允许 dict,这将失败。也可以使用某种冻结开关。
freeze switch
是什么?
类跟踪它被“冻结”的位置,因此在初始化时它会首先设置一些值“冻结”从 False 到最后的 True,然后在特殊方法中检查是否设置或不设置值以检查键是否在字典中。因此允许您最初设置字典,但之后不能设置
这个答案好像用了这个方法***.com/a/58010685/1179925【参考方案2】:
您可以覆盖__setattr__
特殊方法。
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__setattr__('_initializing', True)
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
super(AttrDict, self).__setattr__('_initializing', False)
def __setattr__(self, x, value):
if x == '_initializing':
raise KeyError("You should not edit _initalizing")
if self._initializing or x in self.__dict__.keys():
super(AttrDict, self).__setattr__(x, value)
else:
raise KeyError("No new keys allowed!")
请注意,我需要添加一个属性_initializing
以让__setattr__
区分__init__
创建的属性和用户创建的属性。
由于python没有私有属性,用户可能仍然将_initializing
设置为True
,然后将他们的属性添加到AttrDict
实例中,所以我添加了进一步检查以确保他们没有尝试编辑_initializing
.
它仍然不是 100% 安全的,因为用户仍然可以使用 super()
将 _initializing
设置为 True。
【讨论】:
以上是关于Python:如何禁用在属性字典中创建新键?的主要内容,如果未能解决你的问题,请参考以下文章
如何在Python中创建一个递归函数来创建一个映射Odoo 8关系字段记录的字典?
如何使用 scala/python/spark 在 CSV 文件中创建新的时间戳(分钟)列
根据附加的字典列表在 df 中创建新列并遍历字典 Pandas 列表