I am using SQLAlchemy on my new project and would like to use __slots__ with models (in beta version without alchemy, __slots__ were necessary because a large number of objects was created). But I am unable to combine them with SQLAlchemy declarations and get the following error for code:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class NotWorking(Base):
__tablename__ = 'table1'
pk = Column(Integer, primary_key=True)
name = Text(length=64, convert_unicode=True)
__slots__ = ['name', 'pk']
Error
ValueError: 'name' in __slots__ conflicts with class variable
Which is expected as __slots__ modify class to create descriptors for fields defined in them, so one workaround is to make hidden fields (_name) and make model fields act as properties as shown here:
class Working(Base):
__tablename__ = 'table2'
pk = Column(Integer, primary_key=True)
name = Text(length=64, convert_unicode=True)
__slots__ = ['_name', '_pk']
# Workaround
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
But this code can be a bit tedious to write and you need to add corresponding property for each new field. I am wondering, is there a better way to do without properties, while still using declarative base (without using Classical Mappings).
name = Text(length=64, convert_unicode=True)create the correct descriptor already? So you'd have__slots__ = ()to indicate there are no extra instance variables that need to be stored? - Tadhg McDonald-Jensen__slots__were intended to get decrease memory consumption, and maybe made object a bit more static, but (I found that after checking your comment) as Base does not define them, they are not exactly useful.__dict__still remains, and you can still add new fields, so they could only be used at most as a guideline. - jOOsko