问题Adding an attribute to a python dictionary from the standard library显示了如何将属性添加到内置数据类型。但有没有办法在一个步骤中向变量添加一个属性,以便它可以在函数调用中使用,相当于以下内容:
>>> class Adict(dict):
pass
>>> def myfunc(x):
print(x, x.my_attr)
>>> v = {'a':'cat'}
>>> var = Adict(v)
>>> var.my_attr = 'whatever'
>>> myfunc(var)
{'a': 'cat'} whatever
我想将最后3行减少到一行,例如:
>>> myfunc(Adict(v, my_attr='whatever'))
传递带有两个项目的字典(' a'和#39; my_attr')并且没有属性,或
>>> myfunc(Adict(v).my_attr='whatever')
被解析为关键字参数而不是属性设置。有没有办法在一个步骤中设置值和属性?
--------编辑----------
要回答Sven的问题,我正在努力扩展优秀的genson JSON模式处理器,其中包括以下代码:
# parse properties and add them individually
for prop, val in schema.items():
if prop == 'type':
self._add_type(val)
elif prop == 'required':
self._add_required(val)
elif prop in ['properties', 'patternProperties']:
v = Adict(val)
v._ptype = prop
self._add_properties(v, 'add_schema')
elif prop == 'items':
self._add_items(val, 'add_schema')
elif prop not in self._other:
self._other[prop] = val
除了能够使用属性标记它之外,我不需要使用自定义dict的任何特殊内容,并且能够在{{1下清理我那些丑陋的3行代码会很好所以它在视觉上匹配其他情况:-)。我可能会做的是将该标记单独传递给properties
函数。
答案 0 :(得分:1)
您可以覆盖Adict
的构造函数以接受关键字参数并根据它设置属性:
class Adict(dict):
def __init__(*args, my_attr=None, **kwargs):
self = args[0]
self.my_attr = my_attr
dict.__init__(*args, **kwargs)
这为您提供了一种以某种奇怪的方式更改的字典,因为my_attr
关键字参数的行为与所有其他关键字参数的行为不同。 (您也可以选择不将kwargs
传递给dict
构造函数。)
答案 1 :(得分:1)
您可以介绍所谓的构建器(或类工厂模式),它获取所有必需的参数并返回结果对象。这是你想要的吗?
class Adict(dict):
pass
def myfunc(x):
print(x, x.my_attr)
def my_builder(v, **kvargs):
obj = Adict(v)
obj.__dict__.update(kvargs) # internal dictionary with attributes
return obj # return the created object
# Your original code.
v = {'a':'cat'}
var = Adict(v)
var.my_attr = 'whatever'
myfunc(var)
print('------------')
v2 = {'d': 'dog'}
myfunc(my_builder(v2, my_attr='whatever_dog'))
print('------------')
myfunc(my_builder({'c': 'crocodile'}, my_attr='whatever_croc'))
这是完全按照你在三条线上所做的那样直截了当的方式。但是,建造者可能会更加智能。它可以测试参数的值和类型,并根据情况,可以创建,初始化和返回其他类型的对象作为结果。这就是类工厂模式的设计目标 - 为您工作的代理。 (这里的问题是你在执行obj
之后抛弃了myfunc()
,但你可能意味着要对对象做一些其他事情 - 将它传递到某处或其他任何地方。)