Source code for free_properties._property_factory
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 18 14:18:27 2019
@author: Guest Group
"""
from ._free_property import metaProperty, FreeProperty
__all__ = ('PropertyFactory',)
# %% Property Factory
[docs]def PropertyFactory(fget=None, fset=None, clsname=None, doc=None, units=None,
slots=None):
"""Create an FreeProperty subclass with getter and setter functions.
Parameters
----------
fget : function, optional
Should return value of instances. If not given, a decorator expecting
fget will be returned.
fset : function, optional
Should set the value of instances.
clsname : str, optional
Name of the class. Defaults to the function name of fget.
doc : str, optional
Docstring of class. Defaults to the docstring of fget.
units : str, optional
Units of measure.
slots : tuple[str], optional
Slots for class.
Examples
--------
The PropertyFactory is a FreeProperty class creator that functions similar to Python 'property' objects. Use the PropertyFactory to create a Weight class which calculates weight based on density and volume:
.. code-block:: python
>>> from free_properties import PropertyFactory
>>> def getter(self):
... '''Weight (kg) based on volume (m^3).'''
... data = self.data
... rho = data['rho'] # Density (kg/m^3)
... vol = data['vol'] # Volume (m^3)
... return rho * vol
>>>
>>> def setter(self, weight):
... data = self.data
... rho = data['rho'] # Density (kg/m^3)
... data['vol'] = weight / rho
>>>
>>> # Initialize with a value getter, setter, and the class name.
>>> Weight = PropertyFactory(fget=getter, fset=setter, clsname='Weight', units='kg')
It is more convinient to use the PropertyFactory as a decorator:
.. code-block:: python
>>> @PropertyFactory(units='kg')
>>> def Weight(self):
... '''Weight (kg) based on volume (m^3).'''
... data = self.data
... rho = data['rho'] # Density (kg/m^3)
... vol = data['vol'] # Volume (m^3)
... return rho * vol
>>>
>>> @Weight.setter
>>> def Weight(self, weight):
... data = self.data
... rho = data['rho'] # Density (kg/m^3)
... data['vol'] = weight / rho
Create dictionaries of data and initialize new Weight objects:
.. code-block:: python
>>> water_data = {'rho': 1000, 'vol': 3}
>>> ethanol_data = {'rho': 789, 'vol': 3}
>>> weight_water = Weight('Water', water_data)
>>> weight_ethanol = Weight('Ethanol', ethanol_data)
>>> weight_water
<Water: 3000 kg>
>>> weight_ethanol
<Ethanol: 2367 kg>
.. Note::
The units are taken from the the function docstring. The first word in parentesis denotes the units.
These properties behave just like their dynamic value:
.. code-block:: python
>>> weight_water + 30
3030
>>> weight_water + weight_ethanol
5367
Get and set the value through the 'value' attribute:
.. code-block:: python
>>> weight_water.value
3000
>>> weight_water.value = 4000
>>> weight_water.value
4000.0
>>> water_data # Note that the volume changed too
{'rho': 1000, 'vol': 4.0}
In place magic methods will also change the property value:
.. code-block:: python
>>> weight_water -= 1000
>>> weight_water
<Water: 3000 kg>
>>> water_data # The change also affects the original data
{'rho': 1000, 'vol': 3.0}
"""
if not fget:
return lambda fget: PropertyFactory(fget, fset, clsname, doc, units, slots)
# Defaults
if clsname is None: clsname = fget.__name__
if doc is None: doc = fget.__doc__
definitions = {'__doc__': doc,
'__slots__': slots or ('name', 'data'),
'__module__': fget.__module__,
'_units': units,
'value': property(fget, fset)}
return metaProperty(clsname, (FreeProperty,), definitions)