仅当属性存在时,我才尝试获取列表中类的属性的值。如果属性不存在,我希望它得到其他东西(我知道它是内部列表,并且想要在该内部列表中获得项目的属性)。
以下代码中的示例可以运行和调试:
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:“阻止”对象没有 支持索引
我不明白为什么getattr在不应该出现的情况下在第三个argumnet上引发异常。
我的最终目标是确定列表或内部列表中所有项目的名称。
谢谢。
答案 0 :(得分:1)
您的第一种情况有效,因为block_num = 2
是列表,blocks[2][0]
,<__main__.Block at 0x....>
是对象blocks[2]
时
在第一种情况下,您为getattr(blocks[block_num], 'block_name', blocks[block_num][0].block_name)
拥有block_num = 2
,blocks[block_num]
是一个列表,并且该列表将不包含block_name
,因此默认值{{ 1}}返回
在第二种情况下,对于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)
答案 1 :(得分:1)
我认为您理解为什么在第二个示例中,第三个参数引发错误-这是因为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()
时,在执行函数之前,将同时评估三个参数。在我介绍的表达式中,它们按照以下顺序进行求值:
if hasattr(blocks[block_num], 'block_name')
blocks[block_num].block_name
(如果1为真)blocks[block_num][0].block_name
(如果1为假)应该可以解决您的问题。