2016-09-01 36 views
2

我想:一個字符串檢查對象的屬性名稱出現在一個字符串蟒蛇

  • 檢查是否包含一個對象的屬性
  • 如果它再訪問屬性

因此,對於一個類的對象

class Person(object): 
    name = "" 
    age = 0 
    major = "" 

    def __init__(self, name="", surname="", father="", age =0): 
     self.name = name 
     self.surname = surname 
     self.father = father 
     self.age = age 
     self.identity = name +" "+ surname 
    def __str__(self): 
     return self.identity 

    __repr__ = __str__ 

和對象

person = Person("Earl", "Martin", "Jason", 40) 

我想對於字符串「叫什麼名字」 返回person.name (我已經知道該對象的字符串約)

最基本的解決辦法是做對每個案件屬性在那裏,但實際的代碼有很多,我相信我不會手動編寫它們,我只是編程的新手,所以我不確定什麼語法用於此

任何幫助讚賞

+1

串「什麼是姓」 _also_包含屬性名稱'「名」'。我假設你寧願在這種情況下返回'姓氏',但問題(如書面)是不明確的。另外,你想用字符串做什麼,顯然包含多個屬性名稱? (例如「名字和姓氏是什麼?」) – mgilson

+0

@ mgilson感謝您指出它;是的,你的解釋是正確的;至於第二個問題,我只能返回單個字符串,因此可能以先到者爲準 – temo

+0

@mgilson:貪婪是一個體面的解決方案;只需從恰好是對象屬性的字符串中拉出第一個完整的「單詞」(例如匹配正則表達式「r」\ w +「',甚至可以處理下劃線)。如果你永遠不會看到'name'作爲一個單獨的單詞,你甚至不會檢查它。比試圖在查詢中執行'name'更安全的檢查將匹配查詢字符串中的部分字詞。 – ShadowRanger

回答

2

正如其他人指出,getattr一般是有用的。

hasattr具有較低的實用性;在內部,它基本上是一個getattr中的呼叫try/except AttributeError:塊(如果發生AttributeError,它返回False,也不例外意味着True),所以如果你正在考慮類似的代碼:

if hasattr(myobj, attrname): 
    attr = getattr(myobj, attrname) 
    ... 

只需使用:

try: 
    attr = getattr(myobj, attrname) 
except AttributeError: 
    pass 
else: 
    ... 

避免使查找,函數調用和屬性查找的數量翻倍。

或者,反覆拉動命名的屬性(S),operator.attrgetter基本上可讓您的getattr的優化版,預綁定屬性名稱查找(使它適合與像mapfilter功能材料的使用,如它使它們比它們等價的listcomps/genexprs更有效率)。

除此之外,取決於你的目標是什麼,the dir和(稍微不太可靠,由於類that use __slots__ to define a known set of variables to reduce memory usage and prevent auto-vivification的問題)vars function可能是有用的。

例如,在拉從一個字符串對應一個單詞的任何屬性的例子情況下,可以使用vars()/dir()和你filterset操作的選擇(或混合)做法律屬性名稱的散裝識別根據訂單,獨特的

from future_builtins import filter # Only on Py2, not Py3 
import operator 
import re 

def query_obj(obj, querystr): 
    # Extract list of legal attribute names from string 
    words = re.findall(r'\w+', querystr) 

    # Reduce to names present on object's __dict__; no need to construct temporaries 
    attrnames = filter(vars(obj).__contains__, words) 
    # Alternate if __slots__ might be an issue (temp list & frozenset): 
    attrnames = filter(frozenset(dir(obj)).__contains__, words) 
    # Or combine the two to be sure (on Py3, use .keys() instead of .viewkeys()) 
    # (temp list and set): 
    attrnames = filter((vars(obj).viewkeys() | dir(obj)).__contains__, words) 

    # Convenient way to get all names discovered at once; returns single object 
    # for single attr, tuple of objects for multiple attrs: 
    return operator.attrgetter(*attrnames)(obj) 

    # If you want a tuple unconditionally, use this instead: 
    return tuple(getattr(obj, name) for name in attrnames) 

    # Or to only return the first attribute encountered, raising StopIteration 
    # if no attributes are found: 
    return next(getattr(obj, name) for name in attrnames) 

的重要性,等等:然後用法是:

>>> person = Person("Earl", "Martin", "Jason", 40) 
>>> query_obj(person, "What is the name?") 
'Earl' # Would be ('Earl',) in unconditional tuple case 
>>> query_obj(person, "What is the name and surname?") 
('Earl', 'Martin') # Would be 'Earl' in single return case 
+0

謝謝你提供一個很好解釋的解決方案,也可以指出LBYL模式的缺陷,我不知道下面的模式;一個屬性幾乎肯定會出現在我的情況下,所以EAFP模式將是首選。 – temo

3

您正在尋找功能hasattr()getattr()

要檢查屬性是否存在:

hasattr(Person(), 'string') 

,並呼籲屬性:

getattr(Person(), 'string') 
+0

供參考:有些人認爲你應該永遠不會使用['hasattr'](https://hynek.me/articles/hasattr/),而是更喜歡變體上更詳細的'if getattr(obj,string,sentinel )是哨兵'。 – mgilson

+1

@mgilson:我反對'hasattr',但不贊成使用不同的[LBYL](https://docs.python.org/3/glossary.html#term-lbyl)解決方案,該解決方案需要在成功案例。 'attr = getattr(obj,string,sentinel)'then'如果attr不是sentinel:'沒問題,你只需要在'if'檢查前存儲結果。缺陷w /'hasattr'就是成功案例中的工作翻倍(你仍然需要'getattr',它和getattr'本身做同樣的工作),所以使用[EAFP模式](https:// docs.python.org/3/glossary.html#term-eafp)與'getattr'避免了這種併發症。 – ShadowRanger

+0

@ShadowRanger - 當然。我認爲這取決於你正在使用的對象。屬性查找應該很快,所以加倍查找並不一定是壞事(除非你有一個對象,你知道屬性查找_可能會很昂貴)。另外,有很多情況下你只是想知道某個屬性是否存在,但不會對它的值做任何事情(例如'__subclasshook__'中使用了很多)。顯然EAFP通常是首選的:-)。我最後的辯護是我說過「變體」:-P – mgilson

相關問題