Python: immutable private class variables?

Is there a way to translate this Java code in Python?

class Foo { final static private List<Thingy> thingies = ImmutableList.of(thing1, thing2, thing3); } 

eg. thingies is an immutable thingies private object list that belongs to the Foo class, not its instance.

I know how to define class static variables from this question Static class variables in Python , but I don't know how to make them immutable and private.

+7
source share
4 answers

You cannot do any of these things in Python, but not in the sense that you do them in Java. Anyway.

By convention, underlined prefix names are considered private and should not be accessible outside the implementation, but nothing in Python applies this convention. He looked at more warnings that you were bothering with implementation details that could change without warning in a future version of the code.

+8
source

In Python, the convention should use the _ prefix for attribute names, which means protected and the __ prefix for private . This language is not respected by the language; programmers are expected to not write code based on non-public data.

If you really want to ensure immutability, you can use the metaclass [ docs ] (class of the class). Just change __setattr__ and __delattr__ to raise exceptions when someone tries to change it, and make it tuple (immutable list) [ docs ] .

 class FooMeta(type): """A type whose .thingies attribute can't be modified.""" def __setattr__(cls, name, value): if name == "thingies": raise AttributeError("Cannot modify .thingies") else: return type.__setattr__(cls, name, value) def __delattr__(cls, name): if name == "thingies": raise AttributeError("Cannot delete .thingies") else: return type.__delattr__(cls, name) thing1, thing2, thing3 = range(3) class Foo(object): __metaclass__ = FooMeta thingies = (thing1, thing2, thing3) other = [1, 2, 3] 

Examples

 print Foo.thingies # prints "(0, 1, 2)" Foo.thingies = (1, 2) # raises an AttributeError del Foo.thingies # raise an AttributeError 
 Foo.other = Foo.other + [4] # no exception print Foo.other # prints "[1, 2, 3, 4]" 

It would still be technically possible to change them by going through the inner class of .__dict__ class attributes, but this should be enough to hold most users, it is very difficult to completely protect Python objects.

+14
source

You can make it non-writable (subtly different from immutable) using properties, but there is no way to make it private - this contradicts the Python philosophy.

 class Foo(object): # don't need 'object' in Python 3 @property def thingies(self): return 'thing1', 'thing2', 'thing3' f = Foo() print f.thingies #('thing1', 'thing2', 'thing3') f.thingies = 9 #Traceback (most recent call last): # File "test.py", line 8, in <module> # f.thingies = 9 #AttributeError: can't set attribute 

Whether it is immutable or not depends on what you return; if you return a mutable object, you can mutate it so that these changes appear in the instance / class.

 class FooMutable(object): _thingies = [1, 2, 3] @property def thingies(self): return self._thingies foo = FooMutable() foo.thingies.append(4) print foo.thingies # [1, 2, 3, 4] 

This will allow you to mutate thingies , and since the returned object is the same object stored in the instance / class, the changes will be reflected on subsequent access.

Compare this to:

 class FooMutable(object): @property def thingies(self): return [1, 2, 3] foo = FooMutable() foo.thingies.append(4) print foo.thingies # [1, 2, 3] 

Since the new list is returned every time, changes to it are not reflected in subsequent calls.

+5
source

You want to look into the property() function. It allows you to define your own custom Getter and Setter methods for the element attribute for the class. It might look something like this:

 class myClass(object): _x = "Hard Coded Value" def set_x(self, val): return def get_x(self): return self._x def del_x(self): return x = property(get_x, set_x, del_x, "I'm an immutable property named 'x'") 

I have not used it enough to make sure that it can be used to create something "private", so you have to delve into it yourself, but isinstance can help.

+1
source

All Articles