2016-07-25 40 views
0

有没有办法使用set和get语句来创建函数的字典,然后将它们用作set和get函数?使用__get__,__set__字典项?

class thing(object): 
    def __init__(self, thingy) 
     self.thingy = thingy 
    def __get__(self,instance,owner): 
     return thingy 
    def __set__(self,instance,value): 
     thingy += value 

theDict = {"bob":thing(5), "suzy":thing(2)} 

theDict["bob"] = 10 

希望的结果是,10进入设置功能,并增加了现有的5

print theDict["bob"] 
>>> 15 

实际的结果是,该词典替换数值

print theDict["bob"] 
>>> 10 

入口为什么我不能制作像.. theDict [“bob”]。add(10) 是因为它构建了一个现有的,已经很好的工作g函数使用set和get。我正在处理的案例是一个边缘案例,对于为这一案件进行工作而重新编程一切都没有意义。

我需要一些手段来存储此set/get thingy的实例,它可以访问,但不会创建可能会破坏现有引用的某个深度层。

请不要询问实际的代码。它会花费大量的代码来封装问题。

+0

什么鬼?不,'__get__'和'__set__'不能像那样工作。如果你现有的设计是在描述符本身上存储'thingy',而不是描述符附加到的类的对象,我会高度怀疑你现有的设计。 – user2357112

+0

我对这个问题也很困惑......我不明白'__get__'和'__set__'与你正在做什么有关。我想你可以创建一个包装类来覆盖'__getitem__'和'__setitem__'来以任何你想要的方式更新委托字典。然而,如果没有看到一些真实的代码(或者至少是你真正想要完成的事情的最低限度的例子),那么很难给出更多的建议...... – mgilson

+0

你有这个主要问题,你必须决定哪个对象负责您的自定义行为。现在你在字典上执行动作('theDict [“bob”] = 10')在'theDict'中为键'bob'指定10(正如你所看到的,这个描述甚至没有提到先前存储在所述键下的值) ,但期望利用'thing'中的自定义逻辑。如果自定义逻辑在'thing'中,请'thing'去做,不要问字典。如果你不能,重新考虑你的设计。 –

回答

1

你可以做,如果你(也)使用的是了解你的Thing类,并分别处理它的字典的专用版本:

class Thing(object): 
    def __init__(self, thingy): 
     self._thingy = thingy 
    def _get_thingy(self): 
     return self._thingy 
    def _set_thingy(self, value): 
     self._thingy += value 

    thingy = property(_get_thingy, _set_thingy, None, "I'm a 'thingy' property.") 

class ThingDict(dict): 
    def __getitem__(self, key): 
     if key in self and isinstance(dict.__getitem__(self, key), Thing): 
      return dict.__getitem__(self, key).thingy 
     else: 
      return dict.__getitem__(self, key) 

    def __setitem__(self, key, value): 
     if key in self and isinstance(dict.__getitem__(self, key), Thing): 
      dict.__getitem__(self, key).thingy = value 
     else: 
      dict.__setitem__(self, key, value) 


theDict = ThingDict({"bob": Thing(5), "suzy": Thing(2), "don": 42}) 

print(theDict["bob"]) # --> 5 
theDict["bob"] = 10 
print(theDict["bob"]) # --> 15 

# non-Thing value 
print(theDict["don"]) # --> 42 
theDict["don"] = 10 
print(theDict["don"]) # --> 10 
+0

这几乎适用于我,但有一个例外。传递参数的数量。我放入字典的类使用传递给它的实例。这个字典方法似乎没有通过该实例。这种方法有没有办法做到这一点? –

1

不,因为要执行theDict["bob"] = 10,Python运行时不会调用任何前一个值为theDict["bob"]的方法。这与myObject.mydescriptor = 10调用描述符设置器不同。

那么,如果引用计数为零,那么也许它会在前一个值上调用__del__,但我们不要去那里!

如果你想做这样的事情,那么你需要改变字典的工作方式,而不是内容。例如,你可以继承dict(通常警告你写了一个非Liskov替代的派生类是Evil,Bad和Wrong)。或者您可以从头开始实施collections.MutableMapping的实例。但我不认为有任何方法利用存储在其中的特殊值来劫持dict的正常运行。

+0

+1对'collections.MutableMapping'建议。请参阅:[http://stackoverflow.com/a/3387975/6084928](http://stackoverflow.com/a/3387975/6084928) –

+0

@Lex:我认为实现一个具体的'collections.MutableMapping'容器是过度杀伤 - 一个相对简单的'dict'子类很好。请参阅[我的答案](http://stackoverflow.com/a/38574478/355230)。 – martineau

+0

公平点。您的解决方案更简洁。 –