Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python, __slots__, and "attribute is read-only"

Tags:

I want to create an object in python that has a few attributes and I want to protect myself from accidentally using the wrong attribute name. The code is as follows:

class MyClass( object ) :     m = None # my attribute     __slots__ = ( "m" ) # ensure that object has no _m etc  a = MyClass() # create one a.m = "?"  # here is a PROBLEM 

But after running this simple code, I get a very strange error:

Traceback (most recent call last):   File "test.py", line 8, in <module>     a.m = "?" AttributeError: 'test' object attribute 'm' is read-only 

Is there any wise programmer who can spare a bit of their time and enlighten me about "read-only" errors?

like image 221
grigoryvp Avatar asked May 04 '09 15:05

grigoryvp


People also ask

What does __ slots __ mean in Python?

The special attribute __slots__ allows you to explicitly state which instance attributes you expect your object instances to have, with the expected results: faster attribute access.

What is read only attribute in Python?

To define a readonly property, you need to create a property with only the getter. However, it is not truly read-only because you can always access the underlying attribute and change it. The read-only properties are useful in some cases such as for computed properties. This code works perfectly fine.

How do slots work Python?

slots provide a special mechanism to reduce the size of objects.It is a concept of memory optimisation on objects. As every object in Python contains a dynamic dictionary that allows adding attributes. For every instance object, we will have an instance of a dictionary that consumes more space and wastes a lot of RAM.

Should I use slots Python?

Why Use `__slots__`? The short answer is slots are more efficient in terms of memory space and speed of access, and a bit safer than the default Python method of data access. By default, when Python creates a new instance of a class, it creates a __dict__ attribute for the class.


1 Answers

When you declare instance variables using __slots__, Python creates a descriptor object as a class variable with the same name. In your case, this descriptor is overwritten by the class variable m that you are defining at the following line:

  m = None # my attribute 

Here is what you need to do: Do not define a class variable called m, and initialize the instance variable m in the __init__ method.

class MyClass(object):   __slots__ = ("m",)   def __init__(self):     self.m = None  a = MyClass() a.m = "?" 

As a side note, tuples with single elements need a comma after the element. Both work in your code because __slots__ accepts a single string or an iterable/sequence of strings. In general, to define a tuple containing the element 1, use (1,) or 1, and not (1).

like image 101
Ayman Hourieh Avatar answered Oct 02 '22 04:10

Ayman Hourieh