{ }codelper

学习 › Python

流程控制 · 08

布尔值与三元运算符

把真假存进变量、在两个值里选一个、问“是不是其中之一”。

在“条件语句”一课里,比较是直接写在 if 里的。
这次把比较的结果当作值来用。
下面的例子读入星期和游客的年龄,把“是不是周末”和“有没有儿童”存进变量,再输出门票的总和:周末每人 12,平日每人 8。

day = input().strip()ages = list(map(int, input().split())) weekend = day in ("sat", "sun")   # 포함 검사의 결과(참·거짓)를 변수에 담아요child = False                     # 깃발: 아직 어린이를 못 봤어요for age in ages:    if age < 13:        child = True price = 12 if weekend else 8      # 두 값 중 하나를 골라요print("weekend" if weekend else "weekday")print(price * len(ages))print("child" if child else "adults")
stdin
sat
35 41 9
stdout
weekend
36
child

要点

  • 比较的结果(age < 13)是一个布尔值(真或假)。
    它和数字、字符串一样,可以存进变量反复使用。
    存好的值直接写在条件的位置:if (weekend) 就够了,不用加 == true。
  • 标记是把布尔变量和循环一起用的写法。
    循环前先设为假,遇到要找的东西就改成真。
    循环结束后,它就告诉你“有没有至少一个”。
  • 三元运算符按条件在两个值里选一个。
    if 选的是要做的事,三元选的是值,所以可以直接写在赋值的右边或输出里面。
  • 三元只在很短的时候用。
    一旦要在三元里再套三元,改用 if 和 else 写会更容易读。
  • 包含判断问的是“这个值是不是这些值中的一个”。
    不用把 == 用 || 连成一长串,而是把这些值放进列表,只问一次“在不在里面”。
    答案是布尔值。
  • 直接输出布尔值,各语言不一样:Python 和 C# 输出 True,JavaScript、Java、Craykon 输出 true,C 和 C++ 输出 1。
    所以例子用三元选出字符串再输出。

各语言的写法

Pythonweekend = day in ("sat", "sun"),标记从 child = False 变成 True。
三元写作 12 if weekend else 8 — 为真时的值在最前面。
取反是 not weekend
JavaScriptconst weekend = ["sat", "sun"].includes(day);,三元是 weekend ? 12 : 8。
in 不是包含判断:"sat" in ["sat", "sun"] 是 false(它问的是有没有这个下标,不是值)
TypeScript和 JavaScript 一样。
类型名是 boolean
Javaboolean weekend = List.of("sat", "sun").contains(day);,三元是 weekend ? 12 : 8。
和单个字符串比较用 day.equals("sat")
C#bool weekend = rest.Contains(day); — 用在数组上需要 using System.Linq;。
三元是 weekend ? 12 : 8
C++bool weekend = std::find(rest.begin(), rest.end(), day) != rest.end();(<algorithm>),三元是 weekend ? 12 : 8。
直接输出 bool 得到 1,先送入 std::boolalpha 才是 true
C要写 #include <stdbool.h> 才能用 bool、true、false。
没有包含判断的工具,只能用循环逐个看 strcmp(day, rest[i]) == 0。
单个字符可以用 strchr("aeiou", c) != NULL。
三元是 weekend ? 12 : 8
Craykonweekend = ["sat", "sun"].包含(day);,标记从 child = 假; 变成 真。
三元是 weekend ? 12 : 8。
字符串也可以这样问:"aeiou".包含("e")

常见错误

用 == "sat" or "sun" 问是不是二者之一Python · JavaScript · TypeScript · C · C++ · Craykon

day = "mon"
if day == "sat" or "sun":
    print("weekend")
else:
    print("weekday")

→ weekend — 明明是星期一却成了周末。它被读成 (day == "sat") or "sun",前面为假时 "sun" 就成了条件,而非空字符串算作真

两边都写成比较(day == "sat" or day == "sun")。
用包含判断更短(day in ("sat", "sun"))。
Java 和 C# 会用编译错误拦住这段代码。

在 else 里把标记改回了假

int[] ages = {9, 35, 41};
boolean child = false;
for (int age : ages) {
    if (age < 13) child = true;
    else child = false;
}
System.out.println(child ? "child" : "adults");

→ adults — 明明有 9 岁的,却说没有儿童。标记在 9 时变成真,又在 35 和 41 时被改回假。这样写,标记里只剩下“最后一位游客是不是儿童”。用哪种语言写都一样

删掉 else。
标记只在循环前设一次假,循环里只把它改成真。
在循环里写 child = age < 13; 这样每次重新赋值,也是同样的错误。

三元不加括号就接在 + 后面JavaScript · TypeScript · Python · C++ · Craykon

const ok = false;
console.log("Result: " + ok ? "yes" : "no");

→ yes — + 先算。字符串 "Result: false" 成了条件,非空字符串永远为真。Craykon 也输出 yes。Python 的 "Result: " + "yes" if ok else "no" 只输出 no,C++ 的 std::cout << ok ? "yes" : "no"; 输出 0

把整个三元用括号括起来:"Result: " + (ok ? "yes" : "no")。
Java 和 C# 在没有括号时会报编译错误。

各语言的差异
把不是布尔值的东西写在条件的位置时,各语言分成两派。
Java 和 C# 用编译错误拦住。
C、C++、Python、JavaScript、TypeScript、Craykon 会把 "sun" 这样的值也当作真,继续往下走。
什么算作假,各语言也不一样:空列表在 Python 里是假,在 JavaScript 和 Craykon 里却是真。
第一个和第三个错误悄悄给出错误答案,原因就在这里。
养成只在条件里写比较或布尔变量的习惯,就安全了。

练习题