【发布时间】:2015-05-09 12:37:41
【问题描述】:
我为配置选项创建了一个自定义描述符,可用于创建这样的类:
class Configuration(SomeSpecificBackend):
basedir = ConfigurationProperty('basedir', int)
logfile = ConfigurationProperty('logfile', Path)
真实的实例包含更多的属性。问题是我想要一个__init__,它允许我在构造时初始化我想要的任何属性,如下所示:
def __init__(self, basdir=None, logfile=None):
if basedir is not None:
self.basedir = basedir
if logfile is not None:
self.logfile = logfile
由于实际上有更多的属性,这变得难以维护,并且由于这里的模式非常规则,我想知道是否有一种方法可以自动提供此功能。
我的初稿是这门课:
class ConfigurationBase():
def __init__(self, **kwargs):
super().__init__()
for key, value in kwargs.items():
if hasattr(self, key): # don't create new attributes
setattr(self, key, value)
这是我想要的,但在某些情况下甚至更多,因为它还会初始化不是配置属性的属性,这可能会导致其他基类出现问题。我不知道如何解决这个问题。 type(getattr(self, key)) 不会产生 ConfigurationProperty,而是当前值的类型。
此外,它将所有kwargs 视为要初始化的配置属性。其中一些可能是其他基类构造函数的参数,所以我需要能够区分这一点。
那么,有没有办法以通用的方式和安全的方式提供这个功能呢?
【问题讨论】:
-
ConfigurationProperty是如何实现的?因为显然发生了一些神奇的事情,将返回值从getattr()转换了。您还可以查看__getattr__()和__getattribute__()之间的区别,也可以直接致电__getattr__()。 -
ConfigurationProperty是使用descriptor protocol 实现的。所以是的,有魔法,但那是 Python 的内置魔法。 -
在这种情况下,原始的
ConfigurationProperty对象仍应位于__class__.__dict__中(没有魔法),并且可以检查该类型。
标签: python descriptor