-
Website
http://blog.tplus1.com/ -
Original page
http://blog.tplus1.com/index.php/2009/03/24/instead-of-setting-instance-attributes-within-__init__/ -
Subscribe
All Comments -
Community
-
Top Commenters
-
Aaron Oliver
13 comments · 4 points
-
Michael Foord
3 comments · 7 points
-
holgerkrekel
2 comments · 1 points
-
beza1e1
1 comment · 1 points
-
Doug Hellmann
6 comments · 3 points
-
-
Popular Threads
-
Add an option for your script to drop into the debugger
1 day ago · 1 comment
-
Add an option for your script to drop into the debugger
In my opinion, __init__ is for initializing stuff, so what's wrong with initializing instance attributes there? Seems to me that your way abstracts that in the sense that it takes what would I would normally look for in __init__ and put it somewhere else.. Just a thought that I'm sure you've had already :)
You can always break up the argument parsing bit from the default values bit with a comment.
Simon Hibbs
Every property takes 5 lines instead of 1? And you were worried about length???
You could call a separate method from init to do the setting.
- Paddy.
>>> class D(object):
... @property
... def a(self):
... if not hasattr(self, 'a'):
... self.a =1
...
>>>
>>> d = D()
>>> print d.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in a
AttributeError: can't set attribute
>>>
"Perl's approach to object oriented is almost excessively Perlish: there are far too many ways to do it....
There are just so many possible combinations of implementation, structure, and semantics that it's quite rare
to find two unrelated class hierarchies that use precisely the same style of Perl OO."
http://misko.hevery.com/code-reviewers-guide/fl...
I'm not saying this is always the best solution, but do find that when I think about this while wanting to do real work in __init__() often I find an alternative way of doing things that's rather elegant. And the line of what "real" work is can be quite fine too sometimes.
Oh, I also agree with the comments about properties taking up so many more lines.
Also, are you sure you're not getting a loop in that 'a' method? The first time you actually access the property it should loop and eventually bail with an error. [I just tried it - it quits after 999 recursive calls and raises an AttributeError]
class D(object):
__slots__ = ('a', 'b')
def __init__(self, attr_defaults={'a': 1,'b': 2}):
[setattr(self, key, value) for key, value in attr_defaults.items()]
...seems to me to retain readability, although it's not the usual way of doing things.
>>>class D(object):
... __slots__ = ('a', 'b')
... def __init__(self, attr_defaults={'a': 1,'b': 2}):
... [setattr(self, key, value) for key, value in attr_defaults.items()]
class C(object):
a = 1
b = 2
def __init__(self):
# Init code goes here
class Test:
def __getattr__(self,attr):
self.__dict__[attr] = 1
return self.__dict__[attr]
def __init_vars(self):
self.a=1
self.b=2
and call that from the __init__ function.
In both cases I would worry about tools not understanding what is going on. Pulling the variable initialization out of the __init__ function will fool programs like pylint and doxygen.
I would probably just create sections in my __init__ like:
def __init(self):
#
# Variable
#
self.a=1
self.b=2
#
# Object setup
#
do interesting stuff here
But then again I do a lot of support programming and I like boring simple programs. They make it easier for me to understand.
>>> class C(object):
...
... @property
... def a(self):
... try:
... self._a
... except AttributeError:
... # Do possibly expensive stuff here
... self._a = <result of possibly expensive stuff>
... return self._a
I think this has better performance than using hasattr. Also, I wonder if having a @property and instance variable with the same name would cause problems somewhere; that's why I use `_a`.
Note: I didn't read other comments first. Sorry for any repetition.
............@property
............def a(self):
................try:
....................self._a
................except AttributeError:
....................# Do possibly expensive stuff here
....................self._a = <result of possibly expensive stuff>
................return self._a
Another problem is you've defined only a read-only property: the decorator wraps the getter, but the property has no setter (or deleter or docstring).
The above just looks like a mess!
from enthought.traits.api import HasTraits, Float
class MyClass(HasTraits):
a = Float(1.234) #default value declared statically
class AnotherClass(HasTraits):
a = Float()
def _a_default(self): #dynamic init setup using naming convention
return 1.234
for the later, the 'a' attribute is calculated on demand.
Traits also does runtime type checking, notification, delegation and GUI-generation. There are also Property traits which are cacheable and handle depenencies. There are predefined traits for all the standard types and you can subclass your own.
class MyClass(HasTraits):
....a = Float(1.234) #default value declared statically
.
.
class AnotherClass(HasTraits):
....a = Float()
....def _a_default(self): #dynamic init setup using naming convention
........return 1.234