Python:如何在dict中引用变量?

时间:2017-10-15 21:42:19

标签: python dictionary

如何从dict中的实例引用变量?

此代码:

class Gold():
    def __init__(self):
        self.amount = 10

class Cheese():
    def __init__(self, gold):
        self.gold = gold
        self.wallet = {'gold' : self.gold.amount}
        self.charge ={'gold' : 10}

    def subtract(self):
        for cat, cost in self.charge.iteritems():
            if self.wallet[cat] >= cost:
                self.wallet[cat] -= cost

gold = Gold()
cheese = Cheese(gold)
cheese.subtract()
print 'gold amount =', cheese.gold.amount, 'wallet =', cheese.wallet

的产率:

gold amount = 10 wallet = {'gold': 0}

而不是

gold amount = 0 wallet = {'gold': 0}

在实际代码中我不想要一个完整的列表' if'声明。所以我把一个dict与这个例子中的所有成本(费用)结合到一个带有所有实际值的字典,所以我不必这样做

if cost == 'gold':
    pass
if cost == 'action points':
    pass

有关如何执行此操作的任何提示? 最终的问题是:

a = 1
b = a

有没有办法更新a和b(b + = 1只更新b到2)

2 个答案:

答案 0 :(得分:1)

在Python中:

  • 所有变量都是参考
  • 整数和字符串是不可变的

所以当你这样做时:

>>> a = 1  # a points to 1
>>> b = a  # b points to 1
>>> b = 10   # b now points to 10, a still points to 1 and 1 is unchanged.
>>> b
10

>>> a
1

如果您使用可变数据类型,那么它可以工作:

>>> a = []
>>> b = a
>>> b.append(10)
>>> b
[10]

>>> a
[10]

>>> a[0] = 20
>>> b
[20]

也许您可以创建一个通用容器:

class GenericContainer(object):
    def __init__(self, **kwargs):
        self._keys = set()
        for k, v in kwargs.items():
            if k in ('inventory', 'charge'):
                raise ValueError('Unable to override method {}'.format(k))
            setattr(self, k, v)
            self._keys.add(k)

    def charge(self, **kwargs):
        for k, v in kwargs.items():
            if k in ('inventory', 'charge'):
                raise ValueError('Unable to override method {}'.format(k))
            if v < 0 and getattr(self, k, 0) < abs(v):
                raise ValueError("You don't have enough {}".format(k))
            setattr(self, k, getattr(self, k, 0) + v)
            self._keys.add(k)
        return self

    def inventory(self):
        return {k:getattr(self, k) for k in self._keys}

    def __repr__(self):
        return str(self.inventory())

然后你的钱包可以是GenericContainer的一个实例:

>>> wallet = GenericContainer(gold=10, silver=5)
>>> wallet
{'gold': 10, 'silver': 5}

>>> wallet.charge(gold=-5, silver=5)
{'gold': 5, 'silver': 10}

>>> wallet.charge(gold=-20)
ValueError: You don't have enough gold

>>> wallet.gold
5

您可以直接设置和/或检索属性:

>>> wallet.gold
5

>>> wallet.gold += 10
>>> wallet.gold
15

>>> wallet
{'gold': 15, 'silver': 10}

您可以从广告资源或使用getattr

按名称获取属性
>>> wallet.inventory().get('gold', 0)
15

>>> getattr(wallet, 'gold')
15

您可以使用参数:value或setattr

的dict按名称设置
>>> wallet.charge(**{'gold': -10})
{'gold': 5, 'silver': 10}

>>> setattr(wallet, 'gold', 20)
>>> wallet.gold
20

查看结果,我明白为什么在Python中我经常只使用字典而不是创建一个类 - 尽管我确实错过了Javascript对象语法,您可以使用foo.bar或{{1来访问属性}}

在Python中,内置数据结构非常强大,Python开发人员倾向于使用&#34;我们都同意成人&#34;只需传递数据而不必过多关注属性保护的方法。可能我最终会这样做:

foo["bar"]

而不是使用>>> wallet = {'gold': 10, 'silver': 15} 方法:

charge(gold=10)

这需要时间&#34;它只是数据&#34;沉没的方法但在那之后你很少会错过更多官僚主义的OO成语,这些成语在Java或C ++等语言中非常常见,特别适用于小型项目/团队。

答案 1 :(得分:1)

似乎最简单的方法是将wallet从属性更改为property

class Cheese():
    def __init__(self, gold):
        self.gold = gold
        self.charge ={'gold' : 10}

    @property
    def wallet(self):
        return {'gold': self.gold.amount)

    def subtract(self):
        for cat, cost in self.charge.iteritems():
            if self.wallet[cat] >= cost:
                self.wallet[cat] -= cost

属性是行为类似属性的方法。它们每次都是在通话时计算,而不是在创建对象时计算,而不是再次计算。但是,你以相同的方式使用它们,所以:

>>> print 'gold amount =', cheese.gold.amount, 'wallet =', cheese.wallet
gold amount = 0 wallet = {'gold': 0}