实现** <class>?

时间:2016-09-09 18:36:44

标签: python class dictionary overloading magic-methods

修改

这个问题已被标记为重复,但我认为不是。实现建议的答案,即使用Mapping abc,没有我想要的行为:

from collections import Mapping

  class data(Mapping):

    def __init__(self,params):
      self.params = params

    def __getitem__(self,k):
      print "getting",k
      return self.params[k]

    def __len__(self):
      return len(self.params)

    def __iter__(self):
      return ( k for k in self.params.keys() )

def func(*args,**kwargs):
  print "In func"
  return None

ps = data({"p1":1.,"p2":2.})

print "\ncalling...."
func(ps)

print "\ncalling...."
func(**ps)

输出:

calling....
In func

calling....
in __getitem__ p2
in __getitem__ p1
In func

正如问题所述,这不是我想要的。

评论中给出的另一个解决方案是修改导致问题的例程。这肯定会奏效,但我正在寻找一个快速(懒惰?)修复!

问题:

除了通过**之外,如何为类实现__getitem__运算符?例如,我希望能够做到这一点::

  def func(**kwargs):
    <do some clever stuff>

  x = some_generic_class():

  func( **x )

没有对some_generic_class.__getitem__()的隐式调用。在我的应用程序中,我已经实现了__getitem__一些数据记录,当上面引用类时我不想执行它。

如果无法重载**运算符,是否可以检测何时由于类传递给函数而调用__getitem__,而不是显式?

背景

我正在研究一个物理模型,该模型是根据运行时根据用户输入选择的一组包构建的。模型的灵活结构意味着我很少知道所需的参数,因此我在模型之间传递dict个参数名称和值。为了使这个用户更友好,我现在正在尝试开发一个类paramlist,它使用一组例程执行一些一致性检查,设置默认值等来重载dict功能。这个想法是我传递paramlist的实例而不是dict。其中一个更重要的目标是记录物理包中哪些paramlist成员被引用,哪些没有。下面是一个剥离版本,旨在维护第二个dict,记录是否已引用参数::

class paramlist(object):

  def __init__( self, params ):

    self.params = copy(params)
    self.used = { k:False for k in self.params }

  def __getitem__(self, k):

    try:
      v = self.params[k]
    except KeyError:
      raise KeyError("Parameter {}  not in parameter list".format(k))
    else:
      self.used[k] = True

    return v

  def __setitem__(self,k,v):
    self.params[k] = v
    self.used[k] = False

哪个没有我想要的行为:

  ps = paramlist( {"p1":1.} )

  def donothing( *args, **kwargs ):
    return None

  donothing(ps)
  print paramlist.used["p1"]

  donothing(**ps)
  print paramlist.used["p1"]

输出:

 False
 True

我希望use dict在两种情况下都保持False,这样我就可以告诉用户他们的一个参数没有被使用(暗示他们搞砸了,而是使用了默认值) 。我认为**案例会对__getitem__中的每个条目调用paramlist

0 个答案:

没有答案