使用配置文件中的属性创建 class
Create class with properties from config file
我正在尝试从配置文件动态创建 Python class(为简单起见,我在示例中使用字典)。我创建的属性我想设置为属性,因为我有验证功能,我想在设置属性时 运行。
我有一个代码可以正常工作,但它有一些意想不到的结果。
def func(x):
""" Example validation function. """
if x < 0:
raise ValueError
return
config = {
"x": {
"type": int,
"default": 0,
"validate": func
},
"y": {
"type": int,
"default": 10,
"validate": func
},
"z": {
"type": str,
"default": "bar",
"validate": None
}
}
def get_property(prop, validate):
key = f"_{prop}"
def get_(self):
return exec(f"self.{key}")
def set_(self, value):
if validate is not None:
validate(value)
exec(f"self.{key} = value")
def del_(self):
exec(f"del self.{key}")
return property(get_, set_, del_)
def get_Foo(**kwargs):
class Foo:
def __init__(self, **_kwargs):
for k_, v_ in _kwargs.items():
setattr(self, "_" + k_, None)
if v_["type"] == str:
exec(f"self.{k_} = '{v_['default']}'")
else:
exec(f"self.{k_} = {v_['default']}")
# Add properties to Foo class
for k, v in kwargs.items():
prop_ = get_property(k, v["validate"])
setattr(Foo, k, prop_)
# Create Foo class and set defaults
return Foo(**kwargs)
foo = get_Foo(**config)
现在测试时 'setter' 似乎在工作,但 'getter' 不工作,'deleter' 部分工作。
print(foo.x) # prints None
print(foo._x) # prints 0
foo.x = 10
print(foo.x) # prints None (getter not working)
print(foo._x) # prints 10 (setter works)
foo.x = -1 # raises error (validator in setter works)
del foo.x
print(foo.x) # AttributeError: 'Foo' object has no attribute '_x' (del sort-of works?)
谁能解释一下结果?
感谢juanpa.arrivillaga;切换到 getattr、setattr、delattr 解决了这个问题。
解决方法如下:
def get_property(prop, validate):
key = f"_{prop}"
def get_(self):
return getattr(self, key)
def set_(self, value):
if validate is not None:
validate(value)
setattr(self, key, value)
def del_(self):
delattr(self, key)
return property(get_, set_, del_)
def get_Foo(**kwargs):
class Foo:
def __init__(self, **_kwargs):
for k_, v_ in _kwargs.items():
setattr(self, "_" + k_, None)
setattr(self, k_, v_['default'])
# Add properties to Foo class
for k, v in kwargs.items():
prop_ = get_property(k, v["validate"])
setattr(Foo, k, prop_)
# Create Foo class and set defaults
return Foo(**kwargs)
foo = get_Foo(**config)
我正在尝试从配置文件动态创建 Python class(为简单起见,我在示例中使用字典)。我创建的属性我想设置为属性,因为我有验证功能,我想在设置属性时 运行。
我有一个代码可以正常工作,但它有一些意想不到的结果。
def func(x):
""" Example validation function. """
if x < 0:
raise ValueError
return
config = {
"x": {
"type": int,
"default": 0,
"validate": func
},
"y": {
"type": int,
"default": 10,
"validate": func
},
"z": {
"type": str,
"default": "bar",
"validate": None
}
}
def get_property(prop, validate):
key = f"_{prop}"
def get_(self):
return exec(f"self.{key}")
def set_(self, value):
if validate is not None:
validate(value)
exec(f"self.{key} = value")
def del_(self):
exec(f"del self.{key}")
return property(get_, set_, del_)
def get_Foo(**kwargs):
class Foo:
def __init__(self, **_kwargs):
for k_, v_ in _kwargs.items():
setattr(self, "_" + k_, None)
if v_["type"] == str:
exec(f"self.{k_} = '{v_['default']}'")
else:
exec(f"self.{k_} = {v_['default']}")
# Add properties to Foo class
for k, v in kwargs.items():
prop_ = get_property(k, v["validate"])
setattr(Foo, k, prop_)
# Create Foo class and set defaults
return Foo(**kwargs)
foo = get_Foo(**config)
现在测试时 'setter' 似乎在工作,但 'getter' 不工作,'deleter' 部分工作。
print(foo.x) # prints None
print(foo._x) # prints 0
foo.x = 10
print(foo.x) # prints None (getter not working)
print(foo._x) # prints 10 (setter works)
foo.x = -1 # raises error (validator in setter works)
del foo.x
print(foo.x) # AttributeError: 'Foo' object has no attribute '_x' (del sort-of works?)
谁能解释一下结果?
感谢juanpa.arrivillaga;切换到 getattr、setattr、delattr 解决了这个问题。
解决方法如下:
def get_property(prop, validate):
key = f"_{prop}"
def get_(self):
return getattr(self, key)
def set_(self, value):
if validate is not None:
validate(value)
setattr(self, key, value)
def del_(self):
delattr(self, key)
return property(get_, set_, del_)
def get_Foo(**kwargs):
class Foo:
def __init__(self, **_kwargs):
for k_, v_ in _kwargs.items():
setattr(self, "_" + k_, None)
setattr(self, k_, v_['default'])
# Add properties to Foo class
for k, v in kwargs.items():
prop_ = get_property(k, v["validate"])
setattr(Foo, k, prop_)
# Create Foo class and set defaults
return Foo(**kwargs)
foo = get_Foo(**config)