getattr访问第三个参数,即使条件不是m

2024-10-06 12:21:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图只在属性存在的情况下获取列表中类的属性值。如果属性不存在,我希望它获取其他内容(我知道它是内部列表,并且希望在该内部列表中获取项的属性)。你知道吗

下面代码中的示例,可以运行和调试:

class Block(object):
    def __init__(self, name):
        self.block_name = name


blocks_list = [Block("d"), Block("d"), Block("d")]
blocks = [Block("a"), Block("b"), blocks_list, Block("c")]

# this is ok
block_num = 2
name = getattr(blocks[block_num], 'block_name', blocks[block_num][0].block_name)

# this is raises exception
block_num = 0
name = getattr(blocks[block_num], 'block_name', blocks[block_num][0].block_name)

例外情况:

name = getattr(blocks[block_num], 'block_name', blocks[block_num][0].block_name) TypeError: 'Block' object does not support indexing

我不明白为什么getattr在第三个argumnet上引发异常,而它不应该引发异常。你知道吗

我的最终目标是确定列表或内部列表中所有项目的名称。你知道吗

谢谢。你知道吗


Tags: nameself列表属性objectis情况this
2条回答

您的第一个case在block_num = 2blocks[2][0]<__main__.Block at 0x....>时起作用,因为blocks[2]是一个列表

在第一种情况下,您有getattr(blocks[block_num], 'block_name', blocks[block_num][0].block_name)表示block_num = 2blocks[block_num]是一个列表,并且该列表不包含block_name,因此返回默认值blocks[block_num][0].block_name

在第二种情况下,对于block_num=0,在调用函数时会计算默认值,但最终会抛出TypeError: 'Block' object is not subscriptable,因为blocks[0]是一个对象<__main__.Block at 0x....>,并且不能索引对象

为了保持一致,一个建议可能是改为blocks_list[block_num].block_name

更新后的代码可能看起来像

class Block(object):
    def __init__(self, name):
        self.block_name = name


blocks_list = [Block("d"), Block("d"), Block("d")]
blocks = [Block("a"), Block("b"), blocks_list, Block("c")]

block_num = 2
name = getattr(blocks[block_num], 'block_name', blocks_list[block_num].block_name)
print(name)

block_num = 0
name = getattr(blocks[block_num], 'block_name', blocks_list[block_num].block_name)
print(name)

这给了你

d
a

我想您理解为什么在您的第二个示例中,第三个参数会引发错误—这是因为blocks[0]不是一个列表,所以您不能索引到它。我还认为您希望不会出现错误,因为只有当blocks[0]没有属性'block_name'(因为getattr()的第三个参数是默认值)时,才应该计算第三个参数。你知道吗

不幸的是,它不是这样工作的。您给出的第三个参数getattr()(即blocks[block_num][0])是在调用函数时计算的,而不是在执行函数时计算的。你知道吗

不过,有一个解决方法:三元运算符可以做与getattr()相同的事情(如果存在,则返回一个属性,如果不存在,则返回一个默认值),但是在执行时而不是在调用时计算其他参数:

name = blocks[block_num].block_name if hasattr(blocks[block_num], 'block_name') else blocks[block_num][0].block_name

在对getattr()的调用中,在执行函数之前,这三个参数将同时求值。在我给出的这个表达式中,它们的求值顺序如下:

  1. if hasattr(blocks[block_num], 'block_name')
  2. blocks[block_num].block_name(如果1为真)
  3. blocks[block_num][0].block_name(如果1为假)

这应该能解决你的问题。你知道吗

相关问题 更多 >