【问题标题】:How can I closely achieve ?: from C++/C# in Python?我怎样才能接近实现?:来自 Python 中的 C++/C#?
【发布时间】:2010-09-13 05:07:33
【问题描述】:

在 C# 中,我可以轻松编写以下代码:

string stringValue = string.IsNullOrEmpty( otherString ) ? defaultString : otherString;

有没有一种在 Python 中做同样事情的快速方法,还是我坚持使用 'if' 语句?

【问题讨论】:

    标签: python syntax ternary-operator syntax-rules


    【解决方案1】:

    在 Python 2.5 中,有

    A if C else B
    

    它的行为很像 ?: 在 C 中。然而,它不受欢迎的原因有两个:可读性,以及通常有更简单的方法来解决问题。例如,在您的情况下:

    stringValue = otherString or defaultString
    

    【讨论】:

    • 第二个示例 /works/,但请参阅我的评论以了解如何指定比较。
    • 这不是倒退吗?通常,由于“cond and A or B”之类的陷阱,and/or 技巧不受欢迎,其中 A 恰好是 0 之类的错误值。有一些解决方法,例如 (cond and [A] or [B])[0 ],但是添加了 if/else 语法几乎可以消除这种滥用的需要。
    • 这不是倒退。添加了 if/else 语法以“修复”人们对三元运算符的需求,从而导致他们遇到错误和/或技巧。但是,请注意我的示例如何不使用“和”。它只使用“或”,这是一种更直接的方式来执行 OP 想要的操作。没有问题。
    【解决方案2】:

    @丹

    if otherString:
       stringValue = otherString
    else:
       stringValue = defaultString
    

    这种类型的代码更长,更有表现力,但也更易读

    嗯,是的,它更长。不太确定“更具表现力”和“更具可读性”。至少,你的主张是有争议的。我什至会说这是完全错误的,原因有两个。

    首先,您的代码强调决策(相当极端)。另一方面,条件运算符强调其他东西,即值(分别是所述值的分配)。而这正是这段代码的作者想要的。决策实际上是代码的副产品。这里重要的部分是赋值操作。你的代码在很多语法噪音中隐藏了这个赋值:分支。

    您的代码表达力较差,因为它把重点从重要部分转移了。

    即使这样,您的代码也可能会胜过一些晦涩的 ASCII 艺术,例如 ?:。内联-if 会更好。就个人而言,我不喜欢 Python 2.5 引入的变体,因为它是倒退的。我更喜欢在与 C 三元运算符相同的流程(方向)中读取但使用单词而不是 ASCII 字符的东西:

    C = if cond then A else B
    

    这很容易获胜。

    遗憾的是,C 和 C# 没有这样的表达方式。但是(这是第二个论点),C 语言的三元条件运算符由来已久,以至于它本身已成为一个习语。三元运算符与“常规”if 语句一样是语言的一部分。因为它是一个成语,任何了解该语言的人都会立即正确地阅读此代码。此外,它是表达这些语义的一种极短、简洁的方式。事实上,这是可以想象到的最短路径。它极具表现力,因为它不会用不必要的噪音掩盖本质。

    最后,Jeff Atwood 写下了完美的结论:The best code is no code at all

    【讨论】:

    • 如果您认为我错了,请纠正我,但这应该是对 Dan 帖子的评论,而不是新的答案。你对他的回答有争议/有争议是对的,但我想说你说“对错”已经走得太远了。这只是意味着......(大多数物理学家站在彼此的肩膀上,而大多数计算机科学家则站在彼此的脚趾上。)
    • 顺便说一句,我明白为什么你觉得有必要将其作为答案而不是评论来回答......(Stackoverflow 不允许我编辑我的评论......)
    【解决方案3】:

    编写可读性强、富有表现力的代码从来都不是一件坏事。

    if otherString:
       stringValue = otherString
    else:
       stringValue = defaultString
    

    这种类型的代码更长,更有表现力,但也更易读,并且不太可能在路上被绊倒或错误编辑。不要害怕写出富有表现力的代码——可读的代码应该是一个目标,而不是副产品。

    【讨论】:

      【解决方案4】:

      这个问题有几个重复,例如

      本质上,2.5 之前的一般设置中的代码应该使用这个:

       (condExp and [thenExp] or [elseExp])[0]
      

      (给定 condExp,thenExp 和 elseExp 是任意表达式),因为如果 thenExp 计算结果为布尔值 False,它会避免错误结果,同时保持短路计算。

      【讨论】:

        【解决方案5】:

        顺便说一句,j0rd4n,你不要(拜托不要!)用 C# 编写这样的代码。除了IsDefaultOrNull 实际上被称为IsNullOrEmpty 之外,这纯粹是代码膨胀。 C# 为以下情况提供了合并运算符:

        string stringValue = otherString ?? defaultString;
        

        确实,这仅在 otherStringnull(而不是空)时才有效,但如果可以事先确保这一点(而且通常可以),它会使代码更具可读性。

        【讨论】:

        • 这是一个很好的观点(正如我几周前刚刚了解的 coalesce 运算符,但是从数据库查询返回空字符串的情况呢?我编写的大部分代码都使用了我们公司的数据库API,返回空字符串很多。
        • 参考我的 ruby​​ 示例,我在 C# 中编写了一个 IsBlank 扩展方法。不知道你会在 python 中做什么
        【解决方案6】:

        我还发现,仅使用“或”运算符效果很好。例如:

        finalString = get_override() or defaultString
        

        如果 get_override() 返回 "" 或 None,它将始终使用 defaultString

        【讨论】:

          【解决方案7】:

          Chapter 4 of diveintopython.net 有答案。这在 Python 中被称为与或技巧。

          【讨论】:

            【解决方案8】:

            您可以利用逻辑表达式返回其值的事实,而不仅仅是真假状态。例如,您始终可以使用:

            result = question and firstanswer or secondanswer
            

            需要注意的是,如果 firstanswer 为 false,则它不像三元运算符那样工作。这是因为问题首先被评估,假设它是真的 firstanswer 返回,除非 firstanswer 为假,所以这种用法不能像三元运算符一样。但是,如果您知道这些值,则通常没有问题。一个例子是:

            result = choice == 7 and "Seven" or "Another Choice"
            

            【讨论】:

              【解决方案9】:

              如果你用过 ruby​​,你可以写

              stringValue = otherString.blank? ? defaultString : otherString;
              

              内置的blank?方法表示null或空。
              来黑暗面吧……

              【讨论】:

                猜你喜欢
                • 2014-12-25
                • 2015-03-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-11-21
                • 2017-02-25
                • 2021-11-18
                • 1970-01-01
                相关资源
                最近更新 更多