Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Consider this code:

>>> class Foo():
        pass
...
>>> foo = Foo()
>>> foo.a = 'test'
>>> foo.a
'test'

One can just override __setattr__ to make attributes read only and prevent their creation at runtime, however:

  • Why is this the default Python behavior (any good reasons)?
  • Is there any practice to prevent this without altering each class?
  • Would you worry about this behavior in serious projects? don't you consider it error prone? or you can just ignore it (relying on new IDEs code completion)
share|improve this question
1  
What other default behaviour would you expect, and what consequences would it have for class definitions, in particular __init__? –  delnan Aug 31 '13 at 12:44
    
@delnan I would expect AttributeError: 'Foo' object has no attribute 'a' consequences may be in typing, you can for example type: foo.pasword = 'something' instead of foo.password = 'something' –  01walid Aug 31 '13 at 13:00
2  
@01walid: What delnan means is that there is no difference between self.a = 'test' in the __init__ method and foo.a on the instance. Both self and foo are just references to the instance. –  Martijn Pieters Aug 31 '13 at 13:02
    
Ok but, at least -for me- in __init__ you're still inside the class declaring its attributes, I'm asking why the same behavior outside the class definition as for an instance of it? –  01walid Aug 31 '13 at 13:13
2  
@01walid: You can define the __init__ outside the class and then add a reference to it to the class; it'll work just the same as if it was part of the class definition. Python is a highly dynamic language. –  Martijn Pieters Aug 31 '13 at 13:15

2 Answers 2

up vote 5 down vote accepted

As others already mentioned, preventing this would require a special case for __init__, and one of the design principles of Python is to avoid special cases, see the Zen of Python:

Special cases aren't special enough to break the rules.

This design is also in line with other design decisions, e.g, the lack of static type checking or access control modifiers. Python tends to empower its users, not to enforce things.

You can easily prevent this for any particular class by using __slots__. However, there is no way to change this globally.

While this can in theory cause errors, I wouldn't worry about it much. For example, a typo could mean that you are by accident create a new attribute when you meant to assign to an existing attribute. However, good unit testing coverage will usually catch this.

share|improve this answer

Would you worry about this behavior in serious projects? don't you consider it error prone? or you can just ignore it (relying on new IDEs code completion)

Yes, I worry. To me, it is not clear from the post whether you are pointing to the dangers of allowing outsiders to reason about and change the structure of the objects, or to the dangers of assigning to a previously undefined attribute. However, both behaviors are known to be problematic (the first, for sacrificing the benefits information hiding techniques bring to the table and relying on convention; the latter for allowing the spreading of definitions of structure/object when it is desired to have them locally organized).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.