Skip to content

条件表达式

在学习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 逻辑操作符对于常量字面量仅支持:

  • 布尔类型

  • 整数类型

  • 浮点数类型

  • 数组类型

  • 字典类型

gdscript
"" and "hello" # 错误,无法在字符串中运用`and`运算符

推荐的写法是先将值放入变量中,或写成更具语义的形式

gdscript
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() # 推荐写法,可读性更高

但是更推荐将布尔值作为逻辑运算符的操作数

andor是短路求值运算符

  • 对于and,当左边的表达式结果为false时,便会否定整个表达式,不会再去计算右边的结果

  • 对于or,当左边的表达式结果为true时,便会肯定整个表达式,不会再去计算右边的结果

gdscript
# and是短路求值,如果object为null,那么就不会去调用has_method方法,而造成运行时错误
print(object != null and object.has_method("foo"))

逻辑运算优先级:not>and>or,可以使用括号来改变运算优先级

在下面的例子中,condition_1condition_2是不同的结果

  • condition_1:

    ①. 先计算 not falsetrue

    ②. 再计算true or true,因为or左边是true,所以结果直接就是true

    ③. 最后计算my_str and truefalse

  • condition_2

    ①. 先计算not falsetrue

    ②. 再计算my_str and true,因为my_strfalse,所以结果直接就是false

    ③. 最后计算false or truetrue

gdscript
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 Button

x 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()
对于StringStringName,右边的字符串包含左边的字符串时(字符值一致,顺序一致)true,否则false

对于数组,右边的数组中包含左边的元素时true,否则false

对于字典,右边的字典中包含左边的键时
true,否则false

对于对象,右边的对象实例中包含左边的变量名(必须为字符串)时
true,否则为false(和字典一致)

not in与上述规则相反

相等比较是两个等号(==),而不是一个等号,一个等号是赋值号(=)

==!= 运算符在有些情况下允许比较不同类型的值(例如 1 == 1.0 的结果为真),但在其他情况下可能会发生运行时错误。

gdscript
var b = "Hello World"
var c = 10
print(b == c) # 将会触发运行时错误,无法对字符串和整数运用`==`操作符

若你不能确定操作数的类型,可使用 is_same() 函数来进行安全比较(但请注意,该函数对类型和引用更加严格)

gdscript
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),会触发编辑器报错导致无法运行游戏,因为此类检查没有意义

gdscript
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是一个不确定类型的变量;输出false

innot in在字符串中的检查只适用于StringStringName,无法运用于NodePath,进行字符串检查时,遵循大小写一致,字符顺序一致的规则

gdscript
print("hello" in "Hello World!") # 输出false
print("olleH" in "Hello World!") # 输出false

我们不难发现,在上面的各种条件表达式中,如果将其作为参数传入print,那么输出的结果要么是true,要么是false

也就是说,我们可以直接将条件表达式赋值给一个布尔类型的变量

gdscript
var year: int = 2025
var is_leap_year:bool = (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

布尔语境

在布尔语境也就是条件表达式中,只要变量的值不是其类型的默认值,那么其评估结果就是true,否则为false

部分类型的默认值和条件表达式结果:

类型默认值在条件表达式中等同于
Object及其子类nullfalse
int / float0/0.0false
Array[](空数组)false
String""(空字符串)false
Vector2Vector2(0, 0)false

也就是说可以直接将一个变量作为一个条件表达式:

gdscript
# 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)会更清晰

特别地,当使用布尔类型的变量作为条件表达式时,更推荐直接使用变量名本身,而不是写完整的比较式,这样更简洁明了,也符合通用写法习惯:

gdscript
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 就有点多余

练习

  1. 看看这些表达式的结果是什么(true 或 false)
gdscript
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”
gdscript
var a := ""          
var b := []          
var c: Object = null  
var d := 0           
var e := Vector2()
  • 下面这些表达式的结果是 true 还是 false 呢?能解释原因嘛?
gdscript
"Hello" is String
10 is int
[] is not Array
Node2D.new() is CanvasItem
  • 尝试判断 print() 会输出什么,并且试着找出下面代码的bug
gdscript
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)         # ?