Not possible to hide local variables

Chris Angelico rosuav at gmail.com
Tue Apr 28 04:06:21 EDT 2015


On Tue, Apr 28, 2015 at 5:33 PM, Cecil Westerhof <Cecil at decebal.nl> wrote:
> If I remember correctly you can not hide variables of a class or make
> them read-only?
>
> I want to rewrite my moving average to python. The init is:
>     def __init__(self, length):
>         if type(length) != int:
>             raise ParameterError, 'Parameter has to be an int'
>         if n < 0:
>             raise ValueError, 'Parameter should be greater or equal 2'
>         self.length             = length
>         self.old_values         = []
>         self.current_total      = 0
>
> But when someone changes length, old_values, or current_total that
> would wreck havoc with my class instance. What is the best way to
> handle this?

If you simply want them to never change them, but they may look at
them, the best option is to do nothing. It's no different from
anything else they might do; for instance, someone might inject a new
'type' into your namespace, and completely break your check. (More on
that later.) If they aren't meant to look at _or_ change them, what
you could do is name them "_length" and so on - a single leading
underscore is a signal that this is a private implementation detail,
not to be changed or viewed. But you can't stop people from messing
you up. You can't stop people from playing around with ctypes and
changing the value of 0 (and yes, that is possible - it'll probably
crash Python sooner or later though!). None of that is your problem.

In fact, it's not really your problem if someone gives you a length
that isn't a simple integer. In the first place, they might give you a
subclass of int, so a better check would be this:

if not isinstance(length, int):
    raise ValueError("length should be integral")

(note that I'm avoiding the multiple-argument syntax which doesn't
work in Python 3; if ParameterError is a subclass of ValueError you
could use that instead, but ValueError works)

You don't even need to check that it's an integer. If you get
something that can't be compared against 0, they'll get an instant
exception; otherwise, the exception might come up later. But it's
still not your problem. You could skip the nonnegativity check too,
but that's good documentation. (I'm assuming that ought to be checking
'length', as there is no 'n' in your example.)

So here's how I'd write that function:

    def __init__(self, length):
        if length < 0:
            raise ValueError("Length should be non-negative")
        self.length = length
        self.old_values = []
        self.current_total = 0

If someone changes them... not your problem. Life's so easy when you
don't have to worry!

ChrisA



More information about the Python-list mailing list