从 JavaScript 的角度理解 Python 语法

📅 2026/6/26 6:47:47
从 JavaScript 的角度理解 Python 语法
1. 前言从 JavaScript 的角度学习 Python你会发现两者有很多相似之处都是动态、解释型、多范式语言但语法和设计哲学上也有显著差异。下面我以一名 JavaScript 开发者的视角带你快速理解 Python 的核心语法和概念相信通过本文的学习你就算入门 Python 了。2. 核心差异速览特性JavaScriptPython代码块{ }缩进通常4空格语句结束;可选换行布尔值true/falseTrue/False空值null/undefinedNone逻辑运算两个竖线!andornot数组Arraylist对象Objectdict当前实例thisself方法第一个参数构造函数constructor()__init__()继承extendsclass Child(Parent):3. 变量声明JavaScript 使用var、let、const声明变量而 Python 直接赋值即可无需关键字。Python 变量的作用域由所在代码块函数、模块决定没有块级作用域。// JavaScript - 需要声明关键字 const name Alice // 常量不可重新赋值 let age 25 // 块作用域变量 var city Beijing // 函数作用域变量旧式# Python - 直接赋值动态类型 name Alice # 变量无需关键字作用域由所在代码块决定 age 25 city Beijing # 约定常量全大写但实际仍可修改如 PI 3.144. 代码块与缩进规则Python 使用缩进通常4个空格表示代码块不再使用花括号{}。缩进必须严格一致不能混用空格和制表符。// JavaScript - 使用花括号 {} 界定代码块 if (score 90) { let grade A; console.log(优秀); } else { let grade B; console.log(加油); } // 花括号内缩进仅为可读性语法不强制# Python - 使用缩进表示代码块 if score 90: grade A # 缩进内的代码属于if块 print(优秀) else: grade B print(加油) # 缩进必须一致不能混用空格和制表符4. 布尔值、空值与逻辑运算Python 的布尔值首字母大写True/False空值只有None没有undefined。逻辑运算符使用英文单词and、or、not。and并且两个条件都为 Trueor或者任意一个为 Truenot取反True 变 FalseFalse 变 True// JavaScript - 布尔小写空值有null/undefined let isDone true; // 或 false let empty null; // 主动赋空 let notDefined; // undefined if (isDone !empty) { // 逻辑运算符 || ! console.log(执行); }# Python - 布尔首字母大写空值只有None is_done True # 或 False empty None # 唯一空值 # 变量必须赋值后才能使用无undefined if is_done and not empty: # 逻辑运算符 and or not print(执行)5. 数组与对象 / 列表与字典Python 的列表list对应 JavaScript 的数组字典dict对应 JavaScript 的对象。但方法名称和访问方式有所不同。// JavaScript - 数组和对象 let arr [1, 2, 3]; arr.push(4); // 添加元素 let obj { name: Alice, age: 25 }; obj.city Beijing; // 添加属性 console.log(obj.name); // 点语法访问# Python - 列表list和字典dict arr [1, 2, 3] arr.append(4) # 添加元素 obj {name: Alice, age: 25} obj[city] Beijing # 字典键访问必须用中括号 # 点语法不适用于字典只能用 obj[key] print(obj[name])6. 函数定义Python 使用def关键字定义函数支持默认参数、可变参数*args、**kwargs。匿名函数用lambda表达式但只能写单行。# Python - def 关键字 def add(a, b): return a b multiply lambda a, b: a * b # lambda 仅限单行表达式 # 可变参数示例 def log(*args, **kwargs): print(args, kwargs)7. 类定义构造函数、继承Python 的类使用class关键字构造函数为__init__所有实例方法第一个参数必须是self相当于 JavaScript 的this。继承时在类名后加括号指定父类。# Python - classself 显式 from hashlib import new class Person: def __init__(self, name, age): # 构造函数 self.name name self.age age def greet(self): # 方法必须带 self return fHi, Im {self.name} class Student(Person): # 继承 def __init__(self, name, age, grade): super().__init__(name, age) # 调用父类构造函数 self.grade grade res Student(zs, 18, 男) print(res.greet())8. 控制流if / forPython 的if条件语句不需要括号但条件后必须跟冒号。for循环直接迭代可迭代对象类似 JavaScript 的for...of。range()用于生成数字序列。# Python - if 和 for x 10 arr [1, 2, 3, 4, 5] if x 0: print(正数) else: print(非正数) for i in range(5): # range 生成数字序列0-4 print(i) for item in arr: # 直接遍历可迭代对象 print(item)9. 异常处理Python 使用try/except捕获异常可以指定异常类型并支持else子句无异常时执行。finally无论是否异常都会执行。// JavaScript - try/catch try { let result 10 / 0; if (!isFinite(result)) throw new Error(除零错误); } catch (error) { console.log(error.message); } finally { console.log(清理工作); }# Python - try/except try: result 10 / 0 except ZeroDivisionError as e: print(除零错误, e) except Exception as e: print(其他错误, e) else: print(没有异常发生) finally: print(清理工作)10. 异步编程Python 通过asyncio库和async/await实现异步编程需要显式运行事件循环。与 JavaScript 不同Python 的异步是协作式多任务需要主动让出控制权如await asyncio.sleep()。// JavaScript - async/await async function fetchData() { let response await fetch(url); let data await response.json(); return data; } fetchData().then(console.log);# Python - asyncio import asyncio async def fetch_data(): await asyncio.sleep(1) # 模拟IO return data async def main(): result await fetch_data() print(result) asyncio.run(main()) # 启动事件循环11. 模块和导入导出JavaScriptES6使用import/export管理模块而 Python 使用import和from ... import ...。每个 Python 文件都是一个模块文件夹可以通过包含__init__.py成为包Python 3.3 可省略但推荐保留math_my.py模块PI 3.14159 def add(a, b): return a b class Calculator: passmain 导入模块import math_my print(math_my.PI) print(math_my.add(1, 2))只把 PI 和 add 导入当前作用域from math_my import PI, add print(PI) print(add(1, 2))Python 的import会执行整个模块导入后的名称通过模块名访问如math.PI。可以使用as别名import math as m或from math import PI as pi。没有默认导出的概念但可以通过__all__控制from module import *的行为。以上是从 JavaScript 角度快速理解 Python 语法的核心要点。掌握这些差异后你就可以开始编写 Python 代码并逐步熟悉更多高级特性如装饰器、生成器等。两种语言各有千秋灵活运用会让你的编程之路更加宽广。附一为什么有 \ 在代码后面这个\是 Python 的行续接符line continuation character表示当前代码行还没结束下一行是它的延续。例如client lark.Client.builder() \ .app_id(APP_ID) \ .app_secret(APP_SECRET) \ .log_level(LogLevel.INFO) \ .build()如果不加\Python 会把每一行视为独立语句导致语法错误。加了\后Python 知道这几行实际上是同一条语句。用括号包裹的方式更 Pythonic不需要\例如client (lark.Client.builder() .app_id(APP_ID) .app_secret(APP_SECRET) .log_level(LogLevel.INFO) .build())两者功能完全一致\写法在 Builder 模式中也很常见只是要注意\后面不能有空格或注释否则会报错。我们更推荐使用括号包裹的方式。附二__init__.py文件在 Python 中的作用1. 标记目录为 Python 包在 Python 中一个普通的文件夹如果想要被当作包来导入必须包含一个__init__.py文件在 Python 3.3 之前这是强制性的。例如假设你有这样的目录结构mypackage/ __init__.py module1.py module2.py当你执行import mypackage或from mypackage import module1时Python 会识别出mypackage是一个包因为它下面有__init__.py。如果没有这个文件Python 就会把该文件夹当作一个普通的目录无法从中导入模块除非使用命名空间包见后文。2. 执行包的初始化代码当包被首次导入时__init__.py文件中的代码会被自动执行。你可以在其中放置包级别的初始化逻辑例如设置包级别的全局变量导入包内其他子模块或子包配置日志检查运行环境、版本等例如在mypackage/__init__.py中# mypackage/__init__.py print(Initializing mypackage) VERSION 1.0.0 from . import module1 from .module2 import some_function这样当用户import mypackage时会看到打印信息并且可以直接通过mypackage.some_function调用module2中的函数而不必写mypackage.module2.some_function。3. 控制包的导入行为定义__all__在__init__.py中定义一个名为__all__的列表可以指定当用户使用from package import *时哪些子模块会被导入。例如# mypackage/__init__.py __all__ [module1, module2]那么from mypackage import *只会导入module1和module2其他未列出的模块则不会被导入。延迟导入有时为了避免循环导入或提高启动速度可以在__init__.py中使用函数或属性来延迟导入子模块# mypackage/__init__.py def get_module1(): from . import module1 return module14. 简化导入路径通过__init__.py将子模块中的对象“提升”到包级别可以让用户使用更简洁的导入语句。例如# mypackage/__init__.py from .module1 import MyClass from .module2 import my_function之后用户可以直接写from mypackage import MyClass, my_function5. Python 3.3 的变化命名空间包从 Python 3.3 开始引入了隐式命名空间包PEP 420。如果一个目录下没有__init__.py但它是 Python 路径上的一个有效目录并且包含其他 Python 模块或子目录那么它会被视为一个命名空间包namespace package。命名空间包允许将多个目录合并成一个逻辑上的包常用于将大型项目拆分到多个代码仓库。重要区别传统包regular package必须包含__init__.py可以有初始化代码。命名空间包不需要__init__.py但不能包含任何初始化代码因为它只是多个目录的逻辑合并。因此如果你需要执行包的初始化代码或者想要明确地将一个目录标记为包尤其是为了兼容旧版 Python仍然建议保留__init__.py。理解__init__.py的作用有助于你更好地理解 Python 项目。总结是不是通过对比学习突然发现 Python 其实是一门非常简单的语言呢加油吧前端们。在 AI 时代掌握多一门语言很重要并且说 Python 的是 AI 的原生语言也不为过。我们可以在各种前端技术群里看到很多前端觉得学习 Python 太麻烦了所以还继续学习 Node.js当然如果你是一名 Node.js 专家级前端那么你继续学习使用 Node.js 是没有什么问题的。如果你只是一名普通的前端只想找一份工作那么在这个由后端统治的世界里即便现在有很多以 Node.js 为主的产品比如 OpenClaw、Claude Code但专门的 Node.js 岗位依然少得可怜。尤其是国内基本没有大一点的公司会把 Node.js 作为核心开发语言。当然如果你是所谓的独立开发者那么无论是 Node.js 还是 Python 还是 Java 甚至 PHP 都无所谓了。但从打工人找工作的角度看就不一样了。