如何获取对象属性的引用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取对象属性的引用?相关的知识,希望对你有一定的参考价值。

我正在寻找一种方法来改变对象属性取决于解析到方法的值。例如:

class Character(object):
    def __init__(self, hp, mp, st, ag):
        self.hp = hp
        self.mp = mp
        self.st = st
        self.ag = ag

    def increase_stat(self, stat, value):
        ''' Increase one of the attributes
            (hp, mp, st, ag) by a given value.
        '''
        stat_dict = {'hp': self.hp,
                     'mp': self.mp,
                     'st': self.st,
                     'ag': self.ag}
        stat_attr = stat_dict.get(stat)
        # below should be equivalent to self.hp += value
        stat_attr += value


hero = Character(hp=10, mp=4, st=3, ag=2)
hero.increase_stat(stat='hp', value=2)
# this should increase the hp by 2
print(hero.hp == 12)

我理解这不起作用,因为stat_dict.get(stat)返回self.hp指向的值而不是实际的self.hp对象。

Current Solution

我没有将属性作为dict的值,而是增加了每个单独的stat。

class Character(object):
    def __init__(self, hp, mp, st, ag):
        self.hp = hp
        self.mp = mp
        self.st = st
        self.ag = ag

    def increase_stat(self, stat, value):
        ''' Increase one of the attributes
            (hp, mp, st, ag) by a given value.
        '''
        stat_method_dict = {'hp': self._increase_hp,
                            'mp': self._increase_mp,
                            'st': self._increase_st,
                            'ag': self._increase_ag}
        alter_stat_method = stat_method_dict.get(stat)
        alter_stat_method(value)

    def _increase_hp(self, value):
        self.hp += value

    def _increase_mp(self, value):
        self.mp += value

    def _increase_st(self, value):
        self.st += value

    def _increase_ag(self, value):
        self.ag = value


hero = Character(hp=10, mp=4, st=3, ag=2)
hero.increase_stat(stat='hp', value=2)
# this should increase the hp by 2
print(hero.hp == 12)

我的问题是它是重复的,如果我决定在类中添加更多的属性/统计数据,那么这只会增加重复方法的数量。我想知道是否有比这更好的解决方案吗?

SOLUTION

现在看来非常明显。谢谢大家。

class Character(object):
    def __init__(self, hp, mp, st, ag):
        self.hp = hp
        self.mp = mp
        self.st = st
        self.ag = ag

    def increase_stat(self, stat, value):
        ''' Increase one of the attributes
            (hp, mp, st, ag) by a given value.
        '''
        current = getattr(self, stat) 
        setattr(self, stat, current+value)
答案

你的统计数据真的没有任何意义。使用getattrsetattr动态操作属性。所以,像:

def increase_stat(self, stat, value):
    setattr(self, stat, value + getattr(self, stat))

所以,例如:

In [30]: class Dummy:
    ...:     def __init__(self):
    ...:         self.intelligence = 0
    ...:         self.strength = 10
    ...:         self.hp = 100
    ...:     def increase_stat(self, stat, value):
    ...:         setattr(self, stat, value + getattr(self, stat))
    ...:

In [31]: d = Dummy()

In [32]: d.strength
Out[32]: 10

In [33]: d.increase_stat('strength', 10)

In [34]: d.strength
Out[34]: 20

也许更容易阅读:

def increase_stat(self, stat, value):
    current = getattr(self, stat)
    setattr(self, stat, current + value)

注意,这比直接操作实例__dict__要好,后者会破坏property对象之类的描述符。更不用说没有__dict__的物体,例如与__slots__类型

另一答案

您可以使用__setitem__方法获得更简洁的解决方案:

class Character(object):
  def __init__(self, *args):
     self.__dict__ = dict(zip(['hp', 'mp', 'st', 'ag'], args))
  def __setitem__(self, name, val):
     self.__dict__[name] += val

hero = Character(10, 4, 3, 2)
hero['hp'] = 2
print(hero.hp)

输出:

12

但是,也可以使用自定义方法实现此策略:

class Character(object):
  def __init__(self, *args):
     self.__dict__ = dict(zip(['hp', 'mp', 'st', 'ag'], args))
  def increase_stat(self, stat, value):
     self.__dict__[stat] += value

hero = Character(10, 4, 3, 2)
hero.increase_stat(stat='hp', value=2)

输出:

12

以上是关于如何获取对象属性的引用?的主要内容,如果未能解决你的问题,请参考以下文章

Fragment 的 GetTag 返回空对象引用

如何从布局中获取膨胀的片段参考?

如何从片段中的 JSON 响应中的对象获取数据

使用特定对象而不是对象属性获取核心数据

如何从 CKReference 对象中获取引用字符串

如何:创建用于绘制的 Graphics 对象