使用for循环检查列表中的字段是否错误

时间:2017-09-09 11:48:49

标签: python loops for-loop

我有以下代码,试图将文件内容读入列表(此位有效),然后显示接受消息,如果银行详细信息(用户和相应的号码)匹配。

e.g。如果用户名:customer1和account_number:1输入>>对文件中的每个客户和帐号进行授权等等。

文件详情

def strip_split_read_from_file():
   bankdetails=[]
   with open("bankdetails.txt","r") as f:
      for line in f:
         line=line.rstrip() #r strip removes the new line character from the right side of the string
         split_line=line.split(",")
         for field in split_line:
            bankdetails.append(field)

   accessgranted=False
   while accessgranted==False:
       username=input("username:")
       password=input("account no:")

       for i in bankdetails:
          if username==bankdetails[i] and password==bankdetails[i+1]:
             accessgranted=True
             break
          else:
            accessgranted=False


       if accessgranted==True:
         print("Access Granted")
       else:
         print("Sorry, wrong credentials")

代码

 if username==bankdetails[i] and password==bankdetails[i+1]:
TypeError: list indices must be integers, not str

错误

{{1}}

对于答案和教学/学习目的,我想要以下

  1. 使用现有的提供的代码

  2. 更正错误的错误说明
  3. 关于以尽可能最有效的方法实现同一目标的替代方法的建议

4 个答案:

答案 0 :(得分:1)

for i in bankdetails:表示i将成为bankdetails中的每个元素,而不是它将成为元素的位置。如果您希望它成为位置,则必须执行for i in len(bankdetails),因为len()是获取数据结构长度的函数。但是,由于每次都有两个字段,我建议使用while结构,如下所示:

total = len(bankdetails) - 1
i = 0
while i < total:
    if username==bankdetails[i] and password==bankdetails[i+1]:
        accessgranted=True
        break
    else:
        accessgranted=False
    i += 2

但是,如果列表中有大量条目,则迭代所有条目可能会花费大量时间。为了避免这种情况,使用字典是最好的选择:检查项目是否在其中的速度要快得多,并且您不需要迭代来查找与之关联的值。

如果您不知道字典是如何工作的,它有点像列表,除非它们没有被排序,而您查找项目的方式是检查与键关联的值。让我们更清楚一点。在您的文件中,您有:

customer1,1
customer2,2
customer3,3
customer4,4
customer5,5

将它们添加到字典中的方法是:

bankdetails={} #Notice that they're initialized as {}
   with open("bankdetails.txt","r") as f:
      for line in f:
         line=line.rstrip() #r strip removes the new line character from the right side of the string
         split_line=line.split(",")
         username = split_line[0]
         password = split_line[1]
         bankdetails[username] = password

这样,bankdetails将包含{'customer1': '1', 'customer2': '2', ... }

而且,要查找用户及其密码,您必须执行此操作:

username=input("username:")
password=input("account no:")
if username in bankdetails:
    if bankdetails[username]==password:
       accessgranted=True
       break
    else:
        accessgranted=False

这将完全符合您的要求,但如果您有大量条目,则会更快。

答案 1 :(得分:1)

def strip_split_read_from_file():
   bankdetails=[]
   with open("files.txt","r") as f:
      for line in f:
         line=line.rstrip()
         split_line=line.split(",")
         for field in split_line:
            bankdetails.append(field)

   accessgranted=False

   i = 0                               #1
   while accessgranted==False:

      username=input("username:")
      password=input("account no:")
      if username==bankdetails[i] and password==bankdetails[i+1]:
         accessgranted=True
         print("Access Granted")      #2
         break
      else:
         accessgranted=False
         print("Sorry, wrong credentials")     #3
      i += 2

1)它将是文件

中包含的数据总长度的开始

2)如果用户名和密码正确,则打印&#34;访问授权&#34;在中断之前,它将不会被打印,因为执行将在中断后移出循环

3)打印错误的凭据&#34;如果数据没有匹配并转移到下一次迭代并给出另一次机会

答案 2 :(得分:0)

如何(未经测试):

def strip_split_read_from_file():
    bankdetails=[]
    with open("bankdetails.txt","r") as f:
        for line in f:
            line = line.rstrip() 
            pair = line.split(",")                          # 1 
            assert(len(pair) == 2)                          # 2
            bankdetails.append(pair)                        # 3

    accessgranted=False
    while accessgranted==False:
        username=input("username:")
        password=input("account no:")

        for pair in bankdetails:                            # 4
            if username==pair[0] and password==pair[1]:     # 5
                accessgranted=True
                break
            else:
                accessgranted=False


        if accessgranted==True:
            print("Access Granted")
        else:
            print("Sorry, wrong credentials")

注意:

标记为1-3的行稍微改变了存储(用户名,帐号)对的布局。索引0,2,4,6,...表示用户名和1,3,5,7,...代表帐号,而不是存储为“平面”列表,而是现在有两个维度。现在,bankdetails是一个包含2元素元组的列表,其中第一个元素是用户名,第二个元素是帐号。这与文件的布局非常相似。

之前,您的列表看起来像:

[username1, account1, username2, account2, username3, ...]

现在它看起来像:

[
    (username1, account1),
    (username2, account2),
    (username3, account3),
    ...
]

第2行只对数据执行(非常基本的)健全性检查。

第4行只是将循环变量重命名为pair,以更好地表示将分配给该变量的内容,一个bankdetails条目 - 一对。 (i通常保留用于最小范围的整数循环变量)

第5行使用pair并访问该对中的各个元素 - pair[0]获取第一个,用户名和pair[1]获取第二个/最后一个,即帐号。

这一切都改变了。最后,您可能会考虑制作一个Account类,您可以为每个帐户实例化,并且具有usernameaccount_number成员属性。您也可以使用命名元组来实现类似目的。

此外,您可以稍微清理一下程序的流程,或许类似于(再次,未经测试):

def strip_split_read_from_file():
    bankdetails=[]
    with open("bankdetails.txt","r") as f:
        for line in f:
            line = line.rstrip() 
            pair = line.split(",")                          # 1 
            assert(len(pair) == 2)                          # 2
            bankdetails.append(pair)                        # 3

    return bankdetails

def evaluate_login(bankdetails, username, password):
    for pair in bankdetails:                                # 4
        if username==pair[0] and password==pair[1]:         # 5
            return True

    return False


# Read file containing account info
bankdetails = strip_split_read_from_file()

# Prompt user for login
username=input("username:  ")
password=input("account no: ")

# Test user input
accessgranted = evaluate_login(bankdetails, username, password):

# Show login result
if accessgranted==True:
    print("Access Granted")
else:
    print("Sorry, wrong credentials")

答案 3 :(得分:0)

我建议您使用以下代码:

import csv
with open('bankdetails.txt', 'r') as file:
     reader = csv.reader(file)
     bankdetails = [row for row in reader]

这将为您提供客户列表列表:

[['customer1', '1'], ['customer2', '2'], ['customer3', '3'], ['customer4', '4'], ['customer5', '5']]

现在,你可以更容易地改进它:

for customer in bankdetails:
    customer[0] would be your customer
    customer[1] would be your digit