【问题标题】:Are there a way to use while loop function as a list tracker? and mix with FileI/O?有没有办法使用 while 循环函数作为列表跟踪器?并与 FileI/O 混合?
【发布时间】:2021-01-17 23:23:43
【问题描述】:
to_do_list = []
while True:
    in_listed = input('item list:')
    
    if in_listed == 'quit':
        break
        
    if in_listed[0] == 'add':
        num1 = int(user_li[-1])
        to_do_list.append(num1 - 1)
        to_do_list.append(num1 - 1)  
    
        print(to_do_list)

    elif in_listed[0] == 'rm':
        num1 = int(user_li[1])
        to_do_list.pop(num1 + 1)
        to_do_list.pop(num1 + 1)
    
        print(to_do_list)
    
    elif in_listed[0] == 'ls':
        for i in range(len(to_do_list)-1):
            print(f'{i} {to_do_list[i]}, {to_do_list[i+1]}')

它有效,但我想使用add 添加一个项目,然后放置一个带有日期的项目。比如我输入add 5/5 buy milk,那么输出就是['5/5', 'buy milk']

【问题讨论】:

  • 您正在实施的称为"Read-eval-print loop"
  • in_listed['0'] 是输入字符串的第一个字符,而不是第一个单词。因此,对于“添加 5/5 购买牛奶”,这将仅返回“a”。所以“添加”条件永远不会评估为真。

标签: python-3.x sorting input while-loop file-io


【解决方案1】:

修复您的 in_listed[0] == 'add' 测试

如果要将输入字符串分割成单词列表,可以使用strip and split

in_listed = input('item list: ').strip().split()

然后您可以安全地测试in_listed[0]"add""rm""quit" 之间的相等性。

读取-评估-打印循环

您正在实施的称为“shell”或"Read-eval-print loop"。我建议简化循环的核心,使其读取输入、识别命令并调用适当的命令;每个命令的单独代码可以分离并放入函数中,而不是在循环内巨大的if/elif/else 森林中。

这是简化后循环的样子:

env = { 'todo_list': [], 'prompt': '$ ',  'didntQuit': True }

command_dict = {'add': cmd_add, 'rm': cmd_rm, 'print': cmd_print_todolist, 'quit': cmd_quit}

while env['didntQuit']:
    argv = input(env['prompt']).strip().split()           # read
    command = command_dict.get(argv[0], cmd_notfound)     # identify command
    ret = command(argv)                                   # execute command
    print_return_value(ret, argv)                         # error message if command failed

我们有一个字典command_dict,其中包含所有命令的名称。在 while 循环体中,我们读取输入;将其拆分为单词列表;在命令字典中查找输入的第一个单词;然后我们评估在字典中找到的命令(或者cmd_notfound,如果我们没有找到具有该名称的命令)。

然后我们可以在while循环外定义函数cmd_addcmd_rmcmd_print_todolistcmd_quit

请注意,我将所有全局变量都移到了一个名为 env(用于“环境”)的字典中,因为我对全局变量持谨慎态度,我更喜欢将它们全部放在一个地方。

完整代码

这里是完整的代码:

env = {
 'todo_list': [],
 'prompt': '$ ',
 'replname': 'repl-todolist',
 'didntQuit': True
 }

def cmd_add(argv):
    if len(argv) > 2:
        date = argv[1]
        item = ' '.join(argv[2:])
    elif len(argv) == 2:
        date = ''
        item = argv[1]
    else:
        return -1
    env['todo_list'].append((date, item))
    return 0

def cmd_rm(argv):
    if len(argv) < 2:
        print('rm: please specify the index of the item you want to remove')
        return -1
    try:
        i = int(argv[1])
        env['todo_list'].pop(i)
        return 0
    except ValueError:
        print('rm: failed to interpret "{}" as a list index'.format(argv[1]))
        return -1
    except IndexError:
        print('rm: index out of range')
        return -1

def cmd_print_todolist(argv):
    print('TODO:')
    for i, (date, item) in enumerate(env['todo_list']):
        print('  ({}) {} {}'.format(i, date, item))
    return 0

def cmd_quit(argv):
    env['didntQuit'] = False
    return 0

def cmd_notfound(argv):
    print('{}: {}: command not found'.format(env['replname'], argv[0]))
    return -1

def print_return_value(ret, argv):
    if ret != 0:
        print('{}: command {} failed with return value {}'.format(env['replname'], argv[0], ret))

command_dict = {'add': cmd_add, 'rm': cmd_rm, 'print': cmd_print_todolist, 'quit': cmd_quit}

while env['didntQuit']:
    argv = input(env['prompt']).strip().split()           # read
    ret = command_dict.get(argv[0], cmd_notfound)(argv)   # eval
    print_return_value(ret, argv)                         # error message

文件 I/O

使用这种结构的代码,添加新命令很简单。只需编写一个新函数,并将其添加到命令字典中!

我建议你阅读 python 中文件 I/O 的教程:Official Doc on Reading and Writing Files

这是一个"save" 命令的示例,它将把待办事项列表写入文件:

def cmd_save(argv):
  if len(argv) < 2:
    print('save: please specify a filename to save the todo-list to')
    return -1
  filename = argv[1]
  try:
    with open(filename, 'w') as outf:
      for i, (date, item) in enumerate(env['todo_list']):
        outf.write('TODO:\n')
          for i, (date, item) in enumerate(env['todo_list']):
            outf.write('  ({}) {} {}\n'.format(i, date, item))
     return 0
  except:
    print('save: unable to open file "{}"'.format(argv[1]))
    return -1

然后你可以将这个函数添加到命令字典中:

command_dict = {'save': cmd_save, 'add': cmd_add, 'rm': cmd_rm, 'print': cmd_print_todolist, 'quit': cmd_quit}

日期和排序待办事项列表

如果您需要解析、操作或打印日期和时间,a python module called datetime 真的很酷。 我建议修改函数cmd_add,将date = argv[1] 行替换为更复杂的代码:

def cmd_add(argv):
    if len(argv) > 2:
        date = datetime.datetime.strptime(argv[1],"%m/%d").replace(datetime.datetime.today().year)
        item = ' '.join(argv[2:])
    elif len(argv) == 2:
        date = datetime.datetime.today()
        item = argv[1]
    else:
        return -1
    env['todo_list'].append((date, item))
    env['todo_list'].sort(key=lambda item: item[0])
    return 0

以下是新功能:

  • 现在date 不再是字符串,而是datetime 对象;
  • 由于用户没有指定年份,我将今天的年份添加到日期(另请参阅this answer);
  • 如果用户没有指定日期,我们会添加带有今天日期的项目;
  • 我在函数末尾添加了.sort()。现在您的待办事项列表按日期排序!

由于日期是一个日期时间对象,我们也想修改cmd_print_todolist,以便以良好的格式打印时间:

def cmd_print_todolist(argv):
    print('TODO:')
    for i, (date, item) in enumerate(env['todo_list']):
        print('  ({}) {} {}'.format(i, date.strftime('%m/%d'), item))
    return 0

我使用'%m/%d' 来格式化日期,但您可以更花哨并添加星期几,或者用文字写月份等。有关日期解析的更多信息,请参阅strptime and strftime behaviour 上的文档和日期打印。

【讨论】:

  • 非常感谢我感谢您所做的工作和您花费的时间 我可以根据自己的喜好声明/使用和更改代码吗?抱歉这么晚才告诉你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多