A Python Package to make life ez for pythonistas
Project description
ez_life
The objective of ez_life is to make coding with Python easier by removing repetitive code while still maintaining the same level of functionality
Installation
pip install -U ez_life
param2attr
- Here is a little sneak peak of what you can do with this package!
- First consider this code block:
from ez_life import Param2attr
class Foo:
def __init__(self, param1 = None, param2 = None, param3 = None):
# This sux
self.param1 = param1
self.param2 = param2
self.param3 = param3
- We can instead create a class that looks like this, using a property decorator to perform the param to attribute assignments
class Foo:
@Param2attr(exclude=None)
def __init__(self, param1 = None, param2 = None, param3 = None):
# this good, allows u to write other code here during initialization
pass
- If you are interested to learn about the implementation or other features that param2attr supports, feel free to read the Param2attr documentation!
JTProperty
- Ez_life can also be used to create "variable dependencies" using the @JTProperty decorator
- It essentially builds upon the functionality that the @property decorator gives!
Understanding The Classic @property:
- The concept of python's classic decorator @property is not difficult to learn, read this section if you want to learn it or get a refresher
Classic Setter and Getter Methods
- First consider a classic class Square
- A square has a 3 properties:
- A length, an perimeter and an area
- First we will code the length:
- A square has a 3 properties:
class Square:
def getLength(self):
return self._length # the underscore "_" in "_length" means that it is a "protected variable"
def setLength(self, r):
if r <= 0:
raise ValueError("length should be greater than 0")
self._length = r
- We can use this class as follows:
square = Square() # create a class instance
square.setLength(4) # sets self._length to 4
print(square.getLength()) # 4
square.setLength(-1) # raises a ValueError "length should be greater than 0"
Property Setter and Getter Methods Part 1
- Python's inbuilt @property decorator allows setters and getters to be used in a much easier way:
class Square:
@property
def length(self): # the setter method
return self._length
@length.setter
def length(self, r): # the getter method
if r <= 0:
raise ValueError("length should be greater than 0")
self._length = r
- The code below shows how to use the setter and getter methods for this class:
square = Square() # create a square instance
square.length = 4 # sets self._length to 4
print(square.length) # 4
square.length = -1 # raises a ValueError "length should be greater than 0"
- Syntactically, the code above is much more pythonic, but the problem is that the setter must be called before the getter
- The code below demonstrates this vulnerability:
square = Square()
print(square.length) # raises an error
Property Setter and Getter Methods Part 2
- The reason why an error is raised is because the length has not been set yet via the setter method
- A solution to this could be achieved as follows:
class Square:
@property
def length(self):
if "_length" not in dir(self): # checks if self._length is an attribute yet
self.length = 1 # if not, call the setter method to set self._length to 1
return self._length
@length.setter
def length(self, r):
if r <= 0:
raise ValueError("length should be greater than 0")
self._length = r
- Now we will not get an error when calling the getter before the setter, we instead get some default value
- In this case the default value is 1
square = Square()
print(square.length) # 1
Understanding The @JTProperty:
JTProperty Setter and Getter Methods
- Obviously, the code with the @property decorator is Pythonic, however it is far from perfect
- We can see that there are many lines of code already written for just the length setter and getter methods
- Now we will demonstrate how the ez_life @JTProperty decorator can make the Square class above more concise
- @JTProperty does this by abstracting away the self._length variable
# importing the JTProperty decorator from the ez_life module
from ez_life import JTProperty
class Square:
@JTProperty()
def length(self):
return 1
@length.setter
def length(self, r):
if r <= 0:
raise ValueError("length should be greater than 0")
return r
- For JTProperty we can call the setter before the getter method
square = Square() # create a class instance
square.length = 4 # sets self._length to 4
print(square.length) # 4
square.length = -1 # raises a ValueError "length should be greater than 0"
- Or we can call the getter before the setter method
square = Square()
print(square.length) # 1
- As we can see, JTProperty offers the same functionality as @property but with less code!
Full Implementation of Square with JTProperty
- Now that we have an understanding of JTProperty, we can fully implement the square class perimeter and area setter methods!
class Square:
@JTProperty()
def length(self):
return 1
@length.setter
def length(self, r):
if r <= 0:
raise ValueError("length should be greater than 0")
return r
@JTProperty()
def area(self):
return self.length ** 2
@JTProperty()
def perimeter(self):
return self.length * 4
- We can call these methods as follows:
square = Square()
print(square.area) # (1 ** 2) => 1
print(square.perimeter) # (1 * 4) => 4
square.length = 2 # set length to 2
print(square.area) # 1 <= note that square.area stays the same even though square.length changed
print(square.perimeter) # 4 <= note that square.perimeter stays the same
# square.area = 10 # (note that this gives an error because no setter method is defined for area)
Full Implementation of Square with JTProperty part 2 (with dependencies)
- Notice that square.area and square.perimeter do not update when square.length is changed to 2
- To update square.area and square.perimeter when square.length is changed, a "dependency" list must be given to JTProperty for both square.area and square.perimeter methods:
class Square:
@JTProperty()
def length(self):
return 1
@length.setter
def length(self, r):
if r <= 0:
raise ValueError("length should be greater than 0")
return r
@JTProperty(deps = 'length')
def area(self):
return self.length ** 2
@JTProperty(deps = 'length')
def perimeter(self):
return self.length * 4
- Now when changing square.length to some other value, both square.area and square.perimeter return their corresponding updated values when called
square = Square()
print(square.area) # (1 ** 2) => 1
print(square.perimeter) # (1 * 4) => 4
square.length = 2 # set length to 2
print(square.area) # (2 ** 2) => 4
print(square.perimeter) # (2 * 4) => 8
- This concludes the introduction to some of the features that JTProperty supports!
- Other features not covered here include:
- Support for hierarchal classes
- default and default type setters
- Circular dependency graphs
- If you are interested to learn about these other features and more, feel free to read the JTProperty documentation!
ez-life directory layout:
- develop: the package containing all .ipynb dev files and converted .py files
- param2attr.ipynb: dev notebook for automation of parameter creation to class object attributes
- param2attr.py: param2attr.ipynb -> param2attr.py via Makefile
- jt_property.ipynb: dev notebook for more writing dependency related code
- jt_property.py: jt_property.ipynb -> jt_property.py via Makefile
- ez_life: the package containing all converted .py files
- .gitignore: for ignoring files when pushing and pulling
- LICENSE: what u can and can't do with this repo
- MAKEFILE: automated test cases and .ipynb to .py conversion
- README: this file essentially
- MANIFEST.in: Files to include in pip upload
- build: automatically generated file for pip
- dist: automatically generated file for pip
- setup.py: contains setups for when uploading to pip
- test*.py: test files for modules within ez_life
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
ez-life-1.1.0.tar.gz
(16.3 kB
view details)
Built Distribution
ez_life-1.1.0-py3-none-any.whl
(20.2 kB
view details)
File details
Details for the file ez-life-1.1.0.tar.gz
.
File metadata
- Download URL: ez-life-1.1.0.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.54.1 CPython/3.8.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9c50861f9855e7e633d7a32d1c63831740df4f271c0cd5b72d0f71115725bd30 |
|
MD5 | 0136af7b52f7a59d2951f7c6348fb2fe |
|
BLAKE2b-256 | 720c09a6cba5062d9d7d78cac7c781e74f027c53e3394f8d88f44a08a2a303ff |
File details
Details for the file ez_life-1.1.0-py3-none-any.whl
.
File metadata
- Download URL: ez_life-1.1.0-py3-none-any.whl
- Upload date:
- Size: 20.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.54.1 CPython/3.8.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8ed91f1f2ef11a7e243f30f15b698e20cffc1c0b45eb71e6dc77e5f39e9e3858 |
|
MD5 | 866d6c856bab9e8fe12af946c047bc81 |
|
BLAKE2b-256 | 795c5d559d8c03f185740b44658af4e317568d66cc0c14cf32cdb5ae7f8eed65 |