Python 基于uuu setattr和u getattr的动态配置对象__
我试图创建动态对象来验证我在飞行中的配置,并将结果显示为对象。我试图通过创建这样的类来实现这一点:Python 基于uuu setattr和u getattr的动态配置对象__,python,Python,我试图创建动态对象来验证我在飞行中的配置,并将结果显示为对象。我试图通过创建这样的类来实现这一点: class SubConfig(object): def __init__(self, config, key_types): self.__config = config self.__values = {} self.__key_types = key_types def __getattr__(self, item):
class SubConfig(object):
def __init__(self, config, key_types):
self.__config = config
self.__values = {}
self.__key_types = key_types
def __getattr__(self, item):
if item in self.__key_types:
return self.__values[item] or None
else:
raise ValueError("No such item to get from config")
def __setattr__(self, item, value):
if self.__config._blocked:
raise ValueError("Can't change values after service has started")
if item in self.__key_types:
if type(value) in self.__key_types[item]:
self.__values[item] = value
else:
raise ValueError("Can't assing value in different type then declared!")
else:
raise ValueError("No such item to set in config")
SubcoFig是配置文件中节的包装器。Config具有在程序启动后更改值的开关终止可能性(您只能在初始化时更改值)
问题是当我在getattr中设置它在无穷循环中得到的任何值时。正如我读到的\uuuuu getattr\uuuuu
不应该这样做(首先获取现有attr,然后调用\uuuuu getattr\uuuuu
)。我将我的代码与可用的示例进行了比较,但我什么也找不到
我注意到所有问题都是由我的构造函数生成的。问题是,初始化对象时,构造函数调用
\uuuu setattr\uuuu
,然后调用\uu getattr\uuuu
,因为私有成员尚未初始化
我可以想出两种方法来解决这个问题:
一种选择是调用对象。\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。您还可以直接在self.\uu dict\uu
中设置值。这里的一个问题是,由于使用了双下划线,因此必须手动更改属性名称(因此“\uuuu config”
变成”\uu config”
):
另一种方法是让\uuuuu setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuu>检测并传递对以\uuuuuuu
开头的属性名称的访问,即
if item.startswith('_')
return super(SubConfig, self).__setattr__(item, value)
如果有人有很好的理由访问对象的内部,你就没有理由试图阻止他们。问题是初始化对象时的构造函数调用了,然后调用\uuuu getattr\uuuu
,因为\uuuu
私有成员尚未初始化
我可以想出两种方法来解决这个问题:
一种选择是调用对象。\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。您还可以直接在self.\uu dict\uu
中设置值。这里的一个问题是,由于使用了双下划线,因此必须手动更改属性名称(因此“\uuuu config”
变成”\uu config”
):
另一种方法是让\uuuuu setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuu>检测并传递对以\uuuuuuu
开头的属性名称的访问,即
if item.startswith('_')
return super(SubConfig, self).__setattr__(item, value)
如果有人有很好的理由访问你的对象的内部,那么这就更像是python,您没有理由试图阻止它们。Cf ecatmur对根本原因的回答-请记住,\uuuuuSetAttr\uuuuuuuuuuu
与\uuuGetAttr\uuuuuuuuuuuuuuuuuuuuuu\uuuuuuuuuuuuuuu>并不对称-每次尝试绑定对象属性时都会无条件地调用它。重写\uuuu setattr\uuuuuu
是一件棘手的事情,如果您不清楚其利弊,就不应该这样做
现在为您的用例提供一个简单实用的解决方案:重写初始值设定项以避免触发setattr调用:
class SubConfig(object):
def __init__(self, config, key_types):
self.__dict__.update(
_SubConfig__config=config,
_SubConfig__values={},
_SubConfig__key_types=key_types
)
请注意,我重命名了属性,以模拟使用双前导下划线命名方案时发生的名称损坏 Cf ecatmur对根本原因的回答-请记住,\uuuuu setattr\uuuuuuu
与\uuuu getattr\uuuuuuu
不是对称的-它是在每次尝试绑定对象属性时无条件调用的。重写\uuuu setattr\uuuuuu
是一件棘手的事情,如果您不清楚其利弊,就不应该这样做
现在为您的用例提供一个简单实用的解决方案:重写初始值设定项以避免触发setattr调用:
class SubConfig(object):
def __init__(self, config, key_types):
self.__dict__.update(
_SubConfig__config=config,
_SubConfig__values={},
_SubConfig__key_types=key_types
)
请注意,我重命名了属性,以模拟使用双前导下划线命名方案时发生的名称损坏 感谢您的建议,解决方案是将所有设置器的结构更改为:super(subcontfig,self)。\uuuuuuuu setattr\uuuuuuuu(“\uuuu config”,config)
。这样,我覆盖的\uuuuu setattr\uuuuu
就不起作用了。此外,我还可以在setter中添加一些if来传递以双下划线开头的值。setattr
不起作用,因为它总是遇到\uuuuuuuuuuuuuuuuuuuu
机器。请参阅上面添加的代码。感谢您的建议,解决方案是将所有设置器的结构更改为:super(subcontfig,self)。\uuuuuuuu setattr\uuuuuuuuu(“\uuuuu config',config)
。这样,我覆盖的\uuuuu setattr\uuuuu
就不起作用了。此外,我还可以在setter中添加一些if来传递以双下划线开头的值。setattr
不起作用,因为它总是遇到\uuuuuuuuuuuuuuuuuuuu
机器。请参阅上面添加的代码。