2011-05-20 54 views
11

What’s New in Python 2.7文檔中,它說支持設置字面量是從Python 3.1移植過來的。但是,看起來這種支持並未擴展到ast模塊的literal_eval()函數,如下所示。ast.literal_eval()支持Python 2.7中的設置文字嗎?

這是故意的,疏忽還是別的 - 什麼是從字符串表示中創建文字集的最乾淨的解決方法? (I假設在Python 3.1+以下工作,是嗎?)

import ast 
a_set = {1,2,3,4,5} 
print a_set 
print ast.literal_eval('{1,2,3,4,5}') 

輸出表示錯誤消息:

set([1, 2, 3, 4, 5]) 
Traceback (most recent call last): 
    File "...\setliterals.py", line 4, in <module> 
    print ast.literal_eval('{1,2,3,4,5}') 
    File "...\Python\lib\ast.py", line 80, in literal_eval 
    return _convert(node_or_string) 
    File "...\Python\lib\ast.py", line 79, in _convert 
    raise ValueError('malformed string') 
ValueError: malformed string 

P.S.我能想到的唯一解決方法是使用eval()

回答

1

從錯誤報告:http://bugs.python.org/issue10091

雷蒙德赫廷傑說:

ast.literal_eval的文檔:

「的字符串或提供可能只包括以下的Python 字面結構的節點:字符串,數字,元組,列表,字典,布爾值, 和None。'

我相信我們可以從這個文檔得出結論,這個問題不一定是一個bug,因爲set literal從Python 3.2被移植到3.1和2.7。它ast.literal的Python 2.7用戶應該知道的東西。

+2

在其他意見這個bug線程會說「這可能是一個bug」,從整個討論中可以看出,不包括髮布管理器在缺乏支持時指出的任意決定,從我自己的角度來看,這意味着set如果文字缺乏「ast.literal_eval()」支持,即使事實有效地被遺漏記錄下來,文字也只會被支持2.7。 – martineau 2014-06-06 20:19:31

+1

@martineau thanks,tha值得指出。我使用的bug是可以修復的,不會破壞當前的功能,並且基於Hettinger的迴應和我的上下文理解,他不認爲它是一個錯誤,或者如果他這樣做,他沒有不認爲值得修復?我可能是錯的。 – 2014-06-06 20:31:50

1

我一直在使用這種在一個數據幀大熊貓轉換列(df[col] = df[col].apply(to_set)。可能是任何人發現這個問題是有用的。它可能不是那麼快,但它避免使用eval

def to_set(set_str): 
    """ 
    Required to get around the lack of support for sets in ast.literal_eval. 
    It works by converting the string to a list and then to a set. 

    Parameters 
    ---------- 
    set_str : str 
     A string representation of a set. 

    Returns 
    ------- 
    set 

    Raises 
    ------ 
    ValueError 
     "malformed string" if the string does not start with '{' and and end 
     with '}'. 

    """ 
    set_str = set_str.strip() 
    if not (set_str.startswith('{') and set_str.endswith('}')): 
     raise ValueError("malformed string") 

    olds, news = ['{', '}'] , ['[',']'] 
    for old, new in izip(olds, news):   
     set_str = set_str.replace(old, new) 

    return set(literal_eval(set_str)) 
+2

聰明的解決方法,但前提是您事先知道該字符串包含一組字面值。我還建議剝離前導空白和尾隨空白,以便'startswith'和'endswith'檢查不會拒絕其他有效的字符串。 – martineau 2015-12-03 15:57:26