Skip to main content

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:
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

Metadata

Release files for ez-life 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ez-life 1.1.0
File Size Uploaded
ez-life-1.1.0.tar.gz 16.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ez-life 1.1.0
File Interpreter ABI Platform
ez_life-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 36.5 kB

Release files / ez-life-1.1.0.tar.gz

Download URL ez-life-1.1.0.tar.gz
Size 16.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9c50861f9855e7e633d7a32d1c63831740df4f271c0cd5b72d0f71115725bd30
BLAKE2b-256 checksum
How to use checksums
720c09a6cba5062d9d7d78cac7c781e74f027c53e3394f8d88f44a08a2a303ff
Upload date
Uploaded using Trusted Publishing?
What is 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

Release files / ez_life-1.1.0-py3-none-any.whl

Download URL ez_life-1.1.0-py3-none-any.whl
Size 20.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8ed91f1f2ef11a7e243f30f15b698e20cffc1c0b45eb71e6dc77e5f39e9e3858
BLAKE2b-256 checksum
How to use checksums
795c5d559d8c03f185740b44658af4e317568d66cc0c14cf32cdb5ae7f8eed65
Upload date
Uploaded using Trusted Publishing?
What is 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

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page