python – 懒惰评估:将 *** 作转发到递延值

python – 懒惰评估:将 *** 作转发到递延值,第1张

概述我已经实现了用于延迟评估转储到 JSON的配置的类.没问题,只需扩展编码器以使用特定协议(固定方法/属性)主动评估类. class DeferredCall(object): """Call that is evaluated lazyly""" def __init__(self, func, *func_args, **func_kwargs): self.func = fun 我已经实现了用于延迟评估转储到 JSON的配置的类.没问题,只需扩展编码器以使用特定协议(固定方法/属性)主动评估类.

class DeferredCall(object):  """Call that is evaluated lazyly"""  def __init__(self,func,*func_args,**func_kwargs):    self.func = func    self.func_args = func_args    self.func_kwargs = func_kwargs  def resolve(self):  # called by JsON encoder    return self.func(*self.func_args,**self.func_kwargs) a = DeferredCall(lambda: 1) a # gives <[module].DeferredCall at 0x1e99410> a.resolve() # gives 1

现在,功能强大的用户需要更多功率.即,直接对类进行 *** 作而不是它们所代表的值.根据python data model,这应该像实现魔术方法一样简单,例如__add __,__ len__等.

添加

def __add__(self,other):    return self.resolve() + other

要么

def __add__(self,other):    return self.resolve().__add__(other)

会正确地给我一个3 == 4.

但是,实施所有魔法方法有点过分了.所以我尝试使用__getattr__

def __getattr__(self,item):  return getattr(self.resolve(),item)

这适用于.__ mul __(3)== 3但是对于* 3 == 3,其中包含TypeError:*不支持的 *** 作数类型*:’DeferredCall’和’int’.

那么还有其他方法可以将运算符转发给包含的值吗?理想情况下,没有冒险以编程方式编写代码或__getattribute__的麻烦.

解决方法 发布我的解决方案以防任何其他人需要它.大多数“内置” *** 作(如*或len)不会使用__getattr [ibute] __,按设计.

我已经决定以编程方式创建方法

class DeferredCall(object):  def __init__(self,**func_kwargs):    self.func = func    self.func_args = func_args    self.func_kwargs = func_kwargs  def resolve(self):    return self.func(*self.func_args,**self.func_kwargs)  # magic must be resolved explicitly  # self other - resolve in reflected order to allow other to resolve as well  for so_magic in [("lt","gt"),("le","ge"),("eq","eq"),("ne","ne"),("add","radd"),("sub","rsub"),("mul","rmul"),("div","rdiv"),("truediv","rtruediv"),("floordiv","rfloordiv"),("mod","rmod"),("divmod","rdivmod"),("pow","rpow"),("lshift","rlshift"),("rshift","rrshift"),("and","rand"),("xor","rxor"),("or","ror")]:    for func_name,refl_name in [(so_magic[0],so_magic[1]),(so_magic[1],so_magic[0])]:      exec("def __%(fname)s__(self,other):\n\ttry:\n\t\tres = other.__%(rname)s__(self.resolve())\n\t\tif res == NotImplemented:\n\t\t\traise AttributeError\n\texcept AttributeError:\n\t\tres = self.resolve().__%(fname)s__(other)\n\treturn res" % {"fname": func_name,"rname": refl_name})  # regular magic - immutable only  for magic in ("str","nonzero","unicode","getattr","call","len","getitem","missing","iter","reversed","contains","getslice","neg","pos","abs","invert","complex","int","long","float","oct","hex","index"):    exec("def __%(fname)s__(self,*args,**kwargs):\n\treturn self.resolve().__%(fname)s__(*args,**kwargs)" % {"fname": magic})

基本上,魔术方法必须分为两类:自足方法和上下文方法.

自包含的是直接创建的,解析调用并执行魔术方法.例如,len被解析为:

def __len__(self,**kwargs):  return self.resolve().__len__(*args,**kwargs)

上下文必须反转呼叫,例如“大于”其他实际检查其他人是否“小于”自我.如果两个对象都是延迟调用,那么这是必需的,允许其他对象自行解析;否则,许多方法都会引发TypeError.直接评估仅在其他人没有倒置版本时使用.

def __gt__(self,other):  try:    res = other.__lt__(self.resolve())    if res == NotImplemented:      raise AttributeError  except AttributeError:    res = self.resolve().__gt__(other)  return res

有些调用可能会更有效地实现,因为python使用了一些技巧(这正是我的问题首先出现在哪里).例如,乘法可以利用交换性:

def __mul__(self,other):  """self * other"""  return other * self.resolve()
总结

以上是内存溢出为你收集整理的python – 懒惰评估:将 *** 作转发到递延值全部内容,希望文章能够帮你解决python – 懒惰评估:将 *** 作转发到递延值所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1197431.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存