匿名类继承

5 投票
3 回答
543 浏览
提问于 2025-04-16 16:08

我正在为一个设备配置构建一个Python自动化API,配置大概是这样的……

root@EX4200-24T# show interfaces ge-0/0/6 
mtu 9216;
unit 0 {
    family ethernet-switching {
        port-mode trunk;
        vlan {
            members [ v100 v101 v102 ];
        }
    }
}

root@EX4200-24T#

我正在为某些操作(比如设置SET)定义Python类,同时也为这些操作的关键词定义类……我的想法是,SET会遍历这些关键词类,并把类的对象附加到接口上。

问题是,这个设备的配置结构比较复杂,比如如果有很多ethernet-switching实例,我不希望API用户必须使用:

# Note that each keyword corresponds to a python class that is appended
# to an InterfaceList object behind the scenes...
SET(Interface='ge-0/0/6.0', Family='ethernet-switching', PortMode='trunk', 
    Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/7.0', Family='ethernet-switching', PortMode='trunk', 
    Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/8.0', Family='ethernet-switching', PortMode='trunk', 
    Vlan=['v100', 'v101', 'v102'])

相反,我希望能够使用:

Family('ethernet-switching')
SET(Interface='ge-0/0/6.0', PortMode='trunk', Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/7.0', PortMode='trunk', Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/8.0', PortMode='trunk', Vlan=['v100', 'v101', 'v102'])
Family(None)
# API usage continues...

但是,我找不到一种方法在Python中实现这个,而不需要用到像这样的代码……

f = Family('ethernet-switching')
f.SET(Interface='ge-0/0/6.0', PortMode='trunk', 
    Vlan=['v100', 'v101', 'v102'])
f.SET(Interface='ge-0/0/7.0', PortMode='trunk', 
    Vlan=['v100', 'v101', 'v102'])
f.SET(Interface='ge-0/0/8.0', PortMode='trunk', 
    Vlan=['v100', 'v101', 'v102'])

这还算可以,直到我需要让SET()从多个类继承……比如……

首选API

# Note: there could be many combinations of classes to inherit from
Family('ethernet-switching')
PortMode('trunk')
SET(Interface='ge-0/0/6.0', Vlan=['v100', 'v101', 'v102'])
SET(Interface='ge-0/0/7.0', Vlan=['v100', 'v101', 'v102'])
PortMode('access')
SET(Interface='ge-0/0/8.0', Vlan=['v100'])
SET(Interface='ge-0/0/9.0', Vlan=['v100'])
Family(None)
PortMode(None)

有没有什么Python的方式可以实现我最后这个API的例子?如果没有,你能分享一些关于如何编写类的层次结构的想法吗?

3 个回答

1

这个内容看起来和 jQuery 的选择和过滤功能很像,它们使用了一种叫做“函数链”的方式:

some_set_of_data
    .filter(first_criteria)
        .filter(second_criteria)

他们还引入了 end() 方法,这样你就可以做一些类似的事情:

some_set_of_data
    .filter(first_criteria)
        .filter(second_criteria)
            .do_something()
        .end()
        .do_something_else()

注意,在这个例子中,do_something() 是在经过 first_criteriasecond_criteria 过滤后的数据上调用的,而 do_something_else() 则只是在经过 first_criteria 过滤的数据上调用的。

在 Python 中使用这种方法应该也很简单,因为它和 JavaScript 有很多相似之处。

2

gnibbler使用的 functools.partial 确实是一种很优雅的方法,但如果你想了解真正基于隐式上下文的做法,我建议你去看看 decimal.getcontext()decimal.setcontext()decimal.localcontext() 这些函数的具体实现细节。

相关文档可以在这里找到: http://docs.python.org/py3k/library/decimal 源代码可以在这里查看: http://hg.python.org/cpython/file/default/Lib/decimal.py#l435

10

这样做对你有帮助吗?

from functools import partial
S=partial(SET, Family='ethernet-switching', PortMode='trunk')
S(Interface='ge-0/0/6.0', Vlan=['v100', 'v101', 'v102'])
S(Interface='ge-0/0/7.0', Vlan=['v100', 'v101', 'v102'])
S(Interface='ge-0/0/8.0', Vlan=['v100', 'v101', 'v102'])

撰写回答