2012-01-22 20 views
3

仍试图了解python。它和php完全不同。如何从raw_input处理整数和字符串?

我将选项设置为整数,问题出现在我的菜单上,我还需要使用字母。

如何将整数和字符串一起使用?
为什么我不能设置字符串比整数?

def main(): # Display the main menu 
    while True: 
     print 
     print " Draw a Shape" 
     print " ============" 
     print 
     print " 1 - Draw a triangle" 
     print " 2 - Draw a square" 
     print " 3 - Draw a rectangle" 
     print " 4 - Draw a pentagon" 
     print " 5 - Draw a hexagon" 
     print " 6 - Draw an octagon" 
     print " 7 - Draw a circle" 
     print 
     print " D - Display what was drawn" 
     print " X - Exit" 
     print 

     choice = raw_input(' Enter your choice: ') 

     if (choice == 'x') or (choice == 'X'): 
      break 

     elif (choice == 'd') or (choice == 'D'): 
      log.show_log() 

     try: 
      choice = int(choice) 
      if (1 <= choice <= 7): 

       my_shape_num = h_m.how_many() 
       if (my_shape_num is None): 
        continue 

       # draw in the middle of screen if there is 1 shape to draw 
       if (my_shape_num == 1): 
        d_s.start_point(0, 0) 
       else: 
        d_s.start_point() 
       # 
       if choice == 1: 
        d_s.draw_triangle(my_shape_num) 
       elif choice == 2: 
        d_s.draw_square(my_shape_num) 
       elif choice == 3:    
        d_s.draw_rectangle(my_shape_num) 
       elif choice == 4:    
        d_s.draw_pentagon(my_shape_num) 
       elif choice == 5:    
        d_s.draw_hexagon(my_shape_num) 
       elif choice == 6:    
        d_s.draw_octagon(my_shape_num) 
       elif choice == 7: 
        d_s.draw_circle(my_shape_num) 

       d_s.t.end_fill() # shape fill color --draw_shape.py-- def start_point 

      else: 
       print 
       print ' Number must be from 1 to 7!' 
       print 

     except ValueError: 
      print 
      print ' Try again' 
      print 
+1

不清楚问题是什么;这个菜单方面似乎工作正常:输入X时执行break,输入D时执行log.show_log(),输入1..7中的整数时分配my_shape_num。 –

+0

问题是:如果选择是D;我得到log.show_log()然后我得到错误信息'再试一次' – emre

+0

所以这个问题与string/int无关;它的“尝试”应该包裹在“其他”中。 –

回答

6

我来回答你的问题与另一个问题:
真的有必要混合字母和数字吗?
他们不能只是所有的字符串?

好吧,让我们走一段路,看看该程序在做:

  1. 显示主菜单
  2. 询问/接收用户输入
    • 如果是有效的:OK
    • 如果不是:打印错误消息并重复
  3. 现在我们有一个有效的输入
    • 如果是字母:做一个特殊任务
    • 如果是一个数字:调用正确的绘制功能

1点让我们做一个功能是:

def display_menu(): 
    menu_text = """\ 
    Draw a Shape 
    ============ 

    1 - Draw a triangle 
    2 - Draw a square 
    D - Display what was drawn 
    X - Exit""" 
    print menu_text 

display_menu非常简单,所以不需要解释它的作用,但我们稍后会看到将此代码放入单独的功能。

点2将用一个循环来实现:

options = ['1', '2', 'D', 'X'] 

while 1: 
    choice = raw_input(' Enter your choice: ') 
    if choice in options: 
     break 
    else: 
     print 'Try Again!' 

点3.好了,第二个想法后,也许是特殊任务不那么特别,让我们把它们也变成功能:

def exit(): 
    """Exit""" # this is a docstring we'll use it later 
    return 0 

def display_drawn(): 
    """Display what was drawn""" 
    print 'display what was drawn' 

def draw_triangle(): 
    """Draw a triangle""" 
    print 'triangle' 

def draw_square(): 
    """Draw a square""" 
    print 'square' 

现在,让我们把它放在一起:

def main(): 
    options = {'1': draw_triangle, 
       '2': draw_square, 
       'D': display_drawn, 
       'X': exit} 

    display_menu() 
    while 1: 
     choice = raw_input(' Enter your choice: ').upper() 
     if choice in options: 
      break 
     else: 
      print 'Try Again!' 

    action = options[choice] # here we get the right function 
    action()  # here we call that function 

到交换机的关键在于options,现在已不再是个listdict,所以如果你简单地迭代它像if choice in options你的迭代是在['1', '2', 'D', 'X'],但如果这样做options['X']你得到的退出功能(并不是那么棒!)。

现在,让我们再一次提高,因为保持主菜单消息和options字典还不算好,从现在开始的一年我可能会忘记改变一个或另一个,我不会得到我想要的,我很懒我不想做两次同样的事情,等等......
那么为什么不通过options字典display_manu并让display_menu做所有使用__doc__的文档字符串的工作来生成菜单:

def display_menu(opt): 
    header = """\ 
    Draw a Shape 
    ============ 

""" 
    menu = '\n'.join('{} - {}'.format(k,func.__doc__) for k,func in opt.items()) 
    print header + menu 

我们需要OrderedDict,而不是dictoptions,贝科顾名思义,请使用OrderedDict保留其项目的顺序(看看official doc)。因此,我们有:

def main(): 
    options = OrderedDict((('1', draw_triangle), 
          ('2', draw_square), 
          ('D', display_drawn), 
          ('X', exit))) 

    display_menu(options) 
    while 1: 
     choice = raw_input(' Enter your choice: ').upper() 
     if choice in options: 
      break 
     else: 
      print 'Try Again!' 

    action = options[choice] 
    action() 

要注意的是你要设计你的行动,使它们都具有相同的签名(反正他们应该是这样的,他们都是行动!)。您可能希望将可调用项作为动作使用:执行__call__的类实例。创建一个基类Action类并继承它将是完美的。

+0

非常感谢,会导致问题。我学到了很多东西 – emre

+0

很彻底,但我注意到你把2.x与2.x的'print'和'raw_input'语句混合在一起。 (也就是说,你在3.x的'print()'脚本中使用'raw_input'。) – Edwin

+0

@Edwin:**脚本在'python 2.x' **中工作。在开始时有一些'print()',但由于只有一个字符串,因为'('Try Again')=='Try Again'',所以你不会注意到'python-2.x'中的区别。这就好像括号是在文本上而不是在'print'上。无论如何,我会修复他们,以清除任何疑问:) –

0

你可以把你的'字母选项'放在except块中。如果输入不能被转换为整数,则执行该块。如果它是一封信。


然而,使您的try块越小越好。所以,这是更好地做到这一点:

try: 
    choice = int(choice) 
except ValueError: 
    choice = choice.lower() # Now you don't have to check for uppercase input 

然后,您可以检查是否选择是一个inttype(choice) == int

+0

最后一点是爆炸。基于OP提交的代码,不需要将类型从“字符串”更改为“int”。 – sgallen

+0

@sgallen,如果输入是一个整数,我意识到他做了一些普通的东西,但实际上我已经删除了这部分。 –

+0

只有当输入的字符串是'('1','2','3','4','5','6','7')之一时才需要一般东西,不需要去当你可以更快速地确定“选择”是否属于定义的可迭代时,用'int(选择)'放下'try'路径。我正在考虑用户输入'88'的情况,这会通过你的'try',当你直接跳到''数字必须从1到7!'时,你会不必要地跳过代码! '线。 – sgallen

2

我不完全清楚你在这里问什么。 raw_input()总是返回str类型。如果您想将用户输入自动转换为int或其他(简单)类型,则可以使用input()函数。

您已选择让用户输入一个字母或数字,您可以在菜单中将“字母”选项同样分配给号码。或者,你可以采取try/except的更多优势,例如:

try: 
    choice = int(user_input) 
    if choice == 1: 
     # do something 
    elif ... 
except ValueError: # type(user_input) != int 
    if choice == 'X' or choice == 'x': 
     # do something 
    elif ... 
    else: 
     print 'no idea what you want' # or print menu again 
2

我相信你的代码可以简化一下:

def main(): 
    while 1: 
     print 
     print " Draw a Shape" 
     print " ============" 
     print 
     print " 1 - Draw a triangle" 
     print " 2 - Draw a square" 
     print " 3 - Draw a rectangle" 
     print " 4 - Draw a pentagon" 
     print " 5 - Draw a hexagon" 
     print " 6 - Draw an octagon" 
     print " 7 - Draw a circle" 
     print 
     print " D - Display what was drawn" 
     print " X - Exit" 
     print 
     choice = raw_input(' Enter your choice: ').strip().upper() 
     if choice == 'X': 
      break 
     elif choice == 'D': 
      log.show_log() 
     elif choice in ('1', '2', '3', '4', '5', '6', '7'): 
      my_shape_num = h_m.how_many() 
      if my_shape_num is None: 
       continue 
      elif my_shape_num == 1: 
       d_s.start_point(0, 0) 
      else: 
       d_s.start_point() 
      if choice == '1': 
       d_s.draw_triangle(my_shape_num) 
      elif choice == '2': 
       d_s.draw_square(my_shape_num) 
      elif choice == '3': 
       d_s.draw_rectangle(my_shape_num) 
      elif choice == '4': 
       d_s.draw_pentagon(my_shape_num) 
      elif choice == '5': 
       d_s.draw_hexagon(my_shape_num) 
      elif choice == '6': 
       d_s.draw_octagon(my_shape_num) 
      elif choice == '7': 
       d_s.draw_circle(my_shape_num) 
      d_s.t.end_fill() 
     else: 
      print 
      print ' Invalid choice: ' + choice 
      print 
+0

添加'.lower()'并在[str(i)中使用'选择范围(1,7)]中的',这是完美的。 –

+0

@RobWouters感谢您的建议。我添加了lower(),但我会坚持使用元组''('1',...)',这对于刚刚学习编程 –

+0

的人来说更容易理解。为简单起见,“+1”号为 –

1

如何使用整数和串起来?为什么我不能设置字符串比整数?

嘛,string formatting是一个非常有用的东西:

>>> a_string = "Hi, I'm a string and I'm" 
>>> an_integer = 42 
>>> another_string = "milliseconds old" 
>>> we_are_the_champions = "%s %d %s" % (a_string, an_integer, another_string) 
>>> we_are_the_champions 
"Hi, I'm a string and I'm 42 milliseconds old" 

你甚至可以只是把该整数转换为字符串:

>>> champions_are_here = "Hi, I'm a string and I'm even older, I'm %d milliseconds old" % 63 
>>> champions_are_here 
"Hi, I'm a string and I'm even older, I'm 63 milliseconds old"