2014-10-02 94 views
1

我想验证输入使用Python的简单字段。 int类型的Python输入验证 - int在20和100之间,没有字母

  • map_x
  • int类型的map_y bool类型的
  • 障碍

我已经尝试了这里的许多建议对SO。我的代码:

class Map(object): 

    def __init__(self): 
     # Note: These are defaults. 
     # map_x and map_y both have a range of 20 <= x <= 100 
     # obstacles = 'Y' || 'N' 

     self.map_x = -1 
     self.map_y = -1 
     self.obstacles = '-' 

    def forest_map(self): 
     self.map_x = self.choice("Map Width") 
     self.map_y = self.choice("Map Length") 
     self.obstacles = self.choice("Obstacles (Y/N)") 

    def choice(self, text): 
     # Code 

我尝试了几种不同的解决方案,试图保持“高效”和“可重用”代码的概念。

在方法“选择”中找到text参数的原因:我已提示用户正在与之交互(例如,choice = raw_input(text +“ - >”))。

我的解决方案:

我曾尝试与测试,如果文本的说法,但对我来说,太特别是该解决方案的陈述;因此不可重复使用。

我尝试过使用try/except,但是,即使如此,似乎我的while语句正在消耗输入,并且没有将值返回给map_x和map_y。

我曾尝试(成功上一节中的菜单选择中,不收集用户的喜好!)使用字典如下:

# menu is an argument that takes a dictionary. 
# dictionary can be found in a list of dictionaries named menu_list. 
# choice is a member of class Menus, and menu_list is defined in Menu's __init__. 

def choice(self, menu): 
    acceptable = menu 
    if menu == self.menu_list[2]: 
     choice = raw_input("Choice-> ") 
     while choice not in acceptable: 
      choice = raw_input("Choice-> ") 

     Map().generate(choice) 

我只是在测试“障碍”的成功。我用(虽然选择不在['Y','Y','N','n']:#代码

截至目前,我只有在测试整数的问题,但保持真实可重用性和效率的方面

有没有一种方法,我可以看到,如果输入(选择)包含任何类型的字母,并因此,请求更多的输入? 有没有一种方法,我可以同时,确保该map_x/map_y是的范围内2 < =选择< = 100?

感谢一束, Akratix

===编辑10/2/14 === 感谢下面的解决方案,我提出了两个实现。 为了以验证被认为是一个整数,以及在设定范围内输入,我使用下面的代码片断:

def map_choice(self, text): 
    is_valid = False 

    while not is_valid: 
     try: 
      value = int(raw_input(text + "-> ")) 
      if 2 > value or 100 < value: 
       print "Invalid input!" 
       continue 
      return value 

     except ValueError: 
      print "Invalid input!" 

为了验证输入的是被认为是特定的信在一个可接受的输入的“名单”,我用下面的代码片段:

def obstacle_choice(self, text): 
    is_valid = False 

    while not is_valid: 
     value = raw_input(text + "-> ") 
     if any(value == x for x in ('Y', 'N', 'y', 'n')): 
      return value 

回答

0

,你已经开了个好头,但不要太过火试图概括一切。你有两个截然不同的验证字段,所以使用两个不同的“选择”函数是有意义的。

使用类似下面的内容会简单得多。您甚至可以自定义字段错误消息,告诉用户为什么他的输入无效,并且在一般情况下更有帮助。

def forest_map(self): 
    self.map_x = self.map_choice("Map Width") 
    self.map_y = self.map_choice("Map Length") 
    self.obstacles = self.obstacle_choice("Obstacles (Y/N)") 

def map_choice(self, message) 
    # here we use try except to make sure its an integer 
    try: 
     value = int(raw_input(message)) 
    except ValueError: 
     print "Invalid input!" 
     return -1 
    # check range 
    if 20 > value or 100 < value: 
     print "Invalid input!" 
     return -1 
    return value 

def obstacle_choice(self, message): 
    value = raw_input(message) 
    # check if its an acceptable answer 
    if any(value == x for x in ('Y', 'N', 'y', 'n')): 
     return value 
    print "Invalid input!" 
    return -1 

另外,如果你有很多的领域,它可能是值得的一个选择函数,它验证函数作为参数。与您的第二个choice函数类似,但我们不采用“菜单”字典,而是使用验证函数。

def forest_map(self): 
    valid_map = lambda x: 20 <= int(x) <= 100 
    valid_obstacle = lambda x: any(x == y for y in ('Y', 'N', 'y', 'n')) 

    # the choice function will guarantee its safe to use int on the result 
    self.map_x = int(self.choice("Map Width", valid_map)) 
    self.map_y = int(self.choice("Map Length", valid_map)) 
    self.obstacles = self.choice("Obstacles (Y/N)", valid_obstacle) 

def choice(self, message, validate): 
    """ 
    Prompt a user for input and validate the input 

    Args: 
     message (str): Message to display at prompt 
     validate (callable): callable of one parameter to validate input 
    Returns: 
     str: A valid user input 
    """ 
    is_valid = False 
    while not is_valid: 
     # prompt for input 
     value = raw_input(message) 

     # validate input with our validation function 
     # if validate(value) returns True, it ends the loop 
     try: 
      is_valid = validate(value) 

     # maybe the validation function throws an exception 
     # its best to catch the specific error class, but I'll use Exception for simplicity 
     except Exception: 
      is_valid = False 
    return True 

最后,以检查是否输入包含任何字母。您可以使用isalpha方法,该方法检查字符串中的每个字符是否是字母。要检查字符串中的任何字符是否是字母,可以使用它。

value = raw_input('>') 
contains_letters = any(c.isalpha() for c in value) 
+0

Kalhartt,非常感谢您提供的解决方案。我有一个问题: 在第二种解决方案中,采用'self.map_x ='行。 我很困惑,因为valid_map没有被传入'choice',即代码不是int(self.choice(“Map Width”,valid_map))。 为什么lambda函数作为int()的参数传入? 我误解了使用lambda函数吗? 非常感谢! – Akratix 2014-10-03 00:53:44

+0

@Akratix你是绝对正确的,这是我的错误,应该是'int(self.choice(“Map Width”,valid_map))'。好,我会编辑并修复! – kalhartt 2014-10-03 01:14:36

0

给所述choice功能一个额外的参数,这是我通常所说type(尽管用内置的碰撞),即一个可调用,将改变和验证参数。

用这个例子一样IntRange(2, 100)

class IntRange(object): 
    def __init__(self, min, max): 
     self.min = min 
     self.max = max 
    def __call__(self, s): 
     i = int(s) # throws 
     if self.min <= i <= self.max: 
      return i 
     raise ValueError('%d is out of range' % i) 

更多类型的,我实现了在这里:https://github.com/o11c/attoconf/blob/master/attoconf/types.py; enum类型可能对y/n的回答很有用(但您可能需要一些可以正常化的东西)