必须有更好的方法来做到这一点

时间:2013-02-23 13:08:06

标签: python

这是一个丑陋,高维护的工厂。我真的只需要一种方法来使用字符串来实例化一个名称与字符串匹配的对象。我认为元类是答案,但我无法弄清楚如何应用它:

from commands.shVersionCmd import shVersionCmd
from commands.shVRFCmd import shVRFCmd
def CommandFactory(commandnode):
    if commandnode.attrib['name'] == 'shVersionCmd': return shVersionCmd(commandnode)        
    if commandnode.attrib['name'] == 'shVRFCmd': return shVRFCmd(commandnode)

4 个答案:

答案 0 :(得分:2)

您可以使用globals()函数查找全局名称,该函数返回一个dict:

from commands.shVersionCmd import shVersionCmd
from commands.shVRFCmd import shVRFCmd

# An explicit list of allowed commands to prevent malicious activity.
commands = ['shVersionCmd', 'shVRFCmd']

def CommandFactory(commandnode):
    cmd = commandnode.attrib['name']
    if cmd in commands:
        fn = globals()[cmd]
        fn(commandnode)

答案 1 :(得分:0)

eval是你的朋友:

from commands import *
def CommandFactory(commandnode):
    name=commandnode.attrib['name']
    assert name in ( "shVersionCmd", "shVRFCmd" ), "illegal command"
    return eval(name+"."+name)(commandnode)

请注意,如果您确定 name永远不会包含任何非法命令,那么可以删除assert并将该功能转换为一种无需维护的乐趣。如有疑问,请将其保留并保存在一个地方。

答案 2 :(得分:0)

这个答案How to make an anonymous function in Python without Christening it?讨论了如何根据密钥

干净地调用代码块

答案 3 :(得分:0)

我个人的偏好是在工厂和命令实现之间转换依赖关系,以便每个命令都在工厂注册。

示例实施:

文件命令/ __ init __。py:

import pkgutil
import commands

_commands = {}

def command(commandCls):
    _commands[commandCls.__name__] = commandCls
    return commandCls

def CommandFactory(commandnode):
    name = commandnode.attrib['name']
    if name in _commands.keys():
        return _commands[name](commandnode)

# Load all commands
for loader, module_name, is_pkg in  pkgutil.walk_packages(commands.__path__):
    if module_name!=__name__:
        module = loader.find_module(module_name).load_module(module_name)

文件命令/ mycommand.py:

from commands import command

@command
class MyCommand(object):    
    def __init__(self, commandnode):
        pass

小测试:

from commands import CommandFactory

# Stub node implementation
class Node(object):
    def __init__(self, name):
        self.attrib = { "name": name }

if __name__=='__main__':
    cmd = CommandFactory(Node("MyCommand"))
    assert cmd.__class__.__name__=="MyCommand", "New command is instance of MyCommand"
    cmd = CommandFactory(Node("UnknownCommand"))
    assert cmd is None, "Returns None for unknown command type"