369

私は最近、関数について読みgetattr()ました。問題は、私がまだその使用法を理解できないことです。私が理解している唯一のことは、getattr()それgetattr(li, "pop")が呼び出しと同じであることli.popです。

実行時まで名前を知らなくても関数への参照を取得するためにそれを使用する方法について本が言及したとき、私は理解できませんでした。たぶん、これは私が一般的にプログラミングの初心者であることです。誰かがこの主題に光を当てることができますか? これを正確にいつ、どのように使用するのですか?

4

14 に答える 14

331

Python のオブジェクトは、属性 (データ属性とそれら (メソッド) を操作する関数) を持つことができます。実際、すべてのオブジェクトには組み込みの属性があります ( Python コンソールで 、 、 をdir(None)試してdir(True)くださいdir(...)) 。dir(dir)

たとえば、、 などpersonのいくつかの属性を持つオブジェクト があるとします。namegender

これらの属性 (メソッドまたはデータ オブジェクト) にアクセスするには、通常person.nameperson.genderperson.the_method()、 などを記述します。

しかし、プログラムを作成する時点で属性の名前がわからない場合はどうなるでしょうか。たとえば、属性の名前が という変数に格納されているとしますattr_name

もしも

attr_name = 'gender'

次に、書く代わりに

gender = person.gender

あなたは書ける

gender = getattr(person, attr_name)

いくつかの練習:

Python 3.4.0 (default, Apr 11 2014, 13:05:11)

>>> class Person():
...     name = 'Victor'
...     def say(self, what):
...         print(self.name, what)
... 
>>> getattr(Person, 'name')
'Victor'
>>> attr_name = 'name'
>>> person = Person()
>>> getattr(person, attr_name)
'Victor'
>>> getattr(person, 'say')('Hello')
Victor Hello

getattr指定さAttributeErrorれた名前の属性がオブジェクトに存在しない場合に発生します。

>>> getattr(person, 'age')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'

ただし、そのような属性が存在しない場合に返されるデフォルト値を 3 番目の引数として渡すことができます。

>>> getattr(person, 'age', 0)
0

getattrwithを使用してdir、すべての属性名を反復処理し、それらの値を取得できます。

>>> dir(1000)
['__abs__', '__add__', ..., '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

>>> obj = 1000
>>> for attr_name in dir(obj):
...     attr_value = getattr(obj, attr_name)
...     print(attr_name, attr_value, callable(attr_value))
... 
__abs__ <method-wrapper '__abs__' of int object at 0x7f4e927c2f90> True
...
bit_length <built-in method bit_length of int object at 0x7f4e927c2f90> True
...

>>> getattr(1000, 'bit_length')()
10

これの実用的な使い方は、名前が で始まるすべてのメソッドを見つけてtest呼び出すことです。

その名前を持つオブジェクトの属性を設定できるものがありますgetattrsetattr

>>> setattr(person, 'name', 'Andrew')
>>> person.name  # accessing instance attribute
'Andrew'
>>> Person.name  # accessing class attribute
'Victor'
>>>
于 2010-11-02T08:48:20.520 に答える
119

私にとってgetattrは、このように説明するのが最も簡単です:

メソッド名を入力する代わりに、文字列の内容に基づいてメソッドを呼び出すことができます。

たとえば、次のことはできません。

obj = MyObject()
for x in ['foo', 'bar']:
    obj.x()

x は 型builtinではなくstr. ただし、これを行うことができます:

obj = MyObject()
for x in ['foo', 'bar']:
    getattr(obj, x)()

入力に基づいてオブジェクトに動的に接続できます。カスタム オブジェクトとモジュールを扱うときに、これが役立つことがわかりました。

于 2013-08-30T17:22:36.880 に答える
45

の非常に一般的な使用例getattrは、データを関数にマッピングすることです。

たとえば、Django や Pylons などの Web フレームワークではgetattr、Web 要求の URL をそれを処理する関数に簡単にマップできます。たとえば、Pylons のルーティングの内部を調べると、(少なくともデフォルトでは) リクエストの URL を次のように切り刻んでいることがわかります。

http://www.example.com/customers/list

「顧客」と「リスト」に分けます。次に、 という名前のコントローラ クラスを検索しますCustomerController。クラスが見つかったと仮定すると、クラスのインスタンスを作成し、 を使用getattrしてそのlistメソッドを取得します。次に、そのメソッドを呼び出し、リクエストを引数として渡します。

この考え方を理解すると、Web アプリケーションの機能を拡張するのは非常に簡単になります。コントローラー クラスに新しいメソッドを追加し、それらのメソッドに適切な URL を使用するリンクをページに作成するだけです。これらはすべて によって可能になりgetattrます。

于 2010-11-02T08:32:53.597 に答える
16

を使用して実行されているオペレーティング システムに応じて、クラスがさまざまなバージョンの save メソッドを起動する方法の簡単で汚い例を次に示しますgetattr()

import os

class Log(object):
    def __init__(self):
        self.os = os.name
    def __getattr__(self, name):
        """ look for a 'save' attribute, or just 
          return whatever attribute was specified """
        if name == 'save':
            try:
                # try to dynamically return a save 
                # method appropriate for the user's system
                return getattr(self, self.os)
            except:
                # bail and try to return 
                # a default save method
                return getattr(self, '_save')
        else:
            return getattr(self, name)

    # each of these methods could have save logic specific to 
    # the system on which the script is executed
    def posix(self): print 'saving on a posix machine'
    def nt(self): print 'saving on an nt machine'
    def os2(self): print 'saving on an os2 machine'
    def ce(self): print 'saving on a ce machine'
    def java(self): print 'saving on a java machine'
    def riscos(self): print 'saving on a riscos machine'
    def _save(self): print 'saving on an unknown operating system'

    def which_os(self): print os.name

このクラスを例で使用してみましょう。

logger = Log()

# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along 
# somewhere else as 1st class:
save_func()

# or you can just call it directly:
logger.save()

# other attributes will hit the else 
# statement and still work as expected
logger.which_os()
于 2010-11-02T07:02:26.257 に答える
4

getattr(..)コードで使用する直前に、二次的に重要な属性を遅延して初期化することがあります。

以下を比較してください。

class Graph(object):
    def __init__(self):
        self.n_calls_to_plot = 0

    #...
    #A lot of code here
    #...

    def plot(self):
        self.n_calls_to_plot += 1

これに:

class Graph(object):
    def plot(self):
        self.n_calls_to_plot = 1 + getattr(self, "n_calls_to_plot", 0)

2 番目の方法の利点は、n_calls_to_plotそれが使用されているコード内の場所の周りにのみ表示されることです。これは可読性に優れています。なぜなら、(1) どのように使用されているかを読むときに、どの値で始まるかをすぐに確認できるからです。(2)__init__(..)メソッドに気を散らすものを導入しないためです。これは、理想的には、クラスの概念的な状態に関するものであるべきです。 、最適化などの技術的な理由で関数のメソッドの1つによってのみ使用され、オブジェクトの意味とは何の関係もないユーティリティカウンターではありません。

于 2015-06-11T00:44:26.313 に答える
4
# getattr

class hithere():

    def french(self):
        print 'bonjour'

    def english(self):
        print 'hello'

    def german(self):
        print 'hallo'

    def czech(self):
        print 'ahoj'

    def noidea(self):
        print 'unknown language'


def dispatch(language):
    try:
        getattr(hithere(),language)()
    except:
        getattr(hithere(),'noidea')()
        # note, do better error handling than this

dispatch('french')
dispatch('english')
dispatch('german')
dispatch('czech')
dispatch('spanish')
于 2015-03-26T13:06:33.007 に答える
3

クラスに格納されたデータから XML ファイルを作成しているときに、属性が存在しないかタイプがNone. この場合、私の問題は、質問で述べたように、属性名が何であるかを知らなかったことでしたが、むしろその属性に保存されたデータでした。

class Pet:
    def __init__(self):
        self.hair = None
        self.color = None

以前にこれを行っていた場合、属性値が型であってもhasattr返され、これにより ElementTreeコマンドが失敗しました。TrueNoneset

hasattr(temp, 'hair')
>>True

属性値が type の場合、Noneそれgetattrも返されるため、ElementTreesetコマンドが失敗します。

c = getattr(temp, 'hair')
type(c)
>> NoneType

現在、これらのケースを処理するために次の方法を使用しています。

def getRealAttr(class_obj, class_attr, default = ''):
    temp = getattr(class_obj, class_attr, default)
    if temp is None:
        temp = default
    elif type(temp) != str:
        temp = str(temp)
    return temp

これが私がいつ、どのように を使用するかですgetattr

于 2016-03-11T20:02:22.157 に答える
0

https://www.programiz.com/python-programming/methods/built-in/getattrからも明確になっています

class Person:
    age = 23
    name = "Adam"

person = Person()
print('The age is:', getattr(person, "age"))
print('The age is:', person.age)

年齢:23歳

年齢:23歳

class Person:
    age = 23
    name = "Adam"

person = Person()

# when default value is provided
print('The sex is:', getattr(person, 'sex', 'Male'))

# when no default value is provided
print('The sex is:', getattr(person, 'sex'))

性別は: 男

AttributeError: 'Person' オブジェクトに属性 'sex' がありません

于 2019-01-09T07:43:12.050 に答える