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

前端 未结 14 1643
孤独总比滥情好
孤独总比滥情好 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:29

    getattr(object, 'x') is completely equivalent to object.x.

    There are only two cases where getattr can be useful.

    • you can't write object.x, because you don't know in advance which attribute you want (it comes from a string). Very useful for meta-programming.
    • you want to provide a default value. object.y will raise an AttributeError if there's no y. But getattr(object, 'y', 5) will return 5.
    0 讨论(0)
  • 2020-11-22 09:33

    Quite frequently when I am creating an XML file from data stored in a class I would frequently receive errors if the attribute didn't exist or was of type None. In this case, my issue wasn't not knowing what the attribute name was, as stated in your question, but rather was data ever stored in that attribute.

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

    If I used hasattr to do this, it would return True even if the attribute value was of type None and this would cause my ElementTree set command to fail.

    hasattr(temp, 'hair')
    >>True
    

    If the attribute value was of type None, getattr would also return it which would cause my ElementTree set command to fail.

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

    I use the following method to take care of these cases now:

    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
    

    This is when and how I use getattr.

    0 讨论(0)
  • 2020-11-22 09:34

    Here's a quick and dirty example of how a class could fire different versions of a save method depending on which operating system it's being executed on using 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
    

    Now let's use this class in an example:

    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()
    
    0 讨论(0)
  • 2020-11-22 09:35

    A pretty common use case for getattr is mapping data to functions.

    For instance, in a web framework like Django or Pylons, getattr makes it straightforward to map a web request's URL to the function that's going to handle it. If you look under the hood of Pylons's routing, for instance, you'll see that (by default, at least) it chops up a request's URL, like:

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

    into "customers" and "list". Then it searches for a controller class named CustomerController. Assuming it finds the class, it creates an instance of the class and then uses getattr to get its list method. It then calls that method, passing it the request as an argument.

    Once you grasp this idea, it becomes really easy to extend the functionality of a web application: just add new methods to the controller classes, and then create links in your pages that use the appropriate URLs for those methods. All of this is made possible by getattr.

    0 讨论(0)
  • 2020-11-22 09:35

    Other than all the amazing answers here, there is a way to use getattr to save copious lines of code and keeping it snug. This thought came following the dreadful representation of code that sometimes might be a necessity.

    Scenario

    Suppose your directory structure is as follows:

    - superheroes.py
    - properties.py
    

    And, you have functions for getting information about Thor, Iron Man, Doctor Strange in superheroes.py. You very smartly write down the properties of all of them in properties.py in a compact dict and then access them.

    properties.py

    thor = {
        'about': 'Asgardian god of thunder',
        'weapon': 'Mjolnir',
        'powers': ['invulnerability', 'keen senses', 'vortex breath'], # and many more
    }
    iron_man = {
        'about': 'A wealthy American business magnate, playboy, and ingenious scientist',
        'weapon': 'Armor',
        'powers': ['intellect', 'armor suit', 'interface with wireless connections', 'money'],
    }
    doctor_strange = {
        'about': ' primary protector of Earth against magical and mystical threats',
        'weapon': 'Magic',
        'powers': ['magic', 'intellect', 'martial arts'],
    }
    

    Now, let's say you want to return capabilities of each of them on demand in superheroes.py. So, there are functions like

    from .properties import thor, iron_man, doctor_strange
    
    
    def get_thor_weapon():
        return thor['weapon']
    
    
    def get_iron_man_bio():
        return iron_man['about']
    
    
    def get_thor_powers():
        return thor['powers']
    

    ...and more functions returning different values based on the keys and superhero.

    With the help of getattr, you could do something like:

    from . import properties
    
    
    def get_superhero_weapon(hero):
        superhero = getattr(properties, hero)
        return superhero['weapon']
    
    
    def get_superhero_powers(hero):
        superhero = getattr(properties, hero)
        return superhero['powers']
    

    You considerably reduced the number of lines of code, functions and repetition!

    Oh and of course, if you have bad names like properties_of_thor for variables , they can be made and accessed by simply doing

    def get_superhero_weapon(hero):
        superhero = 'properties_of_{}'.format(hero)
        all_properties = getattr(properties, superhero)
        return all_properties['weapon']
    

    NOTE: For this particular problem, there can be smarter ways to deal with the situation, but the idea is to give an insight about using getattr in right places to write cleaner code.

    0 讨论(0)
  • 2020-11-22 09:35

    I have tried in Python2.7.17

    Some of the fellow folks already answered. However I have tried to call getattr(obj, 'set_value') and this didn't execute the set_value method, So i changed to getattr(obj, 'set_value')() --> This helps to invoke the same.

    Example Code:

    Example 1:

        class GETATT_VERIFY():
           name = "siva"
           def __init__(self):
               print "Ok"
           def set_value(self):
               self.value = "myself"
               print "oooh"
        obj = GETATT_VERIFY()
        print getattr(GETATT_VERIFY, 'name')
        getattr(obj, 'set_value')()
        print obj.value
    
    0 讨论(0)
提交回复
热议问题