zsq*_*are 2 python orm activerecord
我很想知道如何在更高级别(即库等)中实现延迟评估.例如,Django ORM或ActiveRecord如何推迟对查询的评估,直到实际使用它为止?
让我们来看看django django.db.models.query.QuerySet类的一些方法:
class QuerySet(object):
"""
Represents a lazy database lookup for a set of objects.
"""
def __init__(self, model=None, query=None, using=None):
...
self._result_cache = None
...
def __len__(self):
if self._result_cache is None:
...
elif self._iter:
...
return len(self._result_cache)
def __iter__(self):
if self._result_cache is None:
...
if self._iter:
...
return iter(self._result_cache)
def __nonzero__(self):
if self._result_cache is not None:
...
def __contains__(self, val):
if self._result_cache is not None:
...
else:
...
...
def __getitem__(self, k):
...
if self._result_cache is not None:
...
...
Run Code Online (Sandbox Code Playgroud)
这些方法遵循的模式是,在调用真正需要返回某些结果的某个方法之前,不会执行任何查询.此时,结果存储在,self._result_cache并且对同一方法的任何后续调用都将返回缓存的值.
在Python中,一个对象可能"存在" - 但它的内在价值只有在与其中一个运算符一起使用时才被外部世界所知 - 因为运算符是在类中由具有双下划线的魔术名称定义的,如果一个类在调用运算符时写入适当的代码来执行延迟代码,那就没问题了.
这意味着,如果对象的值例如像字符串一样使用,那么将使用该对象的程序的任何部分将在某些时候调用"__str__"强制方法.
例如,让我们创建一个行为类似字符串的对象,但告诉当前时间.字符串可以连接到其他字符串(__ add__),可以请求其长度(__len__),依此类推.如果我们希望它完全适合字符串的位置,我们必须覆盖所有方法.我们的想法是在调用其中一个运算符时检索实际值 - 否则,实际对象可以自由地分配给变量并传递.只有在需要它的值时才会进行评估
然后,可以有一些像这样的代码:
class timestr(object):
def __init__(self):
self.value = None
def __str__(self):
self._getvalue()
return self.value
def __len__(self):
self._getvalue()
return len(self.value)
def __add__(self, other):
self._getvalue()
return self.value + other
def _getvalue(self):
timet = time.localtime()
self.value = " %s:%s:%s " % (timet.tm_hour, timet.tm_min, timet.tm_sec)
Run Code Online (Sandbox Code Playgroud)
在控制台上使用它,您可能有:
>>> a = timestr()
>>> b = timestr()
>>> print b
17:16:22
>>> print a
17:16:25
Run Code Online (Sandbox Code Playgroud)
如果您想要延迟评估的值是对象的属性(如Peson.name)而不是对象的实际行为 - 它更容易.因为Python允许所有对象属性都是特殊类型 - 称为描述符 - 实际上每次访问属性时都会调用一个方法.因此,只需创建一个具有适当方法的类__get__来获取实际值.仅在需要属性时才会调用此方法.
Python甚至还有一个用于轻松创建描述符的实用程序 - "property"关键字,这使得这更加容易 - 您传递的方法是生成属性作为属性的第一个参数的代码.
因此,让一个具有惰性(和实时)评估时间的Event类只是写入的问题:
import time
class Event(object):
@property
def time(self):
timet = time.localtime()
return " %s:%s:%s " % (timet.tm_hour, timet.tm_min, timet.tm_sec)
Run Code Online (Sandbox Code Playgroud)
并使用它如:
>>> e= Event()
>>> e.time
' 17:25:8 '
>>> e.time
' 17:25:10 '
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1163 次 |
| 最近记录: |