[英]Reference list index to enumerate value
我有一個程序可以檢查 Outlook 收件箱中是否有來自字典中特定發件人的附件。 Python - Outlook 僅在特定范圍內搜索電子郵件
該程序運行良好,現在我試圖通過讓用戶能夠從字典中選擇特定發件人來擴展它,以便只搜索他們的電子郵件。 這段代碼在之前的程序中。
我的字典是senderDict = {sender@address.com : Sender Name}
要將其轉換為可供選擇的值菜單,我使用了 enumerate:
listSender = list(senderDict.values())
for count, item in enumerate(listSender,1):
print(count, item)
print("There are", len(listSender), "items.")
while True:
senderNum = int(input("Choose a sender (zero for any): "))
try:
if senderNum <= len(listSender) and senderNum >= 0:
#senderNum = int(input("Choose a sender (zero for any): "))
print("you chose", listSender[senderNum])
break
elif senderNum == 0:
print("Searching for any sender")
break
elif senderNum < 0:
print("Cannot choose a negative number.")
continue
except ValueError: #Not int
print("You did not enter a valid number (ValueError)")
input()
except IndexError: #outside range
print("You did not enter a valid number (IndexError)")
input()
問題是選擇零將選擇零索引,而不是“搜索任何”。 如何使列表索引與枚舉值匹配?
此外,輸入非數字或空白輸入會使程序崩潰,所以我不確定哪些異常涵蓋了它,我認為它屬於 ValueError。
我什至不確定是否需要將字典轉換為列表,但我讀到枚舉工作是必要的,所以我就這樣做了。
您的代碼中似乎有一個小錯誤!
if senderNum <= len(listSender) and senderNum >= 0:
上面的行包括 0. 0 >= 0 == True
因此
elif senderNum == 0:
永遠不會到達,因為它已經在之前的 if 語句中到達了。 我相信你想做的是
if senderNum <= len(listSender) and senderNum > 0:
這樣,當所選數字為 0 時,上面的行將為 False,並且您的代碼將到達 elif 行。 如果您需要它來匹配列表中的索引,由於您將枚舉設置為從 1 開始,您可以手動從用戶選擇的值count - 1
減去count - 1
。
為了捕獲不正確的值,您可以添加一個 else 語句:
else:
print('Incorrect value')
continue
您的問題是如何列出索引匹配枚舉值。 這很容易,您只需從用戶提供給您的輸入中減去 1。 問題在於您的 if 子句senderNum >= 0
如果您的用戶輸入 0 elif senderNum == 0
真,因此elif senderNum == 0
永遠不會為真
當您輸入一個非數字時發生崩潰,因為您在將條目轉換為 int 后進行了try
。 所以你必須把 try 放在int(input("Choose a sender (zero for any): "))
我的建議是選擇負數發送給任何人。
所以我的建議如下:
listSender = list(senderDict.values())
for count, item in enumerate(listSender):
print(count, item)
print("There are", len(listSender), "items.")
while True:
try: # have to be before the int(input(...)) to catch the exception
senderNum = int(input("Choose a sender (-1 for any): "))
if senderNum < len(listSender) and senderNum >= 0: # len(listSender) is not allowed because the index starts at 0 and the last entry is len(listSender) -1
print("you chose", listSender[senderNum])
break
elif senderNum < 0:
print("Search for any sender")
break
except ValueError: #Not int
print("You did not enter a valid number (ValueError)")
input()
except IndexError: #outside range
print("You did not enter a valid number (IndexError)")
input()
如果您真的想使用 0 作為發送任何 I 那么您必須執行以下操作:
listSender = list(senderDict.values())
for count, item in enumerate(listSender,1):
print(count, item)
print("There are", len(listSender), "items.")
while True:
try:
senderNum = int(input("Choose a sender (zero for any): "))
if senderNum <= len(listSender) and senderNum > 0: # if senderNum is zero then send for any so senderNum >= 0 has to be changed to senderNum > 0
print("you chose", listSender[senderNum-1]) # because index starts with 0 you have to subtract 1 from the input
break
elif senderNum == 0:
print("Searching for any sender")
break
elif senderNum < 0:
print("Cannot choose a negative number.")
continue
except ValueError: #Not int
print("You did not enter a valid number (ValueError)")
input()
except IndexError: #outside range
print("You did not enter a valid number (IndexError)")
input()
解決您關於枚舉和字典/列表的最后一個問題。 字典沒有排序,所以這就是為什么你不能用索引枚舉它的原因。 所以有必要做一個轉換成一個列表。 使用它而不將其轉換為列表的另一種方法是使用字典鍵而不是索引號作為輸入。
問題是選擇零將選擇零索引,而不是“搜索任何”。 如何使列表索引與枚舉值匹配?
首先修復測試的順序,然后從用戶的輸入中減去 1。
此外,輸入非數字或空白輸入會使程序崩潰,所以我不確定哪些異常涵蓋了它,我認為它屬於 ValueError。
int(something)
可以引發TypeError
(如果type(something)
不是可以解釋為數值的東西)或ValueError
如果類型正常但不是值。
input()
( py2 中的raw_input()
) always returns a string so you cannot have a
TypeError eher and
ValueError` 確實是你想要捕捉的 - 但你必須把你的 try/except 塊放在正確的位置。 目前你有:
senderNum = int(input("Choose a sender (zero for any): "))
try:
# use senderNum here
except ValueError:
# ...
但是ValueError
是由int(...)
引發的,因此它確實不會被捕獲。 你要:
try:
senderNum = int(input("Choose a sender (zero for any): "))
except ValueError:
print("not a valid value")
continue
# ok, now `senderNum` is an integer
此外,由於您測試senderNum
是否在邊界內,因此您不應該有任何IndexError
。 好吧,實際上如果測試是正確的,你就不會 - 你應該測試senderNum
嚴格小於len(listSender)
- 記住列表是從零開始的,所以列表的最后一個索引是len(lst) - 1
:
>>> lst = list("abc")
>>> len(lst)
3
>>> 3 <= len(lst)
True
>>> lst[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> 3 < len(lst)
False
>>>
我什至不確定是否需要將字典轉換為列表,但我讀到枚舉工作是必要的,所以我就這樣做了。
enumerate()
適用於任何可迭代對象。 dict
是可迭代的,因此您可以直接通過senderDict
進行enumerate
-但是您將擁有密鑰,而不是名稱。 或者您可以直接傳遞senderDict.values()
,但是您將遇到另一個問題,即如何從名稱中取回電子郵件。
此處正確的解決方案是將您的 dict 轉換為(key, value)
元組list(senderDict.items())
- 這與list(senderDict.items())
一樣簡單,因此您可以從選擇的列表索引中獲取姓名和電子郵件。
更正的代碼:
senders = list(senderDict.items())
# this won't change during execution so let's
# stop recomputing it each time
nb_senders = len(senders)
for index, (email, name) in enumerate(senders, 1):
print("{}: {} ({})".format(index, name, email)
print("There are {} items.".format(nb_senders))
while True:
# get the raw input
senderNum = input("Choose a sender (zero for any): ")
# now validate it
try:
senderNum = int(senderNum)
if senderNum < 0:
raise ValueError("should not be negative")
if senderNum > nb_senders:
raise ValueError("should be lesser than {}".format(nb_senders))
except ValueError as e:
print("'{}' is not valid choice: {}".format(senderNum, e))
continue
# ok, done
if senderNum == 0:
print("Searching for any sender")
break
print("you chose {} ({})".format(*listSender[senderNum]))
break
感謝所有有用的回復!
我沒有嘗試更改輸入的值,而是決定在將字典轉換為列表后為“搜索任何”插入一個列表選項,然后讓枚舉從零開始。 這樣我就不必做任何加法或減法,索引值仍然與輸入匹配。
listSender = list(senderDict.values())
listSender.insert(0, "Search Any")
for count, item in enumerate(listSender):
print(count, item)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.