三位运算符 if else

Java中的三位运算符是用 StringUtils.isNotEmpty(nickname) ? nickname : "" 来实现的。Python中是用x if cond else y来实现的(突然换种语法感觉不太适应)

// Java
int a = 2;
int b = 1;

int result = a >= b ? a : b;
# Python
a = 2
b = 1

# if条件成立返回if前面的表达式,if条件不成立返回else对应的表达式
result = a if a >= b else b

Python 不用 ?:,而用 x if cond else y,是一个有意的语言设计选择,核心是让代码按自然语序读起来更清楚,降低嵌套时的可读性灾难。Python 确实在“短”与“可读”之间,经常优先后者。

为什么不用 ? : 主要有几个原因:

  1. Python 语法哲学偏“可读性优先”: ?: 很短,但对很多人(尤其新手)不直观。a if cond else b 基本就是英文句子:“如果 cond,就 a,否则 b”。
  2. 避免 C/Java 风格三元在复杂表达式里的“符号噪音”,像这种在 ?: 里嵌套时很容易变难读:a ? b : c ? d : e, Python 版本虽然也可能复杂,但关键词更显眼: b if a else d if c else e
  3. 和 Python 的关键字风格一致:Python 很多控制结构都偏好关键字而不是符号:and/or/not、is、in。if … else … 延续了这种风格。
  4. 历史上确实讨论过:Python 社区当年为“条件表达式”讨论了很久,最后选择了现在这个写法,而不是 ?:。不是没想到 ?:,而是权衡后主动没选。

适用场景:

  • 建议只在简单场景用:status = “adult” if age >= 18 else “minor”
  • 如果分支逻辑一复杂,就改普通 if/else,这也符合 Python 风格。

or 布尔逻辑运算符

如果 or 前面的布尔表达式为True取当前表达式的值,如果为False取or后面的表达式的值,常用来判断值为空(值为空则为False)给一个默认值。 or 是三元运算符的一种情况下的简写。

flag = False
# 默认值1
print(flag or "默认值1")
# 默认值2
print([] or "默认值2")
# 默认值3
print("" or "默认值3")
# openai
print("openai" or "默认值4")
x = 5
result = "大于0" if x > 0 else "小于等于0"

flag = True
res1 = "是" if flag else "否"
res2 = flag or "否"  # 如果 flag 是 False,返回 "否"

# 返回第一个为 True 的值,否则返回最后一个值
a = 0
b = ""
c = "hello"
result = a or b or c
print(result)  # 输出:"hello"
  • if else:支持任意场景,条件为真时可以返回任意值
  • or : 一般直接判断某个变量的值是否True,为真则直接返回当前值,不为真则返回后面的值,而if else 为真时是可以返回任意表达式的。or还支持连续使用。

取反not

一般其它开发语言中取反操作使用感叹号!,而Python对bool值取反使用not关键字, 有点类似于SQL语法。

flag = False
# True
print(not flag)

print(1 in [1, 2, 3])
print(4 not in [1, 2, 3])

Python 选择 not 而不是 !,not 的选择确实体现了 Python 一贯的取舍,不是追求最短输入,而是追求“更容易读对”。

通常有这几层考虑:

  1. 可读性: if not ready: 对英文阅读更自然,接近自然语言。相比 if !ready,关键字更“语义化”。
  2. 语法一致性:Python 逻辑运算整体是单词体系:and / or / not。不用 && / || / !,风格统一,学习成本更平滑。
  3. 降低符号密度:符号多时,表达式容易“眼花”,尤其对初学者和跨语言读者。 Python 倾向把控制与逻辑写得更像“句子”。
  4. 避免与其他符号组合造成视觉负担: 像 != 这种比较符号仍保留(因为非常通用),但一元逻辑取反用单词能减少连串符号阅读负担。

关键字 is(内存地址)

is 用来判断两个变量是否指向同一个对象(同一内存身份),不是判断值是否相等。

  • is:比较对象身份内存地址(identity)
  • ==:比较对象值(equality)

Java中判断内存地址是使用 ==,判断值是否相等使用equals()

Foobar a = new Foobar("a");
Foobar b = new Foobar("b");

System.out.print(a == b)

if (a == null) {
	System.out.print("a is null")
}

Python中使用is关键字判断是否为同一个内存地址,使用 == 判断值是否相等,在==符号上Python和Java的意义完全不一样。

 a = [1, 2]
 b = [1, 2]
 c = a

 print(a == b)  # True,值相同
 print(a is b)  # False,不是同一个对象
 print(a is c)  # True,c 和 a 指向同一个对象

# Python
foobar = None
if foobar is None:
    print('foobar = None')

# 常见正确用法是和 None 比较,不建议用 is 比较数字、字符串等“值”,因为可能受实现细节影响,语义也不对。
if x is None:
    ...
if x is not None:
      ...

match case 模式匹配

Java中使用 switch case 预发,要匹配多个值需要写多次case只是不写对应的代码块即可。

int day = 3;
switch (day) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        System.out.println("工作日");
        break;
    case 6:
    case 7:
    	 if (day == 6) {
			 	  System.out.println("周六");
			 } else if (day == 7) {
					System.out.println("周末");
			 }
        
        break;
    default:
        System.out.println("无效日期");
        break;
}

Python中使用match关键字,case 一次匹配多个值时使用 |,不用像Java那样还要在另起一行(这点语法更简洁)满足case值时还可以使用 if 守卫条件,满足if条件才能进入case,Java还要在case里面判断,对于简单的条件判断Python的这种方式更加简洁,而且不需要break关键字。

match 表达式:
	case1:
		操作1
	case2 if 条件表达式:
		操作2
	case3 |4:
		操作4
	case:
		默认操作

Python 想解决的不是传统 switch 那个问题,而是更强的“结构化匹配”问题,所以直接引入了 match, 这比 switch 强很多,语义也不同,命名上刻意区分, Python 这个特性本质上是“pattern matching”,叫 match 更准确,避免误解。

  1. 传统 switch 能力太窄:很多语言的 switch 主要是“一个值和一组常量比较”。Python 社区长期觉得这种能力用 if/elif 已经够了,没必要单独加关键字。
  2. Python 需要的是模式匹配,不只是值匹配:match 可以按“数据形状”匹配并解构,比如:
  • 元组/列表结构
  • 字典键结构
  • 类对象字段
  • 还可以加守卫条件(if)
from dataclasses import dataclass


# 类对象模式匹配示例用的数据类
@dataclass
class Point:
    x: int
    y: int


def demo_match(value):
    match value:
        # 1) case 单值(字面量)
        case 0:
            return "单值: zero"

        # 2) case 多值(| 或模式)
        case 1 | 2 | 3:
            return "多值: one/two/three"

        # 3) case 解构:列表
        case [x, y]:
            return f"列表解构: 两个元素 x={x}, y={y}"
        case [first, *rest]:
            return f"列表解构: first={first}, rest={rest}"

        # 4) case 解构:字典
        case {"type": "login", "user": user}:
            return f"字典解构: login user={user}"

        # **rest 捕获未显式匹配到的其余键
        case {"type": "pay", "amount": amount, **rest}:
            return f"字典解构: pay amount={amount}, rest={rest}"

        # 5) case 解构:类对象
        # 按属性名匹配
        case Point(x=0, y=0):
            return "类对象解构: 原点"

        # 按位置匹配(dataclass 默认支持 __match_args__)
        case Point(x, y):
            return f"类对象解构: Point({x}, {y})"

        # 6) case 守卫条件(if)
        case int(n) if n > 100:
            return f"守卫条件: 大整数 {n}"

        case str(s) if s.strip() == "":
            return "守卫条件: 空白字符串"

        # 兜底
        case _:
            return f"未匹配: {value!r}"


if __name__ == "__main__":
    samples = [
        0,                      														# 单值
        2,                      														# 多值
        [10, 20],               														# 列表解构(定长)
        [1, 2, 3, 4],           														# 列表解构(*rest)
        {"type": "login", "user": "alice"}, 											# 字典解构
        {"type": "pay", "amount": 99, "currency": "CNY"},   							# 字典解构 + **rest
        Point(0, 0),            														# 类对象解构(命名)
        Point(3, 4),            														# 类对象解构(位置)
        150,                    														# 守卫条件
        "   ",                  														# 守卫条件
        ("x", "y"),             														# 未匹配
    ]

    for item in samples:
        print(f"{item!r} -> {demo_match(item)}")

while else 和 for else

循环代码块中可以有else代码块(我也是第一次见到这种语法),当循环条件为False时执行else。
else表示正常结束循环体才会执行,如果循环体中遇到break时不执行else代码块的。

for/while … else 主要用于“有 break 的循环”,表达“未触发 break 的兜底分支”。没有 break 的循环里,一般没必要写 else。

nums = [1, 3, 5, 8]
target = 7

for n in nums:
    if n == target:
        print("找到了")
        break
else:
    print("没找到")

假设尝试连接一个服务最多 3 次,如果某次成功就 break,否则执行 else 中的失败处理的兜底逻辑

attempts = 0
max_attempts = 3
while attempts < max_attempts:
    if connect_to_service():   # 假设返回 True 表示连接成功
        print("连接成功")
        break
    attempts += 1
else:
    print(f"重试 {max_attempts} 次后仍然失败")

不用 else 也能写,但通常要加一个标志位,这样就多了2行代码(一行是声明标志变量,一行是标志位是否为为True),这也是Python精简代码的提现。

found = False
for n in nums:
    if n == target:
        found = True
        break

if not found:
    print("没找到")

适合:

  • 明确的“找到了就提前结束,否则执行兜底”的逻辑
  • 不想额外引入 found = False 这类标记变量时

作用:在循环未遭遇 break 的情况下执行收尾代码。
使用场景:任何需要根据“循环是否提前结束”来做不同处理的场合,尤其是查找、校验、重试等逻辑。

异常 try except else finally

在其它编程语言中一般都是try catch finally, Python用的不是catch而是except,并且python还支持else代码块。else子句将在try子句没有发生任何异常的时候执行。注意代码块的顺序:try → except | else → finally。捕获后还可以通过 raise 再次抛出异常,再次抛出时可以直接抛出 raise,也可以带上当前异常信息 raise e。

# try → else → finally
try:
	print('try')
except Exception as e:
	print('except')
else:
	print('else')
finally:
	print('finally')
try:
	print('try')
except Exception as e:
	print('except')
	raise
else:
	print('else')
finally:
	print('finally')
# try → except → finally
try:
    print('try')
    1/0
except Exception as e:
	print('except')
else:
	print('else')
finally:
	print('finally')
# try → else → finally
try:
	print('try')
except Exception as e:
	print('except')
else:
	print('else')
	# 注意:else出现异常不会走except
	print(1/0)
finally:
	print('finally')

else 子句的作用是:仅当 try 块中没有抛出任何异常时,才会执行 else 块中的代码,如果 try 块中发生了异常并被某个 except 捕获,else 块会被跳过,也就是是说 except和else是互斥分支。这就意味着else中的代码发生异常时不会走except

else:只在无异常时执行,常用于放置依赖于 try 块成功执行后的代码; finally:无论是否发生异常,都会在最后执行(一般用于资源释放)。

常用场景:依赖 try 操作结果的后续正常处理;控制 try 范围使其只包含真正预期会抛异常的代码。

# 这个示例功能是等价的
try:
  x = int(input("请输入数字"))
except ValueError:
  print("输入不是数字")
else:
  print("转换成功", x)   # 只在 try 成功时执行

---
try:
  x = int(input("请输入数字"))
  print("转换成功", x)
except ValueError:
  print("输入不是数字")

else 的价值主要不是“功能新增”,而是异常边界更精确:

  • 放在 try 里:except ValueError 会处理 try 内所有可能的 ValueError
  • 放在 else 里:except ValueError 只处理“主操作”(这里是 int(…))的 ValueError
# 不用 else:容易误捕获
try:
    x = int(input("请输入数字: "))
    y = int(input("再输入一个数字: "))  # 这里也可能 ValueError
except ValueError:
    print("第一个输入不是数字")  # 这个提示可能是错的

# 用 else:边界清楚
try:
    x = int(input("请输入数字: "))
except ValueError:
    print("第一个输入不是数字")
else:
    y = int(input("再输入一个数字: "))  # 这里出错就不是上面那个 except 的责任

在真实代码里,else 能避免“误捕获”,让异常处理更准确、可维护性更好。

with关键字

with关键字的作用自动关闭资源或者自动获取锁和自动释放锁,不需要显式的关闭资源和释放锁,相当于Java中的try() catch 语法。

// 使用 try-with-resources 自动关闭 BufferedReader 和 FileReader
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}
# 手动关闭资源
try:
    f = open("test.txt")
    print(f.readline())
except BaseException as e:
    print(e)
finally:
    f.close()
    
    
# with自动方式    
with open('example.txt', 'r', encoding='utf-8') as file:
    for line in file:
        # 每次循环读取一行,包含末尾的换行符 '\n'
        print(line, end='')  # end='' 避免重复换行

with自动获取锁和释放锁

import threading

lock = threading.Lock()
lock.acquire()
print("线程安全代码...")
lock.release()
import threading
lock = threading.Lock()

with lock:
    print("线程安全代码...")

代码块全局变量

在代码块(if、try、while、for)中声明的变量是全局变量

Python在代码块中声明的变量是"全局变量",这和Java语言完全相反,Java在代码块中声明的变量都是局部变量,这就意味着Python在下面可以访问任意代码块中定义的变量,这样一来代码就少了一行,这也是python精简的一个体现。

// Java中要想方法代码块中的变量只能将代码块中的变量提取出来
boolean flag = false;
if (true) {
	flag = true;
}
System.out.print(flag)
if True:
    a = "this is global variable"
print(a)


try:
    b = "try"
except ValueError:
    # 局部变量,外面不能访问
    c = "except"
else:
    d = "else"
finally:
    e = "finally"

print(b)
# print(c)
print(d)
print(e)


while True:
    f = "while"
    break
print(f)

for i in range(10):
    g = "for"
print(g)

lambda表达式

lambda表达式在很多编程语言中都有类似语法。lambda表达式就是一个有参数有返回值的匿名函数

  • Python中的lambda表达式必须使用lambda关键字声明
  • Python中的lambda式的方法体只能是一行代码,不能是代码块,Java中支持代码块多行语句。
// Java多行语句
Runnable task = () -> {
    for (int i = 1; i <= 5; i++) {
        System.out.println("计数: " + i);
    }
    System.out.println("任务完成");
};
# Python只允许一行代码
sum = lambda x, y: x + y 
print(sum(1, 2))
# <class 'function'>
print(type(sum))
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐