我正在一个较大的python模块中工作,可以保存包含类似dict的类实例的程序集的“项目”,但是为了保存类的属性,必须将它们存储在该类的特定字典中。通过将属性写为属性,可以将其作为简单属性(self.x
而不是self.properties['x']
)进行访问。但是我最多只能处理9件事,并且给它们分别一个getter,setter和Deleter似乎是对空间的浪费,特别是因为它们都很琐碎。有更好的方法吗?
太长:
class MyClass(dict):
@property
def variable1(self):
return self.properties.get('variable1', None)
@variable1.setter
def variable1(self, value):
self.properties['variable1'] = value
@variable1.deleter
def variable1(self):
self.properties['variable1'] = None
# ... same for variables 2 - 8, so boring
@property
def variable9(self):
return self.properties.get('variable9', None)
@variable9.setter
def variable9(self, value):
self.properties['variable9'] = value
@variable9.deleter
def variable9(self):
self.properties['variable9'] = None
def __init__(self, variable1='default1', variable9='default9'):
self.properties = dict(variable1=variable1, variable9=variable9)
dict.__init__(self)
如何遍历属性声明,这样会更短?
奖金:如果我循环执行,是否有必要在某些变量中包括次要自定义项(可能在字典中声明要列出的内容作为键,而值是次要自定义项的说明) ?
上面示例的测试/用法:
from var_test import MyClass # If you saved it in var_test.py
a = MyClass(variable1=1234)
b = MyClass(variable1='wheee')
assert a.variable1 is not b.variable1
assert a.properties['variable1'] == a.variable1
assert a.variable1 == 1234
答案 0 :(得分:2)
是的,您可以动态创建属性对象,并将其添加到类中:
def gen_property(name):
def getter(self):
return self.properties.get(name, None)
def setter(self, value):
self.properties[name] = value
def deleter(self):
self.properties[name] = None
return property(getter, setter, deleter)
class MyClass(dict):
def __init__(self, variable1='default1', variable9='default9'):
self.properties = dict(variable1=variable1, variable9=variable9)
dict.__init__(self)
for number in range(1, 10):
name = 'variable{}'.format(number)
setattr(MyClass, name, gen_property(name))
但是,使用attribute access customisation hooks并将属性名称代理到self.properties
字典中可能更清洁:
class MyClass(dict):
def __init__(self, variable1='default1', variable9='default9'):
self.properties = dict(variable1=variable1, variable9=variable9)
dict.__init__(self)
def __getattr__(self, name):
if name.startswith('variable') and name[8:].isdigit():
return self.properties.get(name, None)
raise AttributeError(name)
def __setattr__(self, name, value):
if name.startswith('variable') and name[8:].isdigit():
self.properties[name] = value
return
super().__setattr__(name, value)
def __delattr__(self, name):
if name.startswith('variable') and name[8:].isdigit():
self.properties[name] = None
return
super().__delattr__(name)
答案 1 :(得分:0)
我能做的最好的事情是循环调用trafficPolicy.loadBalancer.consistentHash.[httpHeaderName|httpCookie]
来分配属性生成函数的结果。它比问题陈述中的内容短,但我觉得必须有更好的方法:
exec
这通过了测试:
import copy
class MyClass2(dict):
properties = {} # Temporary declaration of properties during startup
save_attrs = ['variable{}'.format(i) for i in range(1, 10)]
@staticmethod
def _make_property(props, name, init_value=None, doc=None):
"""Creates a property which can be assigned to a variable, with getter, setter, and deleter methods"""
props[name] = init_value
def getter1(self):
return self.properties.get(name, None)
def setter1(self, value):
self.properties[name] = value
def deleter1(self):
self.properties[name] = None
getter1.__name__ = name
setter1.__name__ = name
deleter1.__name__ = name
return property(getter1, setter1, deleter1, doc)
for attr in save_attrs:
exec("{attr:} = _make_property.__func__(properties, '{attr:}')".format(attr=attr))
def __init__(self, **kw):
# Instance-specific reassignment of properties, so instances won't share values
self.properties = copy.deepcopy(self.properties)
for attr in self.save_attrs:
kw_attr = kw.pop(attr, None)
if kw_attr is not None:
self.properties[attr] = kw_attr
dict.__init__(self)