python - getattr 和 setattr 在嵌套子对象/链接属性上?

标签 python python-2.7 recursion attributes setattr

我有一个对象 (Person),它有多个子对象 (Pet, Residence) 作为属性。我希望能够像这样动态设置这些子对象的属性:

class Person(object):
    def __init__(self):
        self.pet = Pet()
        self.residence = Residence()

class Pet(object):
    def __init__(self,name='Fido',species='Dog'):
        self.name = name
        self.species = species

class Residence(object):
    def __init__(self,type='House',sqft=None):
        self.type = type
        self.sqft=sqft


if __name__=='__main__':
    p=Person()
    setattr(p,'pet.name','Sparky')
    setattr(p,'residence.type','Apartment')
    print p.__dict__

目前我得到了错误的输出:{'pet': <__main__.Pet object at 0x10c5ec050>, 'residence': <__main__.Residence object at 0x10c5ec0d0>, 'pet.name': 'Sparky', 'residence.type': 'Apartment'}

如您所见,而不是设置 name Pet 上的属性Person 的子对象, 新属性 pet.name创建于 Person .

  • 我无法指定 person.petsetattr()因为不同的子对象将通过相同的方法设置,如果/当找到相关键时,该方法会解析一些文本并填充对象属性。

  • 有没有一种简单/内置的方法来完成这个?

  • 或者我可能需要编写一个递归函数来解析字符串并调用getattr()多次,直到找到必要的子对象,然后调用 setattr()在那个找到的子对象上?

最佳答案

您可以使用 functools.reduce :

import functools

def rsetattr(obj, attr, val):
    pre, _, post = attr.rpartition('.')
    return setattr(rgetattr(obj, pre) if pre else obj, post, val)

# using wonder's beautiful simplification: https://stackoverflow.com/questions/31174295/getattr-and-setattr-on-nested-objects/31174427?noredirect=1#comment86638618_31174427

def rgetattr(obj, attr, *args):
    def _getattr(obj, attr):
        return getattr(obj, attr, *args)
    return functools.reduce(_getattr, [obj] + attr.split('.'))

rgetattrrsetattrgetattrsetattr 的直接替换, 它还可以处理带点的 attr 字符串。


import functools

class Person(object):
    def __init__(self):
        self.pet = Pet()
        self.residence = Residence()

class Pet(object):
    def __init__(self,name='Fido',species='Dog'):
        self.name = name
        self.species = species

class Residence(object):
    def __init__(self,type='House',sqft=None):
        self.type = type
        self.sqft=sqft

def rsetattr(obj, attr, val):
    pre, _, post = attr.rpartition('.')
    return setattr(rgetattr(obj, pre) if pre else obj, post, val)

def rgetattr(obj, attr, *args):
    def _getattr(obj, attr):
        return getattr(obj, attr, *args)
    return functools.reduce(_getattr, [obj] + attr.split('.'))

if __name__=='__main__':
    p = Person()
    print(rgetattr(p, 'pet.favorite.color', 'calico'))
    # 'calico'

    try:
        # Without a default argument, `rgetattr`, like `getattr`, raises
        # AttributeError when the dotted attribute is missing
        print(rgetattr(p, 'pet.favorite.color'))
    except AttributeError as err:
        print(err)
        # 'Pet' object has no attribute 'favorite'

    rsetattr(p, 'pet.name', 'Sparky')
    rsetattr(p, 'residence.type', 'Apartment')
    print(p.__dict__)
    print(p.pet.name)
    # Sparky
    print(p.residence.type)
    # Apartment

关于python - getattr 和 setattr 在嵌套子对象/链接属性上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31174295/

相关文章:

python - 无法安装python图像库

java - 在 Java 中将可变长度的整数数组倒数到零

java - 使用 Java 中的分治法查找最大数

python - 根据属性将两个人匹配在一起

python - 从数据框中提取文本特征

python : module attributes missing in python script but not in interpreter

python - 需要帮助解决 Anaconda Python 2.7 x32 的问题

python - Pillow 未安装在 Apple Silicon 上

python - 如何找到列表中的最大项目数,使得某些对在输出中不在一起?

recursion - Lisp 中的递归加法