git » pymisc » commit e0f34b2

Implement a lazy evaluation decorator.

author Alberto Bertogli
2006-06-18 18:29:08 UTC
committer Alberto Bertogli
2006-06-18 18:29:08 UTC
parent 06e48cb21c32890dac3da841e58bf902138d5862

Implement a lazy evaluation decorator.

lazy.py +54 -0
samples/lazy/sample1.py +19 -0

diff --git a/lazy.py b/lazy.py
new file mode 100644
index 0000000..b0d6c59
--- /dev/null
+++ b/lazy.py
@@ -0,0 +1,54 @@
+
+"""
+lazy - Decorators and utilities for lazy evaluation in Python
+Alberto Bertogli (albertogli@telpin.com.ar)
+"""
+
+class _LazyWrapper:
+	"""Lazy wrapper class for the decorator defined below.
+	It's closely related so don't use it.
+
+	We don't use a new-style class, otherwise we would have to implement
+	stub methods for __getattribute__, __hash__ and lots of others that
+	are inherited from object by default. This works too and is simple.
+	I'll deal with them when they become mandatory.
+	"""
+	def __init__(self, f, args, kwargs):
+		self._override = True
+		self._isset = False
+		self._value = None
+		self._func = f
+		self._args = args
+		self._kwargs = kwargs
+		self._override = False
+
+	def _checkset(self):
+		if not self._isset:
+			self._override = True
+			self._value = self._func(*self._args, **self._kwargs)
+			self._isset = True
+			self._checkset = lambda: True
+			self._override = False
+
+	def __getattr__(self, name):
+		if self.__dict__['_override']:
+			return self.__dict__[name]
+		self._checkset()
+		return getattr(self._value, name)
+
+	def __setattr__(self, name, val):
+		if name == '_override' or self._override:
+			self.__dict__[name] = val
+			return
+		self._checkset()
+		setattr(self._value, name, val)
+		return
+
+def lazy(f):
+	"Lazy evaluation decorator"
+	def newf(*args, **kwargs):
+		return _LazyWrapper(f, args, kwargs)
+
+	return newf
+
+
diff --git a/samples/lazy/sample1.py b/samples/lazy/sample1.py
new file mode 100644
index 0000000..91e898b
--- /dev/null
+++ b/samples/lazy/sample1.py
@@ -0,0 +1,19 @@
+
+import lazy
+import time
+
+
+def show(v):
+	print 'show() init + print'
+	s = str(v)
+	print 'show() v: ' + s
+	print 'show() done'
+
+@lazy.lazy
+def set():
+	print 'set() returns 3'
+	return 3
+
+v = set()
+show(v)
+