2016-09-01 39 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

相关问题