条件表达式
在学习if语句前,我们需要先了解什么是条件表达式
条件表达式是一个结果为布尔值的逻辑运算表达式
也就是说,一个单独的布尔值即为一个条件表达式
条件表达式使用如下运算符进行计算:
逻辑运算符
组合多个条件表达式
计算并组合关系表达式的结果
对布尔变量或常量、支持布尔语境类型的变量进行逻辑运算
| 运算符 | 名称 | 描述 | 示例 | 运算结果 |
|---|---|---|---|---|
not/! | 逻辑非 | 否定(反转)结果 | not x/not 1+1==2``! x/! 1+1==2 | 当右边的值为true时结果为false,否则为true |
and/&& | 逻辑与 | 两边必须同时满足 | x and y/1+1==2 and 2+2==4``x && y/1+1==2 && 2+2==4 | 左右两边的值都为true时,结果为true,否则为false |
or/|| | 逻辑或 | 任意一边满足 | x or y/1+2==3 or 2+3==5``x || y/1+2==3 || 2+3==5 | 左右两边任意一边为true时,结果为true,否则为false |
!/&&/||是其他编程语言中的逻辑运算符形式,也同样适用于GDScript,用法也相同,但是是不推荐使用的形式,为了可读性推荐使用not/and/or
not是一元运算符,只能用于一个操作数
不要将 and / or 运用在常量字面量上,特别是非布尔类型的常量。在 GDScript 中,and / or 逻辑操作符对于常量字面量仅支持:
布尔类型
整数类型
浮点数类型
数组类型
字典类型
"" and "hello" # 错误,无法在字符串中运用`and`运算符推荐的写法是先将值放入变量中,或写成更具语义的形式
var my_str_1 := ""
var my_str_2 := "hello"
my_str_1 and my_str_2 # 正确写法,结果为false
my_str_1.is_empty() and my_str_2.is_empty() # 推荐写法,可读性更高但是更推荐将布尔值作为逻辑运算符的操作数
and和or是短路求值运算符
对于
and,当左边的表达式结果为false时,便会否定整个表达式,不会再去计算右边的结果对于
or,当左边的表达式结果为true时,便会肯定整个表达式,不会再去计算右边的结果
# and是短路求值,如果object为null,那么就不会去调用has_method方法,而造成运行时错误
print(object != null and object.has_method("foo"))逻辑运算优先级:not>and>or,可以使用括号来改变运算优先级
在下面的例子中,condition_1和condition_2是不同的结果
condition_1:①. 先计算
not false→true②. 再计算
true or true,因为or左边是true,所以结果直接就是true③. 最后计算
my_str and true→falsecondition_2:①. 先计算
not false→true②. 再计算
my_str and true,因为my_str是false,所以结果直接就是false③. 最后计算
false or true→true
var my_str: String = "" # 在布尔语境下空字符串是false
var condition_1: bool = my_str and (true or not false)
var condition_2: bool = my_str and true or not false关系运算符
| 运算符 | 作用 | 示例 | 说明 |
|---|---|---|---|
== | 相等 | x == y/1+2==3 | 左右两边值相等时,结果为true,否则为false |
!= | 不相等 | x != y/1+1!=2 | 左右两边值结果不相等时,结果为true,否则为false |
> | 大于 | x > y/1+3>2 | 左边的值比右边的值大时,结果为true,否则为false |
< | 小于 | x < y/1+2<1+1 | 左边的值比右边的值小时,结果为true,否则为false |
<= | 小于或等于 | x <= y/1+2<=3 | 左边的值比右边的值小或相等时,结果为true,否则为false |
>= | 大于或等于 | x >= y/1+3>=2 | 左边的值比右边的值大或相等时,结果为true,否则为false |
is is not | 检查类型关系 | x is Node$Button is Buttonx is not Node$Button is not Button | 对于集合除外的引用类型,可以被转换为目标类型时为true,否则为false对于值类型和集合,类型完全匹配时为 true,否则为false is not与上述规则相反 |
in not in | 检查包含关系 | x in y"s" in "string"1 in [1, 2, 3]"key" in {"key":1, "key_2":2}"variable_name" in get_parent()x not in y"s" not in "string"1 not in [1, 2, 3]"key" not in {"key":1, "key_2":2}"variable_name" not in get_parent() | 对于String和StringName,右边的字符串包含左边的字符串时(字符值一致,顺序一致) 为true,否则false对于数组,右边的数组中包含左边的元素时为 true,否则false对于字典,右边的字典中包含左边的键时为 true,否则false对于对象,右边的对象实例中包含左边的变量名(必须为字符串)时为 true,否则为false(和字典一致)not in与上述规则相反 |
相等比较是两个等号(==),而不是一个等号,一个等号是赋值号(=)
== 和 != 运算符在有些情况下允许比较不同类型的值(例如 1 == 1.0 的结果为真),但在其他情况下可能会发生运行时错误。
var b = "Hello World"
var c = 10
print(b == c) # 将会触发运行时错误,无法对字符串和整数运用`==`操作符若你不能确定操作数的类型,可使用 is_same() 函数来进行安全比较(但请注意,该函数对类型和引用更加严格)
var a = 10
var b = 10.0
print(is_same(a, b)) # 输出false
print(a == b) # 输出true要比较经过数学运算后的浮点数,请改用 is_equal_approx() 和 is_zero_approx() 函数,详见以往的章节
is用于进行类型检查,其行为与as关键字相似,is not的行为与is相反
is 的结果是 true 或 false
as 的结果是对象实例或空
对于非集合类型的引用类型(
Node,Button,Node2D等),如果需要检查的值的类型不是目标类型或其父类,那么其结果就是false对于值类型和集合,使用更严格的检查,必须完全匹配类型
对于已知其类型的变量或常量字面量,如果使用
is(is not)进行检查后其结果必定是false(true),会触发编辑器报错导致无法运行游戏,因为此类检查没有意义
var node_2 := Node2D.new()
var my_str := "Hello World!"
print(node_2 is Node2D) # 输出true
print(node_2 is Node) # 输出true
print(node_2 is Button) # 报错,表达式的类型为 "Node2D",因此它不会是 "Button" 类型
print(my_str is String) # 输出true
print(my_str is StringName) # 报错,表达式的类型为"String",因此它不会是"StringName"类型
var my_variant = "Hello World!"
print(my_variant is String) # 输出true
print(my_variant is StringName) # 不会报错,因为my_variant是一个不确定类型的变量;输出falsein和not in在字符串中的检查只适用于String和StringName,无法运用于NodePath,进行字符串检查时,遵循大小写一致,字符顺序一致的规则
print("hello" in "Hello World!") # 输出false
print("olleH" in "Hello World!") # 输出false我们不难发现,在上面的各种条件表达式中,如果将其作为参数传入print,那么输出的结果要么是true,要么是false
也就是说,我们可以直接将条件表达式赋值给一个布尔类型的变量
var year: int = 2025
var is_leap_year:bool = (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)布尔语境
在布尔语境也就是条件表达式中,只要变量的值不是其类型的默认值,那么其评估结果就是true,否则为false
部分类型的默认值和条件表达式结果:
| 类型 | 默认值 | 在条件表达式中等同于 |
|---|---|---|
Object及其子类 | null | false |
int / float | 0/0.0 | false |
Array | [](空数组) | false |
String | ""(空字符串) | false |
Vector2 | Vector2(0, 0) | false |
也就是说可以直接将一个变量作为一个条件表达式:
# Object 类型的变量
if object:
# 等价于 object != null
pass
# 整数
if my_integer:
# 等价于 my_integer != 0
pass
# 数组
if my_array:
# 等价于 not my_array.is_empty()
pass
# 取反使用 not
if not object:
# 等价于 object == null
pass
if not my_integer:
# 等价于 my_integer == 0
pass
if not my_array:
# 等价于 my_array.is_empty()
pass但是,这会降低代码可读性,尤其对于新手而言不容易一眼看出表达的含义。更明确地写出完整的比较表达式(如 object != null)会更清晰
特别地,当使用布尔类型的变量作为条件表达式时,更推荐直接使用变量名本身,而不是写完整的比较式,这样更简洁明了,也符合通用写法习惯:
var year: int = 2025
var is_leap_year:bool = (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
# 不推荐形式
if is_leap_year == true:
print("是闰年")
# 推荐的写法
if is_leap_year:
pirnt("是闰年")理由跟上面一样哦:可读性高、表达清晰,变量名本身就说明了意图,再加个 == true/== false 就有点多余
练习
- 看看这些表达式的结果是什么(true 或 false)
print(1 + 1 == 2 and 2 + 2 == 5)
print("hello" in "Hello World!")
print(3 > 1 or 4 < 2)
print(not false and true)
print(not "" or not "fallback")- 根据前面学的“哪些值在布尔语境中为 false”
var a := ""
var b := []
var c: Object = null
var d := 0
var e := Vector2()- 下面这些表达式的结果是
true还是false呢?能解释原因嘛?
"Hello" is String
10 is int
[] is not Array
Node2D.new() is CanvasItem- 尝试判断
print()会输出什么,并且试着找出下面代码的bug
var a = 10
var b = "10"
var c = "hello"
var d = ["hello", "world"]
var e = null
print(a == b) # ?
print(b in c) # ?
print(c in d) # ?
print(e == null) # ?
print(a and b) # ?