我正在学习Python。我正在阅读一些包含这样的代码:
class Menu:
'''Display a menu and respond to choices when run.'''
def __init__(self):
self.notebook = Notebook()
self.choices = {
"1": self.show_notes,
"2": self.search_notes,
"3": self.add_note,
"4": self.modify_note,
"5": self.quit
}
def display_menu(self):
print("""
Notebook Menu
1. Show all Notes
2. Search Notes
3. Add Note
4. Modify Note
5. Quit
""")
def run(self):
"""Display the menu and respond to choices."""
while True:
self.display_menu()
choice = input("Enter an option: ")
action = self.choice.get(choice)
if action:
action()
else:
print("{0} is not a valid choice".format(choice))
def show_notes(self):
pass
def search_notes(self):
pass
def add_note(self):
pass
def modify_note(self):
pass
def quit(self):
pass
有些线路非常有趣:
action = self.choice.get(choice)
if action:
action()
似乎它正在为特定功能创建一个临时名称。 所以我做了以下测试,以了解更多信息:
>>> def show_notes():
print("show notes")
>>> def search_notes():
print("search notes")
>>> choice = {"1": show_notes, "2": search_notes}
>>> action = choice.get(1)
>>> action()
但是我收到以下错误:
Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
action()
TypeError: 'NoneType' object is not callable
有人可以告诉我这种技术是什么以及背后的原理是什么?
答案 0 :(得分:5)
函数是第一类对象,您可以创建对它们的其他引用。这些都是你需要它们的临时性,但它们也可以是永久性的。
然而,你自己的尝试混淆了字符串和整数;你使用了1
(一个整数),其中实际的密钥是'1'
(一个字符串)。由于您使用了错误的密钥,因此dict.get()
method返回了默认密钥None
。 None
不是函数对象,调用失败。
如果您使用正确的密钥,您的代码也会起作用:
>>> def show_notes():
... print("show notes")
...
>>> def search_notes():
... print("search notes")
...
>>> choice = {"1": show_notes, "2": search_notes}
>>> choice['1']
<function show_notes at 0x10b1fae18>
>>> choice['1']()
show notes
您也可以使用dict.get()
返回默认值,方法是为方法提供更好的默认值:
>>> choice.get('none-such-key', search_notes)()
search notes
答案 1 :(得分:2)
您的测试似乎有误。您应该获得"1"
而不是1
。让1
返回None
因为没有为密钥1
定义任何内容。因此,当您将其称为函数时,它无效。
为了澄清,"1"
是一个字符串,1
是一个整数,它是不同的键。
示例:
>>> a = {"1": "yes"}
>>> a.get(1)
>>> a.get("1")
'yes'
示例II(使用功能):
>>> def hello():
... print "hello"
...
>>> hello()
hello
>>> a = {"1": hello}
>>> b = a.get(1)
>>> b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
>>> b = a.get("1")
>>> b()
hello
答案 2 :(得分:1)
它没有为函数创建随机名称。类方法choice
正在选择一个函数并将其返回,然后将其分配给变量action
。然后通过调用action来调用该函数,就像使用任何函数一样。
以下是一个例子:
def foo():
print(5)
def getFunction():
return foo
x = getFunction()
x()
此输出为5。
从所有这些中退一步,您可以将任何对象分配给任何变量。所以请考虑以下示例(我认为这将有助于您了解更多):
def foo():
print(5)
bar = foo
foo = 5
foo()
这将产生一个整数对象不可调用的错误。这种方式的工作方式是将foo
中包含的函数对象分配给变量bar
,将整数5分配给foo
。函数没有改变,但包含它的变量有。
定义函数def foo
的第一部分是让解释器知道您正在定义一个函数对象并存储在变量foo
中。函数的名称和机制是分开的。
这有意义吗?