在有效性检查后从 python 中的列表中删除项目
Removing items from a list in python following validity check
背景:
我正在编写一个小脚本,它需要一个文件中的电子邮件地址列表作为其参数之一。该脚本将继续通过 telnet 连接到 SMTP 服务器使用电子邮件地址,因此它们需要在语法上有效;因此,我添加了一个检查电子邮件地址有效性的功能(顺便说一下,这个正则表达式可能并不完美,但不是问题的重点,请耐心等待。可能会被放松):
def checkmailsyntax(email):
match = re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', email)
if match == None:
return True
main() 程序继续读取输入文件名作为参数(在 argparse 中)并将其插入(当前为全局)列表中:
with open(args.targetfile) as targets:
target_email_list = targets.readlines()
我认为如果 checkmailsyntax
函数失败,脚本自动从列表中删除一个电子邮件地址(而不是仅仅告诉你这是错误的,这是它过去所做的)会很棒。然后,这个清理过的列表可以继续向 SMTP 服务器提交语法上有效的电子邮件地址:
for i in target_email_list:
if checkmailsyntax(i):
target_email_list.remove(i)
检查我在删除元素片段之前和之后放置的代码以查看它是否正在执行它的工作时出错:
for i in target_email_list:
print i
问题:代码的输出是这样的:
删除元素片段(以及提交的文件的全部内容)之前:
me@example.com
you@example.com
them@example.com
noemail.com
incorrectemail.com
new@example.com
pretendemail.com
wrongemail.com
right@example.com
badlywrong.com
whollycorrect@example.com
删除元素片段后:
me@example.com
you@example.com
them@example.com
incorrectemail.com
new@example.com
wrongemail.com
right@example.com
whollycorrect@example.com
所以我很困惑为什么 'noemail.com'
、'pretendemail.com'
和 'badlywrong.com'
被删除,而 'incorrectemail.com'
和 'wrongemail.com'
却没有。当文件中依次有两封语法错误的电子邮件时,似乎会发生这种情况。
谁能给我指出正确的方向?
这是因为您在遍历列表时从列表中删除了元素:
for i in target_email_list:
if checkmailsyntax(i):
target_email_list.remove(i) # here
因为,以下值在一起:
pretendemail.com
wrongemail.com
一旦您删除了 pretendemail.com
封电子邮件,下一封 wrongemail.com
将向上移动并且迭代器认为这已被迭代。所以接下来的项目是 right@example.com
并且 wrongemail.com
永远不会检查有效语法。您可以在检查语法之前添加 print(i)
并自行查看。
您可以为此目的使用列表理解:
valid_emails = [email for email in target_email_list if checkmailsyntax(email)]
AKS 的回答已涵盖您:不要从您正在迭代的列表中删除!对于快速修复,您可以在迭代副本时从实际列表中删除:
for i in target_email_list[:]: # iterates over the slice
if checkmailsyntax(i):
target_email_list.remove(i) # removes from actual list
背景:
我正在编写一个小脚本,它需要一个文件中的电子邮件地址列表作为其参数之一。该脚本将继续通过 telnet 连接到 SMTP 服务器使用电子邮件地址,因此它们需要在语法上有效;因此,我添加了一个检查电子邮件地址有效性的功能(顺便说一下,这个正则表达式可能并不完美,但不是问题的重点,请耐心等待。可能会被放松):
def checkmailsyntax(email):
match = re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', email)
if match == None:
return True
main() 程序继续读取输入文件名作为参数(在 argparse 中)并将其插入(当前为全局)列表中:
with open(args.targetfile) as targets:
target_email_list = targets.readlines()
我认为如果 checkmailsyntax
函数失败,脚本自动从列表中删除一个电子邮件地址(而不是仅仅告诉你这是错误的,这是它过去所做的)会很棒。然后,这个清理过的列表可以继续向 SMTP 服务器提交语法上有效的电子邮件地址:
for i in target_email_list:
if checkmailsyntax(i):
target_email_list.remove(i)
检查我在删除元素片段之前和之后放置的代码以查看它是否正在执行它的工作时出错:
for i in target_email_list:
print i
问题:代码的输出是这样的:
删除元素片段(以及提交的文件的全部内容)之前:
me@example.com
you@example.com
them@example.com
noemail.com
incorrectemail.com
new@example.com
pretendemail.com
wrongemail.com
right@example.com
badlywrong.com
whollycorrect@example.com
删除元素片段后:
me@example.com
you@example.com
them@example.com
incorrectemail.com
new@example.com
wrongemail.com
right@example.com
whollycorrect@example.com
所以我很困惑为什么 'noemail.com'
、'pretendemail.com'
和 'badlywrong.com'
被删除,而 'incorrectemail.com'
和 'wrongemail.com'
却没有。当文件中依次有两封语法错误的电子邮件时,似乎会发生这种情况。
谁能给我指出正确的方向?
这是因为您在遍历列表时从列表中删除了元素:
for i in target_email_list:
if checkmailsyntax(i):
target_email_list.remove(i) # here
因为,以下值在一起:
pretendemail.com
wrongemail.com
一旦您删除了 pretendemail.com
封电子邮件,下一封 wrongemail.com
将向上移动并且迭代器认为这已被迭代。所以接下来的项目是 right@example.com
并且 wrongemail.com
永远不会检查有效语法。您可以在检查语法之前添加 print(i)
并自行查看。
您可以为此目的使用列表理解:
valid_emails = [email for email in target_email_list if checkmailsyntax(email)]
AKS 的回答已涵盖您:不要从您正在迭代的列表中删除!对于快速修复,您可以在迭代副本时从实际列表中删除:
for i in target_email_list[:]: # iterates over the slice
if checkmailsyntax(i):
target_email_list.remove(i) # removes from actual list