dynamic setattr

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Jul 27 15:46:59 CEST 2012


On Fri, 27 Jul 2012 05:49:45 -0700, Mariano Di Felice wrote:

> Hi,
>   I have a property file (.ini) that has multiple sections and relative
>   keys, as default structure.

Have you looked at Python's standard INI file library?

http://docs.python.org/library/configparser.html


> Now, I would like to export from my utility class methods getter and
> setter. I have started as is:
> 
> class Utility:
> 
>   keys = {"STANDUP": ["st_key1", "st_key2", "st_key3", "st_key4"],
>               "DEFAULT": ["def_key1", "def_key2", "def_key3",
>               "def_key4", "def_key5"]}

This defines a *shared* class attribute. As it is attached to the class, 
not an instance, every instance will see the same shared dict.


>   def __init__(self):
>             for section, keyList in  keys .items(): 
>             for key in keyList:

As given, this is a SyntaxError. Please do not retype your code from 
memory, always COPY AND PASTE your actual code.

In this case, it is easy to fix the syntax error by fixing the 
indentation. But what other changes have you made by accident?

Your code:

    def __init__(self):
        for section, keyList in  keys .items(): 

looks for a *global variable* called keys, *not* the shared class 
attribute Utility.keys. By design, attributes are not in the function 
scope. If you want to access an attribute, whether class or instance, you 
must always refer to them as attributes.


    def __init__(self):
        for section, keyList in  self.keys.items():  # this will work


>                 setattr(self, "get_%s" % key, self.get_value(section,
>                 key)) 
>                 setattr(self, "set_%s" % key, lambda
>                 value:self.set_value(section, key, value) )


What a mess. What is the purpose of this jumble of code?

My guess is that you are experienced with Java, and you are trying to 
adapt Java idioms and patterns to Python. Before you do this, you should 
read these two articles by a top Python developer who also knows Java 
backwards:

http://dirtsimple.org/2004/12/python-is-not-java.html
http://dirtsimple.org/2004/12/java-is-not-python-either.html



> if __name__ == "__main__":
>    utility = Utility()
>      print "key2: %s" % utility.get_def_key2() ## -> value return 100

Again, another SyntaxError. This can be fixed. But the next part cannot.

Except for two comments, 100 does not exist in your sample code. Python 
doesn't magically set values to 100. The code you give cannot possibly 
return 100 since nowhere in your code does it set anything to 100.

If you actually run the code you provide (after fixing the SyntaxErrors), 
you get this error:

py> utility = Utility()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __init__
NameError: global name 'keys' is not defined


If you fix that and try again, you get this error:

py> utility = Utility()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in __init__
TypeError: get_value() takes exactly 2 arguments (3 given)


The results you claim you get are not true.


Please read this page and then try again:

http://sscce.org/



-- 
Steven




More information about the Python-list mailing list