2016-09-01 10 views
2

文字列pythonで表示された:文字列は、オブジェクトのプロパティ チェックは、私が欲しい

  • が含まれてい

    • チェックするかどうか、それはその後のためので、属性

    にアクセスしない場合クラス

    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.name (私はすでに文字列が行われるオブジェクトかを知る)

    を返すようにするために希望3210

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

    プロパティは存在しますが、実際のコードにはかなりの数があります。私は手作業でそれらを書き出す必要はないと思います。私はちょうどプログラミングに新しいので、どの構文がこのために使われているのかわかりません。

  • +1

    文字列は、プロパティ名 '「の名前を」'含ま_also_「姓ものです」。私はあなたがむしろ 'surname'を返すと思っていますが、その質問は(書かれているように)あいまいです。また、明らかに複数のプロパティ名を含む文字列で何をしたいですか? (例:「名前と姓は何ですか?」) – mgilson

    +0

    @mgilsonご指摘いただきありがとうございます。はい、あなたの解釈は正しいです。 2番目の質問については、おそらくどちらか早いほうに1文字列しか返せません。 – temo

    +0

    @mgilson:貪欲はまともな解決策です。オブジェクト上の属性である文字列から、最初の完全な "単語"(正規表現の 'r '\ w +''と一致するハンドルのアンダースコアと一致させるなど)を引っ張ります。あなたが 'name'をスタンドアロンの単語として見たことがないなら、あなたはそれをチェックすることさえありません。クエリー文字列中の部分的な単語と一致する 'name in query'チェックを行うよりも安全です。 – ShadowRanger

    答えて

    2

    getattrは一般的に有用です。

    hasattrはあまり有効ではありません。あなたは、コードを検討しているので、もし内部で、それはのように、基本的にtry/except AttributeError:ブロックでgetattrコール(AttributeErrorが発生した場合、それは例外がTrueを意味し、Falseを返します)です:

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

    だけ使用します。

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

    LEG Bルックアップ、関数呼び出し、および属性ルックアップの数を2倍にすることを避ける必要があります。

    また、繰り返しという名前の属性(複数可)を引くため、operator.attrgetterは基本的に、あなたのように、(mapfilter機能のようなものの使用に最適です検索する属性名を事前に結合しgetattrの最適化されたバージョンを作ることができます同等の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()filterまたはset操作の選択(またはミックス)を使用して、法的な属性名のバルク識別を行うことができますオーダー、一意性の重要性など:

    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

    FYI:[hasattr'](https://hynek.me/articles/hasattr/)をほとんど使わないようにと主張し、代わりにもっと冗長な '' getattr(obj、string、sentinel )センチネルです。 – mgilson

    +1

    @mgilson:私は 'hasattr'とは反対ですが、別の[LBYL](https://docs.python.org/3/glossary.html#term-lbyl)の解決策ではなく、成功事例。 'attr = getattr(obj、string、sentinel)'そして 'attrがセンチネルでない場合:'はうまくいきますが、 'if'チェックの前に結果を格納するだけです。 (getattrが必要で、getattr自体と同じ働きをしています)、[EAFPパターン](https://)を使用して、成功した場合の作業を2倍にするという欠点がありますdocs.python.org/3/glossary.html#term-eafp)を 'getattr'と組み合わせると、そのような複雑さが回避されます。 – ShadowRanger

    +0

    @ShadowRanger - 確かに。私はこれがあなたが働いているオブジェクトに本当に依存していると思います。属性ルックアップは速くなければならないので、ルックアップを倍増させることは必ずしも悪いことではありません(属性ルックアップが高価であることがわかっているオブジェクトがない限り)。また、属性が存在するかどうかを知りたいだけで、値を持つことは何もしたくない場合があります(これは、例えば '__subclasshook__'で多く使われています)。そして明らかにEAFPが通常好まれます:-)。私の最終的な防衛は、私が「変種」と言ったことです:-P – mgilson

    関連する問題