Python:为特定函数创建临时名称

时间:2014-08-28 16:53:24

标签: python

我正在学习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

有人可以告诉我这种技术是什么以及背后的原理是什么?

3 个答案:

答案 0 :(得分:5)

函数是第一类对象,您可以创建对它们的其他引用。这些都是你需要它们的临时性,但它们也可以是永久性的。

然而,你自己的尝试混淆了字符串和整数;你使用了1(一个整数),其中实际的密钥是'1'(一个字符串)。由于您使用了错误的密钥,因此dict.get() method返回了默认密钥NoneNone不是函数对象,调用失败。

如果您使用正确的密钥,您的代码也会起作用:

>>> 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中。函数的名称和机制是分开的。

这有意义吗?