dispatch method table - Python 中的函数为什么不能加括号?
Why can't we add brackets for functions in dispatch method table - Python?
我想了解函数 tables 中调度 table 的设计。
这是我最初编码的内容
class Aave():
def __init__(self,address):
self.address = address
def function_map(self):
mapping = {1:self.test(),2:self.test2()}
print(type(self.test()))
return mapping[self.address]()
def test(self):
print(1)
return 1
def test2(self):
print(2)
return 2
a = Aave(1)
print(a.function_map())
但是,此函数将调用 2 函数 self.test()
和 self.test2()
,而不仅仅是与键 self.test()
关联的函数。
另一方面,对不带括号的调度 table 进行编码将执行指定的映射函数
像这样
def function_map(self):
mapping = {1:self.test,2:self.test2}
print(type(self.test()))
return mapping[self.address]()
我参考了不同的资源试图理解,但它们没有解释行为上的差异。
我想知道是否有人可以提供一些关于这个问题的启示。
参考:
https://www.oreilly.com/library/view/python-cookbook/0596001673/ch01s07.html
https://betterprogramming.pub/dispatch-tables-in-python-d37bcc443b0b
为了理解这个问题,让我们像解释器一样逐行阅读代码:
# First of all object creation is executed
a = Aave(1)
# This invokes method __init__ of class Aave, hence next step is
a.address = 1
# After the creation of a class instance, interpreter tries to run
print(a.function_map())
# But since value of a.function_map() is unknown it needs to be calculated first
# Hence, interpreter enters function_map method of class Aave
# Execution of
mapping = {1:self.test(), 2:self.test2()}
# requires the test() and test2() to be evaluated. Since brackets indicate function call
# Thus, test() runs, prints 1 and returns 1. If we could see the value of
# mapping after this, it would have been:
# {1: 1, 2: <unknown yet result of self.test2()>}
# ^
# This value is the result of self.test()
# Next self.test2() is evaluated, since it also has brackets and needs to be called
# test2() runs, prints 2 and returns 2.
# After this step, mapping looks like {1: 1, 2: 2}
# ^ ^
# Had this already result of self.test2()
# After this mapping is completely known and next line may be evaluated.
# Evaluating
print(type(self.test()))
# causes one more call to self.test,
# since it also has brackets.
# And when you finally evaluate last line
return mapping[self.address]()
# Keeping in mind, that mapping was {1: 1, 2: 2}, you try to take value by key 1 from mapping,
# which is 1 (int). And call it (since you put "()"). It causes error, because 1 int is not callable.
因此,您在
行中有 2 次调用 self.test()
mapping = {1:self.test(), 2:self.test2()}
# AND
print(type(self.test()))
并在第
行调用 self.test2()
一次
mapping = {1:self.test(), 2:self.test2()}
如果您希望能够调用存储在 mapping
中的内容,您需要在创建 mapping
时删除这些括号。这样您就可以将函数对象存储在字典中而不是函数结果中。
mapping = {1:self.test(), 2:self.test2()} # Call functions and store results
# VS
mapping = {1:self.test, 2:self.test2} # Store functions themselves
这是完全不同的。带括号 - 函数调用的结果,不带 - 函数对象。
我想了解函数 tables 中调度 table 的设计。
这是我最初编码的内容
class Aave():
def __init__(self,address):
self.address = address
def function_map(self):
mapping = {1:self.test(),2:self.test2()}
print(type(self.test()))
return mapping[self.address]()
def test(self):
print(1)
return 1
def test2(self):
print(2)
return 2
a = Aave(1)
print(a.function_map())
但是,此函数将调用 2 函数 self.test()
和 self.test2()
,而不仅仅是与键 self.test()
关联的函数。
另一方面,对不带括号的调度 table 进行编码将执行指定的映射函数
像这样
def function_map(self):
mapping = {1:self.test,2:self.test2}
print(type(self.test()))
return mapping[self.address]()
我参考了不同的资源试图理解,但它们没有解释行为上的差异。
我想知道是否有人可以提供一些关于这个问题的启示。
参考:
https://www.oreilly.com/library/view/python-cookbook/0596001673/ch01s07.html
https://betterprogramming.pub/dispatch-tables-in-python-d37bcc443b0b
为了理解这个问题,让我们像解释器一样逐行阅读代码:
# First of all object creation is executed
a = Aave(1)
# This invokes method __init__ of class Aave, hence next step is
a.address = 1
# After the creation of a class instance, interpreter tries to run
print(a.function_map())
# But since value of a.function_map() is unknown it needs to be calculated first
# Hence, interpreter enters function_map method of class Aave
# Execution of
mapping = {1:self.test(), 2:self.test2()}
# requires the test() and test2() to be evaluated. Since brackets indicate function call
# Thus, test() runs, prints 1 and returns 1. If we could see the value of
# mapping after this, it would have been:
# {1: 1, 2: <unknown yet result of self.test2()>}
# ^
# This value is the result of self.test()
# Next self.test2() is evaluated, since it also has brackets and needs to be called
# test2() runs, prints 2 and returns 2.
# After this step, mapping looks like {1: 1, 2: 2}
# ^ ^
# Had this already result of self.test2()
# After this mapping is completely known and next line may be evaluated.
# Evaluating
print(type(self.test()))
# causes one more call to self.test,
# since it also has brackets.
# And when you finally evaluate last line
return mapping[self.address]()
# Keeping in mind, that mapping was {1: 1, 2: 2}, you try to take value by key 1 from mapping,
# which is 1 (int). And call it (since you put "()"). It causes error, because 1 int is not callable.
因此,您在
行中有 2 次调用self.test()
mapping = {1:self.test(), 2:self.test2()}
# AND
print(type(self.test()))
并在第
行调用self.test2()
一次
mapping = {1:self.test(), 2:self.test2()}
如果您希望能够调用存储在 mapping
中的内容,您需要在创建 mapping
时删除这些括号。这样您就可以将函数对象存储在字典中而不是函数结果中。
mapping = {1:self.test(), 2:self.test2()} # Call functions and store results
# VS
mapping = {1:self.test, 2:self.test2} # Store functions themselves
这是完全不同的。带括号 - 函数调用的结果,不带 - 函数对象。