Python Slots Property

Posted onby

slots provide a special mechanism to reduce the size of objects. It is especially useful if you need to allocate thousands of objects that would otherwise take lots of memory space. It is not very common but you may find it useful someday. Note, however, that it has some side effects (e.g. pickle may not work) and that Python 3 introduced memory optimisation on objects (sse http://www.python.org/dev/peps/pep-0412/) so slots may not be needed anymore ?

Using slots (only restricts setting arbitary attributes) Property Descriptor. Python ships with built in function called property. We can use this function to customize the way attributes be accessed and assigned. First I will explain you about property before I get you idea about how it is useful to make attribute readonly. 对于追求完美的Python程序员来说,这是必须要做到的! 还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属. This is from Python side. Did htslots field of PyHeapTypeObject does not contain properly calculated slot names? Looking at the code, it appears that htslots does.not. include inherited slots. Msg171902 - Author: Terry J. Reedy (terry.reedy). Date: 2012-10-03 19:02; As I understand it, var(ob) is pretty much a synonym for ob.dict. Hashes for dataslots-1.0.2-py2.py3-none-any.whl; Algorithm Hash digest; SHA256: 4fe302ab59c86e01a4fafe516776a198cd8a42dc696dcc9d525e2ec8ee0fe773: Copy. Organized Robbery George Bernard Shaw once said 'Property is organized robbery.' This is true in a very positive sense in Python as well: A property in Python 'robs' the necessity to need getters and setters for attributes and to make it possible to start with public attributes instead of having everything private!

The main idea is as follows. As you may know every object in Python contains a dynamic dictionary that allows adding attributes. You can see the slots as the static version that does not allow additional attributes.

Contents

  • slots
    • Quick Example

Here is the slots syntax uing the __slot__ keyword:

Class Property Python

The traditional version would be as follows:

This means that for every instance you’ll have an instance of a dict. Now, for some people this might seem way too much space for just a couple of attributes.

Unfortunately there is a side effect to slots. They change the behavior of the objects that have slots in a way that can be abused by control freaks and static typing weenies. This is bad, because the control freaks should be abusing the metaclasses and the static typing weenies should be abusing decorators, since in Python, there should be only one obvious way of doing something.

Making CPython smart enough to handle saving space without __slots__ is a major undertaking, which is probably why it is not on the list of changes for P3k (yet).

I’d like to see some elaboration on the “static typing”/decorator point, sans pejoratives. Quoting absent third parties is unhelpful. __slots__ doesn’t address the same issues as static typing. For example, in C++, it is not the declaration of a member variable is being restricted, it is the assignment of an unintended type (and compiler enforced) to that variable. I’m not condoning the use of __slots__, just interested in the conversation. Thanks! – hiwaylon Nov 28 ‘11 at 17:541

Each python object has a __dict__ atttribute which is a dictionary containing all other attributes. e.g. when you type self.attr python is actually doing self.__dict__[‘attr’]. As you can imagine using a dictionary to store attribute takes some extra space & time for accessing it.

However, when you use __slots__, any object created for that class won’t have a __dict__ attribute. Instead, all attribute access is done directly via pointers.

So if want a C style structure rather than a full fledged class you can use __slots__ for compacting size of the objects & reducing attribute access time. A good example is a Point class containing attributes x & y. If you are going to have a lot of points, you can try using __slots__ in order to conserve some memory.

No, an instance of a class with __slots__ defined is not like a C-style structure. There is a class-level dictionary mapping attribute names to indexes, otherwise the following would not be possible: class A(object): __slots__= “value”,nna=A(); setattr(a, ‘value’, 1) I really think this answer should be clarified (I can do that if you want). Also, I’m not certain that instance.__hidden_attributes[instance.__class__[attrname]] is faster than instance.__dict__[attrname]. – tzot Oct 15 ‘11 at 13:56up vote 4 down vote

Slots are very useful for library calls to eliminate the “named method dispatch” when making function calls. This is mentioned in the SWIG documentation. For high performance libraries that want to reduce function overhead for commonly called functions using slots is much faster.

SalePython slots property for saleSale

Now this may not be directly related to the OPs question. It is related more to building extensions than it does to using the slots syntax on an object. But it does help complete the picture for the usage of slots and some of the reasoning behind them.

By default, instances of both old and new-style classes have a dictionary for attribute storage. This wastes space for objects having very few instance variables. The space consumption can become acute when creating large numbers of instances.

The default can be overridden by defining __slots__ in a new-style class definition. The __slots__ declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__ is not created for each instance.

This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. If defined in a new-style class, __slots__ reserves space for the declared variables and prevents the automatic creation of __dict__ and __weakref__ for each instance. New in version 2.2.

Notes on using __slots__

Without a __dict__ variable, instances cannot be assigned new variables not listed in the __slots__ definition. Attempts to assign to an unlisted variable name raises AttributeError. If dynamic assignment of new variables is desired, then add ‘__dict__’ to the sequence of strings in the __slots__ declaration. Changed in version 2.3: Previously, adding ‘__dict__’ to the __slots__ declaration would not enable the assignment of new attributes not specifically listed in the sequence of instance variable names.

Without a __weakref__ variable for each instance, classes defining __slots__ do not support weak references to its instances. If weak reference support is needed, then add ‘__weakref__’ to the sequence of strings in the __slots__ declaration. Changed in version 2.3: Previously, adding ‘__weakref__’ to the __slots__ declaration would not enable support for weak references.

__slots__ are implemented at the class level by creating descriptors (3.4.2) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by __slots__; otherwise, the class attribute would overwrite the descriptor assignment.

If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its descriptor directly from the base class). This renders the meaning of the program undefined. In the future, a check may be added to prevent this.

Warning

effects of a __slots__ declaration is limited to the class where it is defined. In other words, subclasses will have a __dict__ (unless they also define __slots__).

__slots__ do not work for classes derived from ``variable-length’’ built-in types such as long, str and tuple.

Any non-string iterable may be assigned to __slots__. Mappings may also be used; however, in the future, special meaning may be assigned to the values corresponding to each key.

For every instance of any class, attributes are stored in a dictionary.

Python Slots Property

This means that for every instance you’ll have an instance of a dict. Now, for some people this might seem way too much space for just a couple of attributes.

If you have lots and lots and looooots of instances, and you want to save some memory, you can use __slots__. The basic idea is that when you define the __slots__ class attribute, those attributes will get just the enough space, without wasting space.

Monty Python Slot Machine App

Here is the previous example using __slots__:

Now, one side effect of these __slots__ thing is that, whenever you define the __slots__ class attribute, your __dict__ attribute for every instance will be gone!. It’s not a surprise because that’s why you should use __slots__ in the first place… to get rid off the __dict__ in every instance, to save some memory remember?Can’t bind attributes to the instance any more…

Another side effect is that, as there is no __dict__, there is no way to add, at runtime, any attributes to your instance:

# This should should work if there is no __slots__ defined...>>> instance.new_attr = 10Traceback (most recent call last):

File “<stdin>”, line 1, in <module>

AttributeError: ‘myClass’ object has no attribute ‘new_attr’>>>Read only attributes?

Another one is that, if there is some kind of collision between the slot and a class attribute, then the class attribute will overwrite the slot and, as there is no __dict__, the class attribute will be read-only.

Python Slots Property

However if you want to have a __dict__, you can always insert into the __slots__ the ‘__dict__’ value, and all these little side effects will go away

But what if I wanted to add the ‘__dict__’ value into __slots__ at runtime?

sorry dude but, no can do.

reference: http://mypythonnotes.wordpress.com/2008/09/04/__slots__/:wq

The following are the built-in features of the PythonQt library:

  • Access all slots, properties, children and registered enums of any QObject derived class from Python
  • Connecting Qt Signals to Python functions (both from within Python and from C++)
  • Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
  • Convenient conversions to/from QVariant for PythonQtObjectPtr.
  • Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
  • Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
  • StdOut/Err redirection to Qt signals instead of cout
  • Interface for creating your own import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
  • Mapping of plain-old-datatypes and ALL QVariant types to and from Python
  • Support for wrapping of user QVariant types which are registerd via QMetaType
  • Support for Qt namespace (with all enumerators)
  • All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
  • No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the moc)
  • Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
  • Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
  • Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
  • Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
  • Setting of dynamic QObject properties via setProperty(), dynamic properties can be accessed for reading and writing like normal Python attributes (but creating a new property needs to be done with setProperty(), to distinguish from normal Python attributes)
  • Support for QtCore.Signal, QtCore.Slot and QtCore.Property, including the creation of a dynamic QMetaObject.

PythonQt offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes. This offers the following features:

  • Complete Qt API wrapped and accessible
  • The following modules are available as submodules of the PythonQt module:
    • QtCore
    • QtGui
    • QtNetwork
    • QtOpenGL
    • QtSql
    • QtSvg
    • QtWebKit
    • QtXml
    • QtXmlPatterns
    • QtMultimedia
    • QtQml
    • QtQuick
  • Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
  • Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
  • Multiple inheritance support (e.g., QGraphicsTextItem is a QObject and a QGraphicsItem, PythonQt will handle this well)
  • QtQuick support is experimental and currently it is not possible to register new qml components from Python

PythonQt supports:

  • Python 2 (>= Python 2.6)
  • Python 3 (>= Python 3.3)
  • Qt 4.x (Qt 4.7 and Qt 4.8 recommended)
  • Qt 5.x (Tested with Qt 5.0, 5.3, 5.4 and 5.6)

The last working Qt4 version is available at svn branches/Qt4LastWorkingVersion or you can download the PythonQt 3.0 release. The current svn trunk no longer supports Qt4, since we started to make use of some Qt5-only features.

  • PythonQt is not as pythonic as PySide in many details (e.g. buffer protocol, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
  • PythonQt offers properties as Python attributes, while PySide offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PySide)
  • PythonQt currently does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
  • QObject.emit to emit Qt signals from Python is not yet implemented but PythonQt allows to just emit a signal by calling it like a normal slot
  • Ownership handling of objects is not as complete as in PySide and PySide, especially in situations where the ownership is not clearly passed to C++ on the C++ API.
  • QStrings are always converted to unicode Python objects, QByteArray always stays a QByteArray and can be converted using QByteArray.data()
  • Qt methods that take an extra 'bool* ok' parameter can be called passing PythonQt.BoolResult as parameter. In PySide, a tuple is returned instead.