What is getattr() exactly and how do I use it?

前端 未结 14 1645
孤独总比滥情好
孤独总比滥情好 2020-11-22 09:04

I\'ve recently read about the getattr() function. The problem is that I still can\'t grasp the idea of its usage. The only thing I understand about getattr() is

相关标签:
14条回答
  • 2020-11-22 09:38

    Objects in Python can have attributes -- data attributes and functions to work with those (methods). Actually, every object has built-in attributes.

    For example you have an object person, that has several attributes: name, gender, etc.

    You access these attributes (be it methods or data objects) usually writing: person.name, person.gender, person.the_method(), etc.

    But what if you don't know the attribute's name at the time you write the program? For example you have attribute's name stored in a variable called attr_name.

    if

    attr_name = 'gender'
    

    then, instead of writing

    gender = person.gender
    

    you can write

    gender = getattr(person, attr_name)
    

    Some practice:

    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 will raise AttributeError if attribute with the given name does not exist in the object:

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

    But you can pass a default value as the third argument, which will be returned if such attribute does not exist:

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

    You can use getattr along with dir to iterate over all attribute names and get their values:

    >>> 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
    

    A practical use for this would be to find all methods whose names start with test and call them.

    Similar to getattr there is setattr which allows you to set an attribute of an object having its name:

    >>> setattr(person, 'name', 'Andrew')
    >>> person.name  # accessing instance attribute
    'Andrew'
    >>> Person.name  # accessing class attribute
    'Victor'
    >>>
    
    0 讨论(0)
  • 2020-11-22 09:41

    I sometimes use getattr(..) to lazily initialise attributes of secondary importance just before they are used in the code.

    Compare the following:

    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
    

    To this:

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

    The advantage of the second way is that n_calls_to_plot only appears around the place in the code where it is used. This is good for readability, because (1) you can immediately see what value it starts with when reading how it's used, (2) it doesn't introduce a distraction into the __init__(..) method, which ideally should be about the conceptual state of the class, rather than some utility counter that is only used by one of the function's methods for technical reasons, such as optimisation, and has nothing to do with the meaning of the object.

    0 讨论(0)
  • 2020-11-22 09:43
    # 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')
    
    0 讨论(0)
  • 2020-11-22 09:45

    I think this example is self explanatory. It runs the method of first parameter, whose name is given in the second parameter.

    class MyClass:
       def __init__(self):
          pass
       def MyMethod(self):
          print("Method ran")
    
    # Create an object
    object = MyClass()
    # Get all the methods of a class
    method_list = [func for func in dir(MyClass) if callable(getattr(MyClass, func))]
    # You can use any of the methods in method_list
    # "MyMethod" is the one we want to use right now
    
    # This is the same as running "object.MyMethod()"
    getattr(object,'MyMethod')()
    
    0 讨论(0)
  • 2020-11-22 09:46

    setattr()

    We use setattr to add an attribute to our class instance. We pass the class instance, the attribute name, and the value.

    getattr()

    With getattr we retrive these values

    For example

    Employee = type("Employee", (object,), dict())
    
    employee = Employee()
    
    # Set salary to 1000
    setattr(employee,"salary", 1000 )
    
    # Get the Salary
    value = getattr(employee, "salary")
    
    print(value)
    
    0 讨论(0)
  • 2020-11-22 09:46

    It is also clarifying from 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)
    

    The age is: 23

    The age is: 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'))
    

    The sex is: Male

    AttributeError: 'Person' object has no attribute 'sex'

    0 讨论(0)
提交回复
热议问题