2010-04-06 82 views
3

我正在創建一個公共方法來允許調用者將值寫入設備,例如將其稱爲write_vals()。將非迭代傳遞給list.extend()

由於這些值將被實時輸入,因此我希望通過允許用戶輸入列表或單個值來簡化用戶的生活,具體取決於他們需要編寫多少個值。例如:

write_to_device([1,2,3]) 

write_to_device(1) 

我的功能我想用一個平面列表的工作,所以我試圖要高明和代碼是這樣的:

input_list = [] 
input_list.extend(input_val) 

該作品當用戶輸入一個列表時可以游泳,但當用戶輸入一個整數時會失敗:

T ypeError:'int'對象是不可迭代的

使用list.append()會在列表傳入時創建一個嵌套列表,這將是一個額外的麻煩來扁平化。

檢查傳入的對象的類型看起來笨拙和非pythonic,並希望list.extend()將接受非迭代已經無處得到我。因此,嘗試了其他各種編碼方法。

建議(與編碼有關,請)非常感謝。

+0

當你說用戶輸入列表或單個值時,這是否意味着你收到他們的輸入作爲單個字符串?你是否必須解析逗號? – quamrana 2010-04-06 21:15:00

回答

4

您可以使用try...except...

try: 
    input_list = list(input_val) 
except TypeError: 
    input_list = list((input_val,)) 

這是pythoni C。

P.S .:變量參數,如@sth proposes,好得多,但我留下這個答案的完整性。有時你不能使用可變參數。

+0

我希望找到一個不太羅嗦的解決方案,但是這個工作很好。我喜歡你的'列表((input_val,))'技巧。謝謝! – 2010-04-06 21:42:18

+2

如果將單個字符串傳遞給該函數,則會中斷,如「abc」。 – 2010-04-06 21:45:50

8

您可以檢查傳遞的參數是否爲isinstance()函數的列表。

一個更好的解決方案是支持可變數量的參數:

def write_to_device(*args): 
    # |args| is now a list of all the arguments given to the function 
    input_list.extend(args) 

這樣多個值可以被賦予的功能,即使沒有明確指定它們作爲一個列表:

write_to_device(1) 
write_to_device(1,2,3) 
+0

如果你想傳遞一個列表到write_to_device,你可以使用*:write_to_device(* mylist) – Frederik 2010-04-06 21:15:07

+0

write_to_device(* args)向用戶表明傳遞沒有寫入值是合法的,在這種情況下不是合法的。 – 2010-04-06 21:33:48

+0

@JS:你可以添加一個像if if(args)== 0:raise TypeError('Missing arguments')的檢查' – sth 2010-04-06 21:43:36

3

除了檢查類型,您可以使用try,除了。雖然,我很好奇看到人們如何比Python更好地做到這一點。

input_list = [] 
try: 
    input_list.extend(input_val) 
except TypeError: 
    input_list.append(input_val) 

這似乎是不完整的,以我從錯誤檢查的角度來看,但如果你知道用戶將只輸入一個數值或者列表,這將工作。

+2

+1,但你應該使用'除了TypeError:' – Zach 2010-04-06 21:14:46

+0

@Zach謝謝你捕捉! – Jacinda 2010-04-06 21:18:14

2

有幾種方法可以做到這一點,您選擇的方式取決於您的需求。

你可以嘗試和參數轉換到一個列表,並假設如果它不工作,它應該被解釋爲一個參數:

def write_to_device(args): 
    try: 
     args = list(args) 
    except TypeError: 
     args = [args] 

    print args 

這工作得很好,但你可能會遇到的問題如果你傳遞一個字符串作爲參數:

>>> write_to_device(1) 
[1] 
>>> write_to_device([1,2]) 
[1, 2] 
>>> write_to_device('abc') 
['a', 'b', 'c'] 

您可以通過使用isinstance糾正,要檢查是否該參數是一個字符串:

def write_to_device(args): 
    if isinstance(args, basestring): 
     args = [args] 
    else: 
     try: 
      args = list(args) 
     except TypeError: 
      args = [args] 

    print args 

它給你:

>>> write_to_device(1) 
[1] 
>>> write_to_device([1,2]) 
[1, 2] 
>>> write_to_device('abc') 
['abc'] 

正如有人指出的那樣,你可以讓你的函數取的參數任意數量:

def write_to_device(*args): 
    print args 

它可以幫助您:

>>> write_to_device(1) 
(1,) 
>>> write_to_device([1,2]) 
([1, 2],) 
>>> write_to_device('abc') 
('abc',) 
>>> write_to_device(*[1,2]) 
(1, 2) 

我推薦的方法就是要求將一個列表傳遞給該函數:

write_to_device([1]) 
write_to_device([1, 2, 3]) 

這很簡單,直截了當,毫不含糊。

+0

我喜歡你的第一個建議。清潔和優雅。用戶將傳入一個或一列十六進制值,所以如果他們傳遞一個字符串,那麼腳本就會炸燬,只是甜點。 ;-) 好的,好的。我會檢查一個字符串,並優雅地失敗(抱怨):-) – 2010-04-08 15:37:15

0

基於先發生,我創建這樣的:

def add2list(l,*args): l.extend(args) 
# behaves like .extend, gets round issues of iterability  
# so simple, so powerful! 

實施例:

answer = 42 
mylist = [] 
add2list(mylist,1) 
add2list(mylist,2,3,'a','b','c',answer) 
print mylist 

結果:[1,2,3, 'A', 'B',「C ',42]