Python:在字典中将变量链接/绑定在一起

时间:2009-06-28 18:11:53

标签: python variables dictionary

第一篇文章,所以玩得很好!

我有一个关于Python词典的相当基本的问题。我希望有一些dict值在另一个变量被更改时更新(或者至少在下次调用时重新计算) - 例如:

mass = 1.0
volume = 0.5
mydict = {'mass':mass,'volume':volume}
mydict['density'] = mydict['mass']/mydict['volume']

所以在这种情况下,mydict ['density']只返回2.0。如果我改变mydict ['mass'] = 2.0,密度将不会更新。很好 - 我可以理解为什么 - 密度是由传递给声明时的值定义的。所以我想也许我可以用lambda表达式来解决这个问题,例如(为可怕的代码道歉!):

mydict['density_calc'] = lambda x,y: x/y
mydict['density'] = mydict['density_calc'](mydict['mass'],mydict['volume'])

但同样,这只会返回原始密度,尽管改变了mydict ['mass']。作为最后的尝试,我尝试了这个:

def density(mass,volume): return mass/volume
mydict['density_calc'] = lambda x,y: density(x,y)
mydict['density'] = mydict['density_calc'](mydict['mass'],mydict['volume'])

再次,没有骰子。这似乎是一个非常简单的问题需要解决,所以提前道歉,但如果有人能帮助我,我会非常感激!

干杯,

戴夫

8 个答案:

答案 0 :(得分:9)

似乎是滥用字典结构。为什么不创建一个简单的类?

class Entity(object):
    def __init__(self, mass, volume):
        self.mass = mass
        self.volume = volume
    def _density(self):
        return self.mass / self.volume
    density = property(_density)

答案 1 :(得分:6)

在这种情况下,最好为此创建一个类并使用动态属性。 e.g:


class Body(object):
    def __init__(self):
        self.mass=1.0
        self.volume=0.5

    @property
    def density(self):
        return self.mass/self.volume

这将为您提供质量,体积和密度属性,其中密度是根据其他两个值计算的。 e.g。


b=Body()
b.mass=1
b.volume=0.5
print b.density # should be 2

b.mass=2.0
print b.density # should be 4

但是,如果你坚持使用字典,你应该扩展它并覆盖__getitem____setitem__“魔法”方法,以及检测质量何时发生变化,或者当密度被访问时根据需要重新计算。

答案 2 :(得分:4)

一个班级会做得更好:

class Thing:
    def __init__(self, mass, volume):
        self._mass = mass
        self._volume = volume
        self._update_density()

    def _update_density(self):
        self._density = self._mass / self._volume

    def get_density(self):
        return self._density

    density = property(get_density)

    # You're unlikely to need these, but to demonstrate the point:
    def set_mass(self, mass):
        self._mass = mass
        self._update_density()

    def set_volume(self, volume):
        self._volume = volume
        self._update_density()

brick = Thing(mass=2, volume=0.8)
print brick.density
# Prints 2.5

brick.set_mass(4)
print brick.density
# Prints 5.0

我告诉你,当你设置其他值时,你想要更新密度 - 更简单的方法就是在被要求时简单地计算它:

    def get_density(self):
        return self._mass / self._volume

然后你根本不需要_update_density()

答案 3 :(得分:3)

简短的回答是你不能。

分配的表达式在遇到时会被strictly评估,因此以后对这些术语的任何更改都无关紧要。

您可以使用自定义dict类来覆盖 getitem setitem 方法并为某些键执行特殊操作(即计算值)(比如说)密度和有限数量的其他)。

class MyDict(dict):
    def __getitem__(self, key):
            if key == "density":
                    return self["mass"] / self["volume"]
            return dict.__getitem__(self, key)

d = MyDict()
d["mass"] = 2.0
d["volume"] = 4.0
d["density"]    # 0.5

查看this

答案 4 :(得分:3)

问题是词典不是解决问题的正确工具。你的问题就像“我怎么能用螺丝刀敲钉子”; - )

字典应该将键映射到值,而不关心字典中的其他值。你想要的是一个班级

class PhysicalObject:
    def __init__(self, mass, volume):
         self.mass = float(mass)
         self.volume = float(volume)
    def setMass(self, mass):
         self.mass = float(mass)
    def setVolume(self, volume):
         self.volume = float(volume)
    def getDensity(self):
         return self.mass/float(self.volume)

 v = PhysicalObject(1.0, 2.0)
 print v.getDensity() # prints 0.5
 v.setMass(2.0)
 v.setVolume(1.0)
 print v.getDensity() # prints 2.0

此示例每次您想要获取密度时重新计算密度,购买时您也可以在setMass和setVolume函数中计算它。

答案 5 :(得分:1)

这很容易:

>>> mydict = {'mass':100, 'volume': 2, 'density': lambda: mydict['mass']/mydict['volume']}
>>> mydict['density']()
50
>>> mydict['mass']=200
>>> mydict['density']()
100
>>> mydict['volume'] = 4
>>> mydict['density']()
50

我的lambda引用了mydict,后来又在mydict中检索了最新的数据保存,所以每次我想调用它时都不会将质量和音量传递给函数,就像你的解决方案一样:

def density(mass,volume): return mass/volume
mydict['density_calc'] = lambda x,y: density(x,y)
mydict['density'] = mydict['density_calc'](mydict['mass'],mydict['volume'])

然而,mydict ['density']是一个函数,而不是值本身。

答案 6 :(得分:0)

自引用字典几乎与您的第二次尝试(从7年前)相匹配,并且可以与使用此字典的任何其他代码很好地匹配。换句话说,它看起来仍然像鸭子一样。

mydict['mass']=2.0
print(mydict['density'])

2.0

var myImage = proxy.GetImage();

var converter = new ImageConverter();
var data = (byte[])converter.ConvertTo(myImage, typeof(byte[]);

AppDomain.Unload(tmpDomain);
pictureBox.Image = (Bitmap)converter.ConvertFrom(data);

4.0

答案 7 :(得分:-2)

这里有一个关于如何将dict子类化以满足您的规范的快速入侵,但可能不符合Python的字典规范:

class MyDict(dict):
    def __getitem__(self, key):
        if key == 'density':
           return self['mass'] / self['volume']
        else:
            return dict.__getitem__(self,key)
    def keys(self):
        return ['density'] + dict.keys(self)

x = MyDict()
x['mass'] = 1.0
x['volume'] = 0.5

print x

print x.keys()

print x['density']

x['mass'] = 2.0

print x['density']

打印

{'volume': 0.5, 'mass': 1.0}
['density', 'volume', 'mass']
2.0
4.0

但这并没有考虑到dict.iterkeys()等等。