On 08/09/14 15:17, Juan Christian wrote:

Why normal attributes? Isn't it better to make these read-only as I won't
ever need to modify them? And even if I modify them, it won't change in the
Steam servers, only in my program, and I don't see any use for that, I need
the 'real' values always, the 'real' thing only.

Read only is not a good term for properties, they are not really read-only. You can still change the unmderlying attribute directly:

>>> class C:
...    def __init__(self,x):
...      self._x = x
...    @property
...    def x(self):
...      return self._x
...
>>> c = C(66)
>>> c.x
66
>>> c._x
66
>>> c.x = 22
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> c._x = 22
>>> c.x
22


Notice that although I can't set x, I can set _x!
And it 'changes' x.

The only thing that stops me is seeing the _x which
tells me I shouldn't be messing with it.

So in this scenario the property only buys you a tiny bit of protection, you are really still relying on the "We are all
consenting adults" philosophy of Python...

That's why we would normally only use normal attributes
unless the property needed some munging inside the
getter/setter method.

If you really really don't trust your clients not to mess
with _x then that's where you probably do need the __x version, combined with properties. which is where we came in! :-)
(And its still not 100% foolproof)

>>> class C:
...    def __init__(self,x):
...      self.__x = x
...    @property
...    def x(self):
...      return self.__x
...
>>> c = C(66)
>>> c.x
66
>>> c.__x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute '__x'
>>> c.x = 22
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> c.__x = 22
>>> c.x
66
>>> c.__x
22

Notice I can still set/read __x from the client,
but at least this time it does not change
the x property value...

>>> dir(c)
['_C__x', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '__x', 'x']
>>>

Notice dir() shows that you now have two __x attributes, the original name-mangled version and the new local 'c' instance version.

The only way to get total read-only working would be to write your own get attribute function - I think that is as near foolproof as you can get in Python.

Python doesn't really make this kind of data hiding easy, its just
not the Pythonic way. Python is not Java (or Smalltalk for that
matter).

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to