• 4

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191


File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

Why use setattr() and getattr() built-ins?

From reading the docs, I understand exactly what getattr() and setattr() do. But it also says explicitly that getattr(x, 'foobar') is equivalent to x.foobar and setattr(x, 'foobar', 123) is equivalent to x.foobar = 123.

So why would I use them?

      • 1
    • If you can't think of a good reason to use them, you probably don't have one. :) But one day, you've find yourself with an attribute name in a string variable (e.g., from user input, or computed by processing some JSON from a server, or whatever) and want to get the attribute with the name given in that variable, and that's when you'll use it.

Because you can use a dynamic variable too:

somevar = 'foo'
getattr(x, somevar)

You can't do that with regular attribute access syntax.

Note that getattr() also takes an optional default value, to be returned if the attribute is missing:

>>> x = object()
>>> getattr(x, 'foo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'
>>> getattr(x, 'foo', 42)

Using getattr() you can pull the attribute name from something else, not a literal:

for attrname in dir(x):
    print('x.{} = {!r}'.format(attrname, getattr(x, attrname))

or you can use setattr() to set dynamic attributes:

for i, value in enumerate(dynamic_values):
    setattr(i, 'attribute{}'.format(i), value)
  • 48
Reply Report
      • 1
    • Good explanation. But it's worth noting that often, if you think you want this, you don't; the attribute should have been a value in a dictionary rather than an attribute in the first place.
      • 2
    • @abarnert: Not always. There are usecases to handle dynamic transformations on existing objects. Or looking up attributes that could be missing.
      • 2
    • @MartijnPieters: Yes, that's why I said "often". If they were never useful, they wouldn't be in the language at all. As a good rule of thumb: If you normally want to access something statically, but occasionally dynamically, use an attribute with occasional getattr; if you normally want to access it dynamically, but occasionally statically, use a dict with occasional literal keys.
      • 1
    • In my current project codebase I count 12 modules using getattr() (not counting tests); 4 of those are façades; the rest use getattr() to handle optional attributes, returning a default value if missing.
      • 1
    • @MartijnPieters: I've actually got more __getattr__ instances in my code than getattr… but yes, I use it too. The first time I want getattr somewhere, I stop and ask myself whether the thing really should be an attribute. Sometimes the answer is "yes" (or, occasionally, "no, but there's too much spaghetti at this point to fix it…"). But it's always worth thinking about it (except in the cases where it's obvious—e.g., you're writing reflective code for debugging).

You use them if the attribute you want to access is a variable and not a literal string. They let you parameterize attribute access/setting.

There's no reason to do getattr(x, 'foobar'), but you might have a variable called attr that could be set to "foobar" or "otherAttr", and then do getattr(x, attr).

  • 8
Reply Report

Another case probably shows that they are not totally identical:

class A:
    def __init__(self)?
        self.__var = 10
        setattr(self, '__var2', 100)

a = A()
# 100
# AttributeError: 'A' object has no attribute '__var'

At least, setattr is not identical to ..

  • 2
Reply Report

I find it most useful when there is a possibility that the object whose attribute you need might be None. Exemplified below;

obj = None
attr_val = getattr(obj, 'anyvar', None) #This is not an error.
  • 1
Reply Report

Trending Tags