5

我是 Python OOP 的新手,正在尝试创建一个 OOP 程序来管理库。此代码来自一本书。

此代码按预期工作,但我需要了解action()当我选择特定选项时如何调用相应的函数,例如:当我选择1show_notes函数时,即使我们没有调用它。

Menu.py

import sys
from notebook import Notebook, Note

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.choices.get(choice)
            if action:
                action()
            else:
                print("{0} is not a valid choice".format(choice))

    def show_notes(self, notes=None):
        if not notes:
            notes = self.notebook.notes
        for note in notes:
            print("{0}: {1}\n{2}".format(
                note.id, note.tags, note.memo))

    def search_notes(self):
        filter = input("Search for: ")
        notes = self.notebook.search(filter)
        self.show_notes(notes)

    def add_note(self):
        memo = input("Enter a memo: ")
        self.notebook.new_note(memo)
        print("Your note has been added.")

    def modify_note(self):
        id = input("Enter a note id: ")
        memo = input("Enter a memo: ")
        tags = input("Enter tags: ")
        if memo:
            self.notebook.modify_memo(id, memo)
        if tags:
            self.notebook.modify_tags(id, tags)

    def quit(self):
        print("Thank you for using your notebook today.")
        sys.exit(0)

if __name__ == "__main__":
    Menu().run()

notebook.py

import datetime

# Store the next available id for all new notes
last_id = 0

class Note:
    '''Represent a note in the notebook. Match against a
    string in searches and store tags for each note.'''


    def __init__(self, memo, tags=''):
        '''initialize a note with memo and optional
        space-separated tags. Automatically set the note's
        creation date and a unique id'''
        self.memo = memo
        self.tags = tags
        self.creation_date = datetime.date.today()
        global last_id
        last_id += 1
        self.id = last_id

    def match(self, filter):
        '''Determine if this note matches the filter
        text. Return True if it matches, False otherwise.

        Search is case sensitive and matches both text and
        tags.'''
        return filter in self.memo or filter in self.tags

class Notebook:

    '''Represent a collection of notes that can be tagged,
    modified, and searched.'''

    def __init__(self):
        '''Initialize a notebook with an empty list.'''
        self.notes = []

    def new_note(self, memo, tags=''):
        '''Create a new note and add it to the list.'''
        self.notes.append(Note(memo, tags))

    def _find_note(self, note_id):
        '''Locate the note with the given id.'''
        for note in self.notes:
            if str(note.id) == str(note_id):
                return note
        return None

    def modify_memo(self, note_id, memo):
        '''Find the note with the given id and change its
        memo to the given value.'''
        note = self._find_note(note_id)
        if note:
            note.memo = memo
            return True
        return False

    def modify_tags(self, note_id, tags):
        '''Find the note with the given id and change its
        tags to the given value.'''
        note = self._find_note(note_id)
        if note:
            note.tags = tags
            return True
        return False

    def search(self, filter):
        '''Find all notes that match the given filter
        string.'''
        return [note for note in self.notes if
                note.match(filter)]
4

4 回答 4

6

函数和方法本身就是对象。所以 dict 包含我们然后调用的对象。

所以 self.choices 是一个以“1”、“2”等为键的字典。这些值是方法对象。当您从字典中获取值时,您会获取该对象(称为“可调用”)并将其分配给action. 然后你用action().

代码的关键位是这样的:

 self.choices = {
            "1": self.show_notes,
            "2": self.search_notes,
            "3": self.add_note,
            "4": self.modify_note,
            "5": self.quit
            }

self.choices["1"]计算为 的值self.show_notes,然后将其分配给action,然后用 调用action()

(顺便说一句:示例代码中的菜单是硬编码的,但实际上可以自动生成,如果方法具有文档字符串。 "\n".join("%s: %s" % (key, action.__doc__) for key, action in sorted(self.choices.iteritems())) 要正确处理具有 >=10 项的菜单,您需要将键设置为整数,或者展开单线。)

于 2012-08-08T18:22:17.337 回答
2

self.choices是一个方法字典。当您选择“1”时,会发生这种情况:

action = self.choices.get("1")  # action = self.show_notes

因此,当您打电话时,action()您实际上是在打电话self.show_notes()

于 2012-08-08T18:24:55.427 回答
1

你在这里调用函数:

action = self.choices.get(choice)  # <--- get the function based on user input
if action:
    action()   # <--- call the function here

如果choice等于'1'上面的代码将分配self.show_notesaction然后调用它。

于 2012-08-08T18:22:37.297 回答
0

in menu.py::__init__,self.choices是一个字典,其中键是整数,值是函数。在menu.py::run中,选择是从标准输入输入的,用于键入self.choices字典。所以这条线

action = self.choices.get(choice)

正在将操作设置为 self.choices 中的功能之一。然后可以调用此函数:

action()
于 2012-08-08T18:25:27.790 回答