一个python字典实现,支持属性、类变量和继承以满足复杂的模板化需求。
propdict的Python项目详细描述
一个python字典实现,支持属性、类变量和继承以满足复杂的模板化需求。
测试了Python2.6、2.7和3.3
动机
重写类的特定行为很容易:创建一个子类(甚至仅仅是一个实例)并实现您感兴趣的方面并完成它。不过,模板就不是这样了。如果要更改其中的一部分,则需要重写整个模板,实质上是派生模板作者的工作。
propdict通过允许模板作者将逻辑和行为放入到模板而不是模板本身的数据中来对此进行反驳。
模板的使用者可以简单地对基于propdict的数据进行子类化,覆盖特定方面并保持模板不变。
基本功能
propdict实例的行为几乎与常规字典完全相同,只是您可以使用dict表示法或属性表示法访问值:
>>> server_foo.ip_addr '10.0.0.1' >>> server_foo['ip_addr'] '10.0.0.1'>>> print server_foo['ifconfig'] ifconfig_em0="inet 10.0.0.1 netmask 255.255.255.0">>> print server_foo.ifconfig ifconfig_em0="inet 10.0.0.1 netmask 255.255.255.0"
同样的方法也适用于作业:
>>> server_foo.ip_addr = '192.168.1.1' >>> print server_foo.ip_addr 192.168.1.1>>> server_foo['ip_addr'] = '127.0.0.1' >>> print server_foo.ip_addr 127.0.0.1
当然,赋值也适用于更改属性,如您在示例中所见:
>>> server_foo.ifconfig = u'foo mask' >>> print server_foo.ifconfig foo mask
不过,值得注意的是,您不能删除属性。但是,您可以删除属性的自定义values,但这只会重新公开它们的原始值:
>>> del server_foo['ifconfig'] >>> print server_foo.ifconfig ifconfig_em0="inet 127.0.0.1 netmask 255.255.255.0">>> del server_foo['ifconfig'] Traceback (most recent call last): ... KeyError: 'ifconfig'
示例
假设你是set of templates for configuring *NIX style systems的作者。当然,这些模板中的许多都将使用相同的值,例如正在配置的计算机的IP地址。现在,一些其他值反过来也取决于IP地址的值。假设一个这样的文件有一行使用网络掩码配置网络接口,那么您最终得到一个包含以下代码片段的模板:
>>> template = '''ifconfig_%(iface)s="inet %(ip_addr)s netmask %(netmask)s"'''
给定一个包含必要数据的字典,其计算结果如下:
>>> print template % dict(ip_addr='192.168.1.1', iface='em0', netmask='255.255.255.0') ifconfig_em0="inet 192.168.1.1 netmask 255.255.255.0"
这在大多数情况下都可以工作,但是如果您部署的特定主机位于nat之后,并且需要完全不同的配置,而不遵循上述格式,那会怎么样?现在,您需要创建模板的自定义版本(与上面的基本示例不同,它可以是非平凡的长度和复杂性),只是在一行中不同,或者模板的作者需要工作(另一个)不会影响99%的用户的特殊编辑。
第三种解决方案是尽可能简单地保留(这一行)模板:
>>> template = "%(ifconfig)s"
把逻辑编入字典。喜欢这样:
>>> from propdict import propdict >>> class Host(propdict): ... ip_addr = None ... iface = 'em0' ... netmask = '255.255.255.0' ... @property ... def ifconfig(self): ... return '''ifconfig_%(iface)s="inet %(ip_addr)s netmask %(netmask)s"''' % self>>> server_foo = Host(ip_addr='10.0.0.1') >>> print template % server_foo ifconfig_em0="inet 10.0.0.1 netmask 255.255.255.0"
到目前为止,我们得到了和上面一样的结果。但让我们考虑另一个服务器:
>>> server_bar = Host(ip_addr='10.0.0.2', ifconfig='ifconfig_em1="inet 10.0.0.2 netmask 255.255.0.0"') >>> print template % server_bar ifconfig_em1="inet 10.0.0.2 netmask 255.255.0.0"
请注意,ifconfig的新定义如何包含接口的新值(可能此主机有两个内置值),但仍引用ip_addr。在这种情况下,最好不要简单地提供一个新的静态值,而是更好地实现该属性:
>>> class HostBar(Host): ... iface_2 = 'em1' ... @property ... def ifconfig(self): ... return '''ifconfig_%(iface_2)s="inet %(ip_addr)s netmask %(netmask)s"''' % self >>> server_bar = HostBar(ip_addr='10.0.0.2', netmask='255.255.0.0') >>> print template % server_bar ifconfig_em1="inet 10.0.0.2 netmask 255.255.0.0"
因此,我们可以通过仅更改该值而不接触模板来为ifconfig键提供任意新值,同时仍保留默认行为(它是从接口和IP地址自动为您计算的)。
安装
propdict没有依赖项,可以使用首选工具(如pip、easy_install、buildout和setuptools)简单地作为egg安装。你知道训练。
运行测试
要确保propdict适用于您的安装程序,请运行其测试。您需要从github和py.test结帐,可能是这样:
git clone git@github.com:tomster/propdict cd propdict virtualenv . source bin/activate pip install pytest-cov
然后,运行所有测试(包括本自述文件):
bin/py.test
如果您做了一些更改并想知道是否违反了保险范围:
bin/py.test --cov propdict --cov-report html --cov-report term test_propdict.py
更改日志
1.1-201310-18
- 包装修正[fschulze]
- 在构造函数[fschulze]中支持dict
1.0-2013年10月17日
在生产几个月后,发布了稳定的相同代码。
0.1a1-2013年3月17日
首次公开发行