如何在 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()
,这正是绑定方法对象的用途。
我正在尝试在 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()
,这正是绑定方法对象的用途。