当前位置: 首页 > 面试题库 >

嵌套子对象/链接属性上的getattr和setattr?

史承福
2023-03-14
问题内容

我有一个对象(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('.'))

rgetattr并且rsetattr是插入式替代getattrsetattr,这也可以处理点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


 类似资料:
  • 我正在尝试反序列化一个 JSON 响应,其中包含一些标准字段和一个包含子类属性的 嵌套对象,例如: 字段< code>id和< code>type是标准的,所以我有一个基类< code>Base,然后扩展一些更具体的类: 如何让杰克逊读取 对象作为进一步字段值的来源?我假设我需要创建一个自定义反序列化程序,但我不确定如何具体完成此操作。

  • 我有一些文档在嵌套对象中有嵌套对象: 在这里,主文档有几个嵌套的对象(标记),对于每个标记有几个嵌套的对象(事件)。 我希望获得transfer_processed类型的事件在transfer类型的标记之后60000毫秒内发生的所有文档。为此,我需要查询tags.at、tags.type、tags.events.at和tags.events.type。我不知道如何查询:我只查询tags.event

  • 问题内容: 我有一些文档在嵌套对象中具有嵌套对象: 在这里,主文档有几个嵌套对象(标签),每个标签有几个嵌套对象(事件)。 我想获得的所有地方类型的事件文件 transfer_processed 类型的标签后发生60000毫秒 转移 。为此,我需要同时查询 tag.at , tags.type , tags.events.at 和 tags.events.type 。而且我不知道怎么做:我只设法对

  • 问题内容: 我有一个对象,它可以是任何数量的深度,并且可以具有任何现有属性。例如: 在此我想设置(或覆盖)属性,如下所示: 属性字符串可以具有任何深度,并且值可以是任何类型/事物。 如果属性键已经存在,则不需要合并对象和数组作为值。 前面的示例将产生以下对象: 如何实现这种功能? 问题答案: 此函数使用您指定的参数应添加/更新容器中的数据。请注意,您需要跟踪架构中的哪些元素是容器,哪些是值(字符串

  • 我有一个对象,可以是任何数量的层次深,可以有任何现有的属性。例如: 在此基础上,我希望设置(或覆盖)如下属性: 属性字符串可以有任何深度,值可以是任何类型/事物。 如果属性键已经存在,则不需要合并作为值的对象和数组。 上一个示例将生成以下对象: 如何实现这样的功能?