如果存在则简写if语句

5

我希望你能帮我做的是:

if myObject:  # (not None)
    attr = myObject.someAttr
else:
    attr = ''

尽可能避免使用三元表达式。是否有类似以下的东西:
attr = myObject.someAttr || '' ? 

我考虑创建自己的函数,例如:

get_attr_or_default(instance,attr,default):
    if instance:
        return instance.get_attribute(attr)
    else:
        return default

但如果我听到Python没有这方面的快捷方式,我会感到惊讶。

总结:

我尝试了这两种方法,以下是结果:

class myClass(Models.model):
    myObject = model.foreignKey('AnotherClass')

class AnotherClass(Models.model):
    attribute = models.charField(max_length=100,default = '')


attr = myClass.myObject.attribute if myClass.myObject else '' # WORKED
attr = myClass.myObject and myClass.myObject.attribute # WORKED with NONE as result
attr = myClass.myObject.attribute or ''  # Raises an error (myObject doesn't have attribute attribute)
try: attr = myClass.myObject.attribute
except AttributeError: attr = ''  # Worked

感谢您的回答!

2
为什么要“尽可能避免三元表达式”???那正是它们存在的目的。此外,请注意 bool(myObject) 可能会评估为 False,即使 myObject is not None - 空字符串/列表/元组/字典/集合、数值零(int/float等)和相当多的其他非内置类型在布尔上下文中具有false值。 - bruno desthuilliers
我被告知尽可能避免三元表达式,因为它很难阅读,但我意识到三元表达式并不那么难理解(不像PHP)。 - Kobz
6个回答

11

@traceur 这是我想到的第一件事,所以我加上了它。其他答案解释得更好。:) 谢谢。 - Grijesh Chauhan
2
到目前为止,最符合惯用语的答案。 - ebarr

3
如果myObjectNone,则将attr设置为None,如果它是一个合适的对象,则将其设置为someAttr
attr = myObject and myObject.someAttr

右侧的评估只有在需要该值时才执行,请参见Python Docs,其中说到:

对于and,如果左侧等同于False,则不会评估右侧,并返回左侧的值。

这与C#中的?? null-coalsecing运算符相同,请参见http://msdn.microsoft.com/en-us/library/ms173224.aspx
请注意,如果您的对象上有布尔运算符,则此方法将无法正常工作。如果是这样,您需要使用myObject is not None

@barr 我曾经觉得Python的and/or在一般情况下很难解析,因为我已经用C++做了20年,但是我认为通过良好的语法高亮,关键字会突出显示。最终,你会习惯它,就像其他任何东西一样。 - Macke
@Macke 我的意思不是那个意思,我的意思更多的是,在各种情况下,这对我来说并不是显而易见的。 - ebarr
Macke,我建议您添加来自Python文档的*如果and的左侧等于False,则不评估右侧,并返回左侧值。*,而不是链接C#。 - Grijesh Chauhan
这并不完全是OP想要的。区别在于当myObject为None时:答案返回None,而OP想要''。在许多情况下,这不会改变程序的功能,但在某些边缘情况下可能会有所不同,例如如果某个库明确需要一个str对象。 - hvb

2
很酷的方式(即使没有三元表达式):
attr = getattr(myObject or object(), 'someAttr', '')

object() 会返回一个新的无特征对象(引用自官方文档)。

如果 myObject 是空的,myObject or object() 将会返回 object()

逻辑:

    myObject is empty?
          / \
         /   \ N
        /     \ 
     Y /    getattr(myObject, ...) returns that attribute 
      /          
     /
    /
getattr(object(), ...) will produce '' (empty string)

1

你最多可以做到:

try:
    attr = myObject.someAttr
except AttributeError:
    attr = ''

@traceur,你是什么意思? - sshashank124
1
不要使用裸的 except,更具体一些,例如 except AttributeError: - anon582847382
@AlexThornton,非常感谢。我已经相应地更新了答案。 - sshashank124
@traceur,非常感谢。我已经相应地更新了答案。 - sshashank124
这违反了PEP8指南(http://legacy.python.org/dev/peps/pep-0008/) - ebarr
将所有内容都放在两行上。请查看PEP8的“其他建议”部分。 “虽然有时将if / for / while与小代码块放在同一行上是可以的,但绝不要对多子句语句这样做。此外,请避免折叠太长的行!” - ebarr

1

如果您真的坚持用奇怪、复杂和棘手的方式做事,可以尝试:

val = (myObject is not None and myObject.attr) or default

这是一种旧的(并且相当有争议的)三元表达式习惯用法。请注意,如果bool(myObject.attr)计算为False(大多数空容器、空字符串、数字零和相当多的非内置类型都会出现这种情况),则此方法将不会按预期工作。

简而言之:使用三元表达式,这就是它的作用。


0

你所建议的,但稍有不同:

if myObject:
    attr = myObject.someAttr or ''

如果myObject.someAttrNone,它将会忽略它并在attr中放置''

如果myObject为None,这将失败。 - hvb
@hvb 我假设他仍然会使用 if myObject: 检查。我会进行编辑。 - Tim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接