如何在 Python 中创建方法字典

How do I create a dictionary of methods in Python

我正在尝试在 Python 3.3.3 中创建一个基本的 Intepreter/Virtual 机器 class,如下所示:

class VirtualMachine:

    TERM_DICT = {
        0x01 : self.writeline,
        0x02 : self.expression
    }

    def test(self):
        opcode = 0x01 #hardcoded for testing purposes
        if opcode in self.TERM_DICT:
            term = self.TERM_DICT[opcode]
            term()
        else:
            print("opcode not recognised")

    def writeline(self):
        print("Writeline")

    def expression(self):
        return "Hello World"

myVM = VirtualMachine()
myVM.test()

当我尝试 运行 这个脚本时,我收到错误消息:

Traceback (most recent call last):
  File "testVM.py", line 1, in <module>
    class VirtualMachine:
  File "testVM.py", line 4, in VirtualMachine
    0x01 : self.writeline,
NameError: name 'self' is not defined

请告诉我如何消除此错误并正确使用字典作为对正确 class 方法的查找。

不确定您要做什么,但我想这会给您一个开始:

class VirtualMachine:

    def __init__(self):
        self.TERM_DICT = {0x01 : self.writeline, 0x02 : self.expression}

    def test(self, opcode = 0x01):
        if opcode in self.TERM_DICT:
            term = self.TERM_DICT[opcode]
            term()
        else:
            print("opcode not recognised")

    def writeline(self):
        print("Writeline")

    def expression(self):
        return "Hello World"

myVM = VirtualMachine()
myVM.test()

出于测试目的,您可能希望将 return "Hello World" 更改为 print("Hello World")

您可以像这样重写 test() 函数:

def test(self, opcode = 0x01):
    try:
        self.TERM_DICT[opcode]()
    except KeyError:
        print("opcode not recognised")

根据评论,您可以继续检查操作码,如下所示:

def test(self, opcode = 0x01):
    if opcode in self.TERM_DICT:
        self.TERM_DICT[opcode]()
    else:
        raise KeyError(opcode)

存储方法字典的问题在于,它们需要是绑定方法:

>>> myVM.writeline
<bound method VirtualMachine.writeline of <__main__.VirtualMachine object at 0x104e78c18>>

如果没有实例绑定,您将无法获得绑定方法,因此您需要为每个创建的实例存储 TERM_DICT(正如@Edwin van Mierlo 所做的那样)或查找方法名称动态地 getattr.

这需要对您的代码进行非常少的更改,只需将方法名称存储为字符串,然后在您的测试方法中添加对 getattr 的调用:

class VirtualMachine:

    TERM_DICT = {
        0x01 : "writeline",  #use strings instead of bound methods!
        0x02 : "expression"
    }

    def test(self):
        opcode = 0x01 #hardcoded for testing purposes
        if opcode in self.TERM_DICT:
            method_name = self.TERM_DICT[opcode]
            term = getattr(self, method_name)    #use get_attr here!
            term()
        else:
            print("opcode not recognised")

    def writeline(self):
        print("Writeline")

    def expression(self):
        return "Hello World"

myVM = VirtualMachine()
myVM.test()

这是您每次 运行 创建一个绑定方法对象 .test(),这正是绑定方法对象的用途。