Question about math.pi is mutable

Steven D'Aprano steve at pearwood.info
Fri Nov 6 21:00:31 EST 2015


On Sat, 7 Nov 2015 09:19 am, Thomas 'PointedEars' Lahn wrote:

> It is certainly possible for attributes of (instances of) new-style
> classes (starting with Python 3.2 at the latest) to be read-only by
> declaring them a property that does not have a setter, or one that has a
> setter that throws a specific exception (here: the former):
> 
> #--------------------------
> class SafeMath(object):
>     def __init__ (self):
>         from math import pi
>         self._pi = pi
>     
>     @property
>     def pi (self):
>         return self._pi

The obvious problem with that is that it is trivially easy for the coder to
set self._pi to change the value of self.pi.

Here's a version that at first seems promising:

py> def builder():
...     from math import pi as PI
...     def pi(self):
...             return PI
...     return pi
...
py> class MathLib(object):
...     pi = property(builder())
...
py> mathlib = MathLib()
py> mathlib.pi
3.141592653589793
py> mathlib.pi = 3.12
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

There's no _pi accessible that somebody might change. If you dig into the
property object itself, you eventually get to the cell object containing
the value for pi:

py> MathLib.pi.fget.__closure__[0]
<cell at 0xb7bd5134: float object at 0xb7be5c30>

but there doesn't appear to be any way to manipulate the cell internals to
change the value. But you don't need to:

py> MathLib.pi = property(lambda self: 4.2)
py> mathlib.pi
4.2


A determined coder can change nearly anything done in pure Python code.

*Personally*, I too would like Python to have some equivalent of (say)
Pascal `const`, names which cannot be rebound once assigned to the first
time. Not to prevent determined coders from changing things, but to avoid
*accidental* changes done in error.



-- 
Steven




More information about the Python-list mailing list