2009-10-20 18 views
1

我必須在一個類中創建一個基本的FSM,並用Python編寫它。該任務要求我們從文本文件中讀取機器的轉換。因此,例如,有3個狀態,每個有2個可能的過渡,與可能的輸入「A」和「b」一個FSM,wolud有一個文本文件,它看起來像這樣:在int()調用Python優雅失敗?

2   # first line lists all final states 
0 a 1 
0 b 2 
1 a 0 
1 b 2 
2 a 0 
2 b 1 

我想想出一種更加pythonic的方式來一次讀取一行,並將狀態轉換爲整數,同時將輸入值保留爲字符串。基本上這是這樣的想法:

self.finalStates = f.readline().strip("\n").split(" ") 
for line in f: 
    current_state, input_val, next_state = [int(x) for x in line.strip("\n").split(" ")] 

當然,當它試圖int(「a」)它會引發一個ValueError。我知道我可以使用一個傳統的循環,只是趕上ValueError,但我希望有一個更Pythonic這樣做的方式。

+0

「蟒蛇法」你是什麼意思?寫大難幾行代碼? – Oduvan

回答

12

你真的應該只試圖解析,您希望是整數

for line in f: 
    tokens = line.split(" ") 
    current_state, input_val, next_state = int(tokens[0]), tokens[1], int(tokens[2]) 

可以說是更可讀的標記:

for line in f: 
    current_state, input_val, next_state = parseline(line) 

def parseline(line): 
    tokens = line.split(" ") 
    return (int(tokens[0]), tokens[1], int(tokens[2])) 
5

這東西很實用,但我不肯定它是否是「pythonic」......它可能會導致一些人撓頭。你真的應該有一個「懶惰」的zip()做這樣,如果你有大量的值:

types = [int, str, int] 
for line in f: 
    current_state, input_val, next_state = multi_type(types, line) 

def multi_type(ts,xs): return [t(x) for (t,x) in zip(ts, xs.strip().split())] 

而且您使用帶和分論點可以省略,因爲默認設置將工作這裏。

編輯:重新格式化 - 我不會將它用作實際代碼中的一條長線。

+0

我不認爲我會採取這種方法,如果我的線只包含三個值,但如果他們包含更多?當然。 –

+0

如果您需要經常更改單個參數的「類型」函數 - 即將參數1從int()切換到str(),這也是一個非常好的解決方案。 –

0
self.finalStates = [int(state) for state in f.readline().split()] 

for line in f: 
    words = line.split() 
    current_state, input_val, next_state = int(words[0]), words[1], int(words[2]) 
    # now do something with values 

注意,您可以縮短line.strip("\n").split(" ")下降到只有line.split()str.split()的默認行爲是在任何空格上分割,並且它將返回一組沒有任何類型的前導或尾隨空白的單詞。

如果您要將循環中的狀態轉換爲int,那麼我認爲您也希望finalStates也是int

1

你有很好的答案可以很好地解決你的問題。然而,在其他情況下,如果可行的話(如果它們都是數字的話),您可能確實想要將某些字段轉換爲int,並將它們保留爲str否則(如問題的標題所示)不知道提前哪些字段是整數,哪些字段不是。

傳統的Python的方法是嘗試/除外...:

def maybeint(s): 
    try: return int(s) 
    except ValueError: return s 

...你需要包裝成一個功能,因爲沒有辦法做一個try /除了表達(例如,在列表理解)。所以,你使用它像:

several_fields = [maybeint(x) for x in line.split()] 

然而,可能做到這一點特定任務的內聯,如果你喜歡:

several_fields = [(int(x) if x.isdigit() else x) for x in line.split()] 

if/else 「三元運算符」 長相有點奇怪,但人們可以習慣它;-);並且字符串的isdigit方法在字符串非空且只有數字時給出True。

要重複,這是你應該在你的具體情況,在那裏你知道具體int做什麼 - str - 輸入類型int模式;但在更加普遍的情況下,您可能沒有提前提供這些準確的信息!