There was recently a short discussion about some way to make certain initialization of instances easier (less typing). This was then followed by an expression of a desire for the automatic generation of the slots attribute for classes (which is generally painful to do by hand for any nontrivial class). What is a descriptor in Python? Before we talk about descriptor, we should understand the default behaviour of accessing attributes in Python. When you do article.writer, Python will call the method getattribute, where it does a look up in dict, self.dict'writer' and return the value.
Released:
Decorator to add __slots__ in dataclasses
Project description
Decorator for adding slots
Python3.7 provides dataclasses module for faster class creation (PEP 557).Unfortunately there's no support for __slots__. If you want to create more memory efficient instances, you need todo it by yourself or use dataslots.dataslots decorator.
Usage
Simple example
Inheritance
As described in docs, in derived class __dict__ is created, because base class does not have __slots__.Slots are created from all defined properties (returned by dataclasses.fields() function).
Dynamic assignment of new variables
Weakref
Read-only class variables
With __slots__ it's possible to define read-only class variables. When using dataclasses you cannot provide typefor attribute or use typing.ClassVar to declare one.
Pickling frozen dataclass
Because of an issue 36424 you need custom __setstate__ method. In dataslots there isimplemented default version and it is used if decorated class has no __getstate__ and __setstate__ function declared.
More about __slots__
Release historyRelease notifications | RSS feed
1.0.2
1.0.2rc2 pre-release
1.0.1
1.0.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size dataslots-1.0.2-py2.py3-none-any.whl (4.1 kB) | File type Wheel | Python version py2.py3 | Upload date | Hashes |
Filename, size dataslots-1.0.2.tar.gz (7.5 kB) | File type Source | Python version None | Upload date | Hashes |
Hashes for dataslots-1.0.2-py2.py3-none-any.whl
Algorithm | Hash digest |
---|---|
SHA256 | 4fe302ab59c86e01a4fafe516776a198cd8a42dc696dcc9d525e2ec8ee0fe773 |
MD5 | aa8075201eba64938a16361e741a901b |
BLAKE2-256 | b2b22f9f4ea849a076effa673dd9b7e67bedb9358ad0875c30cd4ae0ad6298bc |
Hashes for dataslots-1.0.2.tar.gz
Algorithm | Hash digest |
---|---|
SHA256 | 0dfc4d12aab104b00ddb88a585c0a2227bbb9bd19c785dc8068b43eb0d6009e1 |
MD5 | 656b169564c8623fe9a97aa5f25df7fd |
BLAKE2-256 | a81ca45405ae05d585b786e1819a3406310a097ffd7bf5f104e7c78e63cb86a8 |
Next Chapter: Implementing a Property Decorator
Properties vs. Getters and Setters
Properties
Getters(also known as 'accessors') and setters (aka. 'mutators') are used in many object oriented programming languages to ensure the principle of data encapsulation. Data encapsulation - as we have learnt in our introduction on Object Oriented Programming of our tutorial - is seen as the bundling of data with the methods that operate on them. These methods are of course the getter for retrieving the data and the setter for changing the data. According to this principle, the attributes of a class are made private to hide and protect them from the other codes.
Unfortunately, it is widespread belief that a proper Python class should encapsulate private attributes by using getters and setters. As soon as one of these programmers introduces a new attribute, he or she will make it a private variable and creates 'automatically' a getter and a setter for this attributes. Such programmers may even use an editor or an IDE, which automatically creates getters and setters for all private attributes. These tools even warn the programmer if she or he uses a public attribute! Java programmers will wrinkle their brows, screw up their noses, or even scream with horror when they read the following: The Pythonic way to introduce attributes is to make them public.
We will explain this later. First, we demonstrate in the following example, how we can design a class in a Javaesque way with getters and setters to encapsulate the private attribute self.__x
:
We can see in the following demo session how to work with this class and the methods:
What do you think about the expression 'p1.set_x(p1.get_x()+p2.get_x())'? It's ugly, isn't it? It's a lot easier to write an expression like the following, if we had a public attribute x:
Such an assignment is easier to write and above all easier to read than the Javaesque expression.
Let's rewrite the class P in a Pythonic way. No getter, no setter and instead of the private attribute self.__x
we use a public one:
Beautiful, isn't it? Just three lines of code, if we don't count the blank line!
'But, but, but, but, but .. ', we can hear them howling and screaming, 'But there is NO data ENCAPSULATION!'Yes, in this case there is no data encapsulation. We don't need it in this case. The only thing get_x and set_x in our starting example did was 'getting the data through' without doing anything.
But what happens if we want to change the implementation in the future? This is a serious argument. Let's assume we want to change the implementation like this: The attribute x can have values between 0 and 1000. If a value larger than 1000 is assigned, x should be set to 1000. Correspondingly, x should be set to 0, if the value is less than 0.
It is easy to change our first P class to cover this problem. We change the set_x method accordingly:
Python Get Attributes Of Class
The following Python session shows that it works the way we want it to work:
But there is a catch: Let's assume we designed our class with the public attribute and no methods. People have already used it a lot and they have written code like this:
Our new class means breaking the interface. The attribute x is not available anymore. That's why in Java e.g. people are recommended to use only private attributes with getters and setters, so that they can change the implementation without having to change the interface.
But Python offers a solution to this problem. The solution is called properties!
The class with a property looks like this:
A method which is used for getting a value is decorated with '@property', i.e. we put this line directly in front of the header. The method which has to function as the setter is decorated with '@x.setter'. If the function had been called 'f', we would have to decorate it with '@f.setter'.Two things are noteworthy: We just put the code line 'self.x = x' in the __init__
method and the property method x is used to check the limits of the values. The second interesting thing is that we wrote 'two' methods with the same name and a different number of parameters 'def x(self)' and 'def x(self,x)'. We have learned in a previous chapter of our course that this is not possible. It works here due to the decorating:
Alternatively, we could have used a different syntax without decorators to define the property. As you can see, the code is definitely less elegant and we have to make sure that we use the getter function in the __init__
method again:
There is still another problem in the most recent version. We have now two ways to access or change the value of x: Either by using 'p1.x = 42' or by 'p1.set_x(42)'. This way we are violating one of the fundamentals of Python: 'There should be one-- and preferably only one --obvious way to do it.' (see Zen of Python)
We can easily fix this problem by turning the getter and the setter methods into private methods, which can't be accessed anymore by the users of our class P:
Even though we fixed this problem by using a private getter and setter, the version with the decorator '@property' is the Pythonic way to do it!
From what we have written so far, and what can be seen in other books and tutorials as well, we could easily get the impression that there is a one-to-one connection between properties (or mutator methods) and the attributes, i.e. that each attribute has or should have its own property (or getter-setter-pair) and the other way around. Even in other object oriented languages than Python, it's usually not a good idea to implement a class like that. The main reason is that many attributes are only internally needed and creating interfaces for the user of the class increases unnecessarily the usability of the class. The possible user of a class shouldn't be 'drowned' with umpteen - of mainly unnecessary - methods or properties!
The following example shows a class, which has internal attributes, which can't be accessed from outside. These are the private attributes self.__potential
_physical
and self.__potential_psychic
. Furthermore we show that a property can be deduced from the values of more than one attribute. The property 'condition' of our example returns the condition of the robot in a descriptive string. The condition depends on the sum of the values of the psychic and the physical conditions of the robot.
Public instead of Private Attributes
Let's summarize the usage of private and public attributes, getters and setters, and properties: Let's assume that we are designing a new class and we pondering about an instance or class attribute 'OurAtt', which we need for the design of our class. We have to observe the following issues:
- Will the value of 'OurAtt' be needed by the possible users of our class?
- If not, we can or should make it a private attribute.
- If it has to be accessed, we make it accessible as a public attribute
- We will define it as a private attribute with the corresponding property, if and only if we have to do some checks or transformation of the data. (As an example, you can have a look again at our class P, where the attribute has to be in the interval between 0 and 1000, which is ensured by the property 'x')
- Alternatively, you could use a getter and a setter, but using a property is the Pythonic way to deal with it!
Let's assume we defined 'OurAtt' as a public attribute. Our class has been successfully used by other users for quite a while. Now comes the point which frightens some traditional OOPistas out of their wits: Imagine 'OurAtt' has been used as an integer. Now, our class has to ensure that 'OurAtt' has to be a value between 0 and 1000? Without property, this is really a horrible scenario! Due to properties it's easy: We create a property version of 'OurAtt'.
This is great, isn't it? You can start with the simplest implementation imaginable, and you are free to later migrate to a property version without having to change the interface! So properties are not just a replacement for getters and setters!
Slot props allow us to turn slots into reusable templates that can render different content based on input props. This is most useful when you are designing a reusable component that encapsulates data logic while allowing the consuming parent component to customize part of its layout. Vue pass props to slot. In Vue, can I define props for the slot in a component, so that the slotted component has access to them? 1 Correct way to pass props to all children through slot-scope in Vue.js.
Something else you might have already noticed: For the users of a class, properties are syntactically identical to ordinary attributes.
Released:
Decorator to add __slots__ in dataclasses
Project description
Decorator for adding slots
Python3.7 provides dataclasses module for faster class creation (PEP 557).Unfortunately there's no support for __slots__. If you want to create more memory efficient instances, you need todo it by yourself or use dataslots.dataslots decorator.
Usage
Simple example
Inheritance
As described in docs, in derived class __dict__ is created, because base class does not have __slots__.Slots are created from all defined properties (returned by dataclasses.fields() function).
Dynamic assignment of new variables
Weakref
Read-only class variables
With __slots__ it's possible to define read-only class variables. When using dataclasses you cannot provide typefor attribute or use typing.ClassVar to declare one.
Pickling frozen dataclass
Because of an issue 36424 you need custom __setstate__ method. In dataslots there isimplemented default version and it is used if decorated class has no __getstate__ and __setstate__ function declared.
More about __slots__
Release historyRelease notifications | RSS feed
1.0.2
1.0.2rc2 pre-release
1.0.1
1.0.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size dataslots-1.0.2-py2.py3-none-any.whl (4.1 kB) | File type Wheel | Python version py2.py3 | Upload date | Hashes |
Filename, size dataslots-1.0.2.tar.gz (7.5 kB) | File type Source | Python version None | Upload date | Hashes |
Hashes for dataslots-1.0.2-py2.py3-none-any.whl
Algorithm | Hash digest |
---|---|
SHA256 | 4fe302ab59c86e01a4fafe516776a198cd8a42dc696dcc9d525e2ec8ee0fe773 |
MD5 | aa8075201eba64938a16361e741a901b |
BLAKE2-256 | b2b22f9f4ea849a076effa673dd9b7e67bedb9358ad0875c30cd4ae0ad6298bc |
Hashes for dataslots-1.0.2.tar.gz
Algorithm | Hash digest |
---|---|
SHA256 | 0dfc4d12aab104b00ddb88a585c0a2227bbb9bd19c785dc8068b43eb0d6009e1 |
MD5 | 656b169564c8623fe9a97aa5f25df7fd |
BLAKE2-256 | a81ca45405ae05d585b786e1819a3406310a097ffd7bf5f104e7c78e63cb86a8 |
Next Chapter: Implementing a Property Decorator
Properties vs. Getters and Setters
Properties
Getters(also known as 'accessors') and setters (aka. 'mutators') are used in many object oriented programming languages to ensure the principle of data encapsulation. Data encapsulation - as we have learnt in our introduction on Object Oriented Programming of our tutorial - is seen as the bundling of data with the methods that operate on them. These methods are of course the getter for retrieving the data and the setter for changing the data. According to this principle, the attributes of a class are made private to hide and protect them from the other codes.
Unfortunately, it is widespread belief that a proper Python class should encapsulate private attributes by using getters and setters. As soon as one of these programmers introduces a new attribute, he or she will make it a private variable and creates 'automatically' a getter and a setter for this attributes. Such programmers may even use an editor or an IDE, which automatically creates getters and setters for all private attributes. These tools even warn the programmer if she or he uses a public attribute! Java programmers will wrinkle their brows, screw up their noses, or even scream with horror when they read the following: The Pythonic way to introduce attributes is to make them public.
We will explain this later. First, we demonstrate in the following example, how we can design a class in a Javaesque way with getters and setters to encapsulate the private attribute self.__x
:
We can see in the following demo session how to work with this class and the methods:
What do you think about the expression 'p1.set_x(p1.get_x()+p2.get_x())'? It's ugly, isn't it? It's a lot easier to write an expression like the following, if we had a public attribute x:
Such an assignment is easier to write and above all easier to read than the Javaesque expression.
Let's rewrite the class P in a Pythonic way. No getter, no setter and instead of the private attribute self.__x
we use a public one:
Beautiful, isn't it? Just three lines of code, if we don't count the blank line!
'But, but, but, but, but .. ', we can hear them howling and screaming, 'But there is NO data ENCAPSULATION!'Yes, in this case there is no data encapsulation. We don't need it in this case. The only thing get_x and set_x in our starting example did was 'getting the data through' without doing anything.
But what happens if we want to change the implementation in the future? This is a serious argument. Let's assume we want to change the implementation like this: The attribute x can have values between 0 and 1000. If a value larger than 1000 is assigned, x should be set to 1000. Correspondingly, x should be set to 0, if the value is less than 0.
It is easy to change our first P class to cover this problem. We change the set_x method accordingly:
Python Get Attributes Of Class
The following Python session shows that it works the way we want it to work:
But there is a catch: Let's assume we designed our class with the public attribute and no methods. People have already used it a lot and they have written code like this:
Our new class means breaking the interface. The attribute x is not available anymore. That's why in Java e.g. people are recommended to use only private attributes with getters and setters, so that they can change the implementation without having to change the interface.
But Python offers a solution to this problem. The solution is called properties!
The class with a property looks like this:
A method which is used for getting a value is decorated with '@property', i.e. we put this line directly in front of the header. The method which has to function as the setter is decorated with '@x.setter'. If the function had been called 'f', we would have to decorate it with '@f.setter'.Two things are noteworthy: We just put the code line 'self.x = x' in the __init__
method and the property method x is used to check the limits of the values. The second interesting thing is that we wrote 'two' methods with the same name and a different number of parameters 'def x(self)' and 'def x(self,x)'. We have learned in a previous chapter of our course that this is not possible. It works here due to the decorating:
Alternatively, we could have used a different syntax without decorators to define the property. As you can see, the code is definitely less elegant and we have to make sure that we use the getter function in the __init__
method again:
There is still another problem in the most recent version. We have now two ways to access or change the value of x: Either by using 'p1.x = 42' or by 'p1.set_x(42)'. This way we are violating one of the fundamentals of Python: 'There should be one-- and preferably only one --obvious way to do it.' (see Zen of Python)
We can easily fix this problem by turning the getter and the setter methods into private methods, which can't be accessed anymore by the users of our class P:
Even though we fixed this problem by using a private getter and setter, the version with the decorator '@property' is the Pythonic way to do it!
From what we have written so far, and what can be seen in other books and tutorials as well, we could easily get the impression that there is a one-to-one connection between properties (or mutator methods) and the attributes, i.e. that each attribute has or should have its own property (or getter-setter-pair) and the other way around. Even in other object oriented languages than Python, it's usually not a good idea to implement a class like that. The main reason is that many attributes are only internally needed and creating interfaces for the user of the class increases unnecessarily the usability of the class. The possible user of a class shouldn't be 'drowned' with umpteen - of mainly unnecessary - methods or properties!
The following example shows a class, which has internal attributes, which can't be accessed from outside. These are the private attributes self.__potential
_physical
and self.__potential_psychic
. Furthermore we show that a property can be deduced from the values of more than one attribute. The property 'condition' of our example returns the condition of the robot in a descriptive string. The condition depends on the sum of the values of the psychic and the physical conditions of the robot.
Public instead of Private Attributes
Let's summarize the usage of private and public attributes, getters and setters, and properties: Let's assume that we are designing a new class and we pondering about an instance or class attribute 'OurAtt', which we need for the design of our class. We have to observe the following issues:
- Will the value of 'OurAtt' be needed by the possible users of our class?
- If not, we can or should make it a private attribute.
- If it has to be accessed, we make it accessible as a public attribute
- We will define it as a private attribute with the corresponding property, if and only if we have to do some checks or transformation of the data. (As an example, you can have a look again at our class P, where the attribute has to be in the interval between 0 and 1000, which is ensured by the property 'x')
- Alternatively, you could use a getter and a setter, but using a property is the Pythonic way to deal with it!
Let's assume we defined 'OurAtt' as a public attribute. Our class has been successfully used by other users for quite a while. Now comes the point which frightens some traditional OOPistas out of their wits: Imagine 'OurAtt' has been used as an integer. Now, our class has to ensure that 'OurAtt' has to be a value between 0 and 1000? Without property, this is really a horrible scenario! Due to properties it's easy: We create a property version of 'OurAtt'.
This is great, isn't it? You can start with the simplest implementation imaginable, and you are free to later migrate to a property version without having to change the interface! So properties are not just a replacement for getters and setters!
Slot props allow us to turn slots into reusable templates that can render different content based on input props. This is most useful when you are designing a reusable component that encapsulates data logic while allowing the consuming parent component to customize part of its layout. Vue pass props to slot. In Vue, can I define props for the slot in a component, so that the slotted component has access to them? 1 Correct way to pass props to all children through slot-scope in Vue.js.
Something else you might have already noticed: For the users of a class, properties are syntactically identical to ordinary attributes.
Next Chapter: Implementing a Property Decorator