A simple, fast, typed, and tested abstract and base classes for a python3.6+ Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor.
Project description
base-descriptor
A simple, fast, typed, and tested abstract and base classes for a python3.6+ Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor. The goal is to aid in the creation of descriptors allowing other developers to make descriptors for their own use case.
Key Features:
- Easy: Flexable and easy to inherit the prebuilt Non Data Descriptors, Data Descriptors, and Slottable Data Descriptors to create your own descriptors.
- Great Developer Experience: Being fully typed makes it great for editor support.
- Fully Tested: Our test suit fully tests the functionality to ensure that all of the classes in this module run as expected.
Installation
pip install base-descriptor
Table of Contents
- Objects Provided in this Module
- Non Data Descriptor Examples
- Data Descriptor Examples
- Slottable Data Descriptors
- References
Objects Provided in this Module
Non Data Descriptors
A non-data descriptor in Python is a type of descriptor that only implements
the __get__()
method. Descriptors are a way to customize attribute access in
Python. When an attribute is
accessed on an object, Python checks if a descriptor exists for that attribute
in the class or its ancestors. If found, the descriptor's __get__()
method is
called to determine the final
value of the attribute.
Class | Description |
---|---|
AbstractNonDataDescriptor |
Abstract Base Class for creating Non Data Descriptors. |
Data Descriptors
A data descriptor in Python is a type of descriptor that implements
both __get__()
and either __set__()
or __delete__()
. Data descriptors
allow you to define custom behavior for
attribute
access, including setting or deleting the attribute in addition to retrieving
its value.
Class | Description |
---|---|
AbstractDataDescriptor |
Abstract Base Class for creating Data Descriptors. |
BaseDataDescriptor |
Base Class for creating Data Descriptors. Provides the same functionality as a standard attribute. |
DefaultDescriptor |
A Data Descriptor that has a default value. |
ReadOnly |
A Data Descriptor that is read only. |
Slottable Data Descriptors
A Data Descriptor that plays well with __slots__
. This module was inspired by
Dr. Fred Baptiste fbaptiste.
The slottable data descriptor has the following advantages:
- Has instance specific storage
- Does not use the instance for storage, thus works with slots.
__slots__ = "__weakref__"
must be set. - Handles non hashable instances
- Data storage is clean.
Class | Description |
---|---|
AbstractSlottableDataDescriptor |
Abstract Base Class for creating Slottable Data Descriptors. |
BaseSlottableDataDescriptor |
Base Class for creating Slottable Data Descriptors. Provides the same functionality as a standard attribute. |
SlottableDefaultDescriptor |
A Slottable Data Descriptor that has a default value. |
Non Data Descriptor Examples
AbstractNonDataDescriptor
Simple way to Inherit from AbstractNonDataDescriptor
to create your own Non
Data Descriptor.
from base_descriptor import AbstractNonDataDescriptor
class SquareDescriptor(AbstractNonDataDescriptor):
def __get__(self, instance, owner=None):
if instance is None:
# Access through the class, return the descriptor itself
return self
return instance._value ** 2
class MyClass:
square = SquareDescriptor()
def __init__(self, value):
self._value = value
# Create an instance of MyClass
my_instance = MyClass(5)
# Access the square attribute using the descriptor
# This will calculate and return the square
print(my_instance.square) # 25
Data Descriptor Examples
ReadOnly
from base_descriptor import ReadOnly
class Person:
name = ReadOnly("Guido")
person = Person()
print(person.name) # Guido
person.name = "Raymond" # raises AttributeError
DefaultDescriptor
Default Descriptor that provides a default value for the attribute.
from base_descriptor import DefaultDescriptor
class Person:
name = DefaultDescriptor(default="Guido")
print(Person.name) # <data_descriptor.DefaultDescriptor object at ...>
person = Person()
print(person.name) # Guido
person.name = "Raymond"
print(person.name) # Raymond
BaseDataDescriptor
Provides the same functionality as a standard attribute.
It enables you to create your own Data Descriptor by overriding
the __set_name__()
, __set__()
, __get__()
,
or __delete__()
methods to match your requirements.
from base_descriptor import BaseDataDescriptor
class Plus2(BaseDataDescriptor):
def __set__(self, instance, value):
value = value + 2
instance.__dict__[self._property_name] = value
class Foo:
bar = Plus2()
foo = Foo()
foo.bar = 1
print(foo.bar) # 3
AbstractDataDescriptor
Provides an Abstract Base Class that can be inherited from to help create your own Data Descriptors.
from base_descriptor import AbstractDataDescriptor
class MyDataDescriptor(AbstractDataDescriptor):
def __init__(self):
self._value = None
def __get__(self, instance, owner):
return self._value
def __set__(self, instance, value):
self._value = value
def __delete__(self, instance):
self._value = None
class MyClass:
my_data_descriptor = MyDataDescriptor()
obj = MyClass()
obj.my_data_descriptor = 1
print(obj.my_data_descriptor) # 1
Slottable Data Descriptors
SlottableDefaultDescriptor
Slottable Default Descriptor that provides a default value for the attribute.
from base_descriptor import SlottableDefaultDescriptor
class Person:
__slots__ = "__weakref__"
first_name = SlottableDefaultDescriptor(default="Guido")
person = Person()
print(person.first_name) # Guido
person.first_name = "Raymond"
print(person.first_name) # Raymond
BaseSlottableDataDescriptor
Provides the same functionality as a standard attribute.
It enables you to create your own Slottable Data Descriptor by overriding
the __set_name__()
, __set__()
, __get__()
,
or __delete__()
methods to match your requirements.
from base_descriptor import BaseSlottableDataDescriptor
class MyDescriptor(BaseSlottableDataDescriptor):
def __set__(self, instance, value):
print(f"Setting {self._property_name} to {value}")
instance.__dict__[self._property_name] = value
class Foo:
__slots__ = "__weakref__"
bar = MyDescriptor()
foo = Foo()
foo.bar = 1
print(foo.bar) # 1
References
This module was heavily inspired by the following resources:
-
Python Deep Dive: Part 4
- Author: Dr. Fred Baptiste (fbaptiste)
- Year: 2023
- Course Title: Python Deep Dive: Part 4
- Platform: Udemy
-
Descriptor HowTo Guide
- Source: Python Documentation
- URL: Descriptor HowTo Guide
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for base_descriptor-1.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | bb0b8de06ca0a77325c02126e39844b4a9187ed94ecca426257a467947c72c29 |
|
MD5 | 05325c068a00cb4090411cb75f330261 |
|
BLAKE2b-256 | 2ace7208b67d58c0a909c98bc94d4f4bbd52c42ae6eaad2350879c43a7c8495d |