☰
Python语法核心精讲:从变量、控制流到装饰器与协程
2026/10/9 7:25:16 网站建设 项目流程

学Python这件事,百分之八十的人是卡在语法核心这一关的。不是看不懂文档,而是没搞懂Python语法的那套脾气——它跟C、Java那种“类型先声明、逻辑嵌套靠花括号”的语言完全不是一个路子。我见过太多人,环境装好了、numpy装好了、项目也抄了一堆,结果一上手写自己的脚本,就栽在变量作用域、切片套路、列表推导式这些最基础的地方。这篇文章就把Python语法核心摊开讲透,从变量怎么赋、流程怎么控制、函数怎么写,到装饰器、生成器、协程这些进阶语法,一次说清。不管你是刚装好Python准备入门的新手,还是学了一半总感觉语法不扎实、写代码全靠猜的进阶者,都建议把这篇当成一份能反复翻的“排查手册”来用。

1. 环境与工具准备:语法核心得先跑起来

1.1 版本选择:不是越新越好,但真的别选太老

说语法核心之前,我得先聊环境。很多人觉得Python的语法是跟版本没关系的,真不是。Python 2和Python 3的print、整数除法、字符串编码完全是两回事,现在你要是还在官网翻到旧版2.x的教程去学,那写出来的代码大概率跑不通。我建议直接用Python 3.8以上,目前主流发行版大多已经是3.10、3.11甚至3.12,语法核心部分基本一致,但新版本在类型标注、异常处理、性能上都有改善。太老的版本比如3.6、3.7,在有些新库上已经逐渐被官方放弃,没必要跟自己过不去。

版本选择的实际原则就一条:看你要用的第三方库支不支持。比如有的量化交易库、爬虫框架对Python版本有明确要求,安装时报错“requires-python >=3.9”,那就乖乖装Python 3.9以上的版本。反过来说,如果你的工作环境里别人用着老版本,就不要贸然用新版语法,老老实实按兼容写法来。语法核心学的是“语言规则”,版本兼容是“工程素养”,两者都得抓。

1.2 官网下载与安装路径:三步装好不折腾

去Python官网下载时我有个习惯:Windows选带“Windows installer (64-bit)”的安装包,macOS选“macOS 64-bit universal2 installer”,Linux大部分发行版自带,也可以用apt或yum装,但版本可能偏旧。安装时最关键的一步是勾选“Add Python to PATH”,这个选项很多人漏掉,装完才发现cmd里敲python没反应。

这里说明一下:PATH就是系统搜索可执行文件的路径列表,你把Python的安装目录加进去,命令行才能在任何目录下直接调用python命令。如果当时没勾选,后面手动配置环境变量也不难:Windows下打开“系统属性 → 环境变量”,在Path中新增Python安装目录和它的Scripts子目录。配置完记得重新打开终端,让环境变量重新加载。

装完之后,我建议顺手验证一下。打开命令行工具,依次敲:

python --version pip --version

如果两个都有输出,说明解释器和包管理器都正常。很多人卡在“python不是内部或外部命令”,十有八九就是PATH没配好。还有一个小技巧:Windows下如果系统里装过Microsoft Store的Python,命令行会弹出商城页面,这时候可以用py --version来确认官方版本。

1.3 写第一个语法验证脚本:交互模式是学语法最快的战场

环境配好后,我强烈建议先在交互式终端里熟悉语法核心。终端里直接敲python进入交互模式,输入一行代码,立刻出结果,这种即时反馈对学习语法来说是最快的路径。

python >>> a = 10 >>> print(a * 2) 20

交互模式适合验证小语法点:类型转换、切片、推导式,随手一敲就有答案。等代码超过五六行,再丢进.py文件里跑。写.py文件的时候,我建议一开始就用一个有缩进意识的编辑器,VS Code配Python插件就是不错的选择。VS Code里装好插件后,按一下F5就行,它会让你选择解释器,直接用刚才装的就行。很多新手在VS Code里报“No interpreter”,其实就是Python插件没有自动找到你装的解释器,手动在命令面板里选一下就好。

2. 变量与数据类型:学语法核心打地基的第一课

2.1 动态类型:Python为什么不用声明类型

Python最核心的一句话是“变量是标签,不是盒子”。这句话太重要了。在C、Java里,定义一个变量等于预先划好一块类型固定的内存区域,数据放进去不能变类型;而Python里的变量只是一个名字,它指向某个对象,这个对象才有类型,变量本身没有固定类型。所以你可以这样写:

a = 100 # a指向整数对象 a = "hello" # a又指向字符串对象 a = [1, 2, 3] # 指向列表对象

这在编译型语言里是不允许的,但在Python里完全合法。好处是写代码快、灵活,坏处是某些时候你传错类型,程序要跑到运行时才报错。这就是动态类型的特点,它是Python语法核心的第一个“性格”。

我在实际写代码时有个体会:动态类型不是让你乱来的理由。团队协作时,变量名的语义要清晰,比如user_name就别写成un。如果担心类型问题,可以用类型标注来辅助,虽然它不强制运行时的类型检查,但代码可读性和IDE提示会好很多:

def greet(name: str) -> str: return "hello, " + name

类型标注是Python 3.5之后引入的语法,后面我会讲到函数,这里先提一句,是因为它跟动态类型并不矛盾——动态是运行时规则,标注是开发期契约。

2.2 常用内置数据类型:数字、字符串、布尔、空值

Python内置的基础数据类型不多,但每个都要吃透它们的脾气。整数int、浮点数float、字符串str、布尔bool、空值NoneType,这是五大门神。

整数在Python里没有固定长度限制,这比很多语言都爽。举个例子,计算2的100次方:

>>> 2 ** 100 1267650600228229401496703205376

这种大数运算在C里要自己处理溢出,Python直接给你算。浮点数要注意的是精度问题,因为底层是二进制存储,有些十进制小数无法精确表示:

>>> 0.1 + 0.2 0.30000000000000004

所以涉及金额计算,我建议用decimal模块,而不是直接用浮点数加减。字符串最基础的是拼接和格式化:

name = "Python" version = 3.11 print(f"{name} {version}") # f-string,3.6之后最好用的格式化方式

f-string是Python字符串的重要语法,把变量嵌进大括号里直接输出,比老式的%格式化和.format()直观得多。布尔值只有True和False,记住在条件判断里,空字符串、空列表、0、None都会被当成False,这个规则叫“真值测试”。

2.3 类型转换:Python类型转换的三种常用姿势

写程序经常要从一个类型切到另一个类型,Python提供的是三个内建函数:int()、float()、str(),加上list()、tuple()、set()这些容器转换。

price = "58.5" price_float = float(price) # 字符串转浮点数 price_int = int(price_float) # 浮点数转整数,直接截断小数部分 message = "价格是" + str(price_float) # 数字转字符串才能拼接

实际操作中最大的坑是:字符串内容不是合法数字时,转换会直接抛出ValueError。比如int("abc")必然崩。所以处理外部输入(命令行参数、文件读取、爬虫抓到的数据)时,最稳的做法是写个安全转换函数:

def safe_int(value, default=0): try: return int(value) except (ValueError, TypeError): return default

另外一个容易混淆的点:int(3.99)结果是3,不是四舍五入的4。Python的int转换是向零取整,想四舍五入得用round(3.99)。类型转换这事看着简单,却是大量运行时异常的源头,值得慢一点处理。

3. 控制流语句:if、for、while是程序的骨架

3.1 if/elif/else的判断逻辑:多分支别写成一堆if

编程的本质是“按条件走不同的路”。Python的条件语句语法跟其他语言很像,但有一点独一份:缩进决定代码块归属。

score = 85 if score >= 90: grade = "优秀" elif score >= 60: grade = "合格" else: grade = "不合格"

elif就是else if的缩写,它跟连续写多个if的区别在于:如果命中第一个条件,后面的elif根本不会判断,整个链条只走一个分支。这一点在性能上有微小的优势,更重要的是语义清晰,表达“互斥条件”时就要用elif。

我见过不少新手把每个条件都用单独的if写,结果逻辑上出现重叠时输出两个值,很难排查。记住一条:互斥条件用if/elif/else,独立条件才用多个if。

3.2 for循环与range:Python遍历的艺术

Python的for循环跟C完全不一样,它是“遍历迭代器”,不是“按下标循环”。最直观的写法:

fruits = ["苹果", "香蕉", "橘子"] for fruit in fruits: print(fruit)

这个写法读作“把列表里的每个元素依次取出来,赋值给fruit”。如果你确实需要下标,用enumerate:

for index, fruit in enumerate(fruits): print(index, fruit)

enumerate是Python的一等好帮手,它同时返回下标和元素,省去手动计数。如果需要生成一系列连续整数,就用range():

for i in range(5): # 0,1,2,3,4 print(i) for i in range(2, 10, 2): # 从2到9,每2步一个 print(i)

range(5)是左闭右开区间,取0到4,不取5。这个“含头不含尾”的规则贯穿Python的切片、range等所有序列操作,记住“结束值永远取不到”,能大幅减少边界错一的bug。实际写爬虫时,翻页循环就经常用for page in range(1, total_pages + 1),这里的+1就是给右开区间补上最后一页。

3.3 while循环与break、continue的控制艺术

while用于不知道循环次数、只知道终止条件的场景:

count = 0 while count < 5: print(count) count += 1

while必须自己管理循环变量的递增,忘记写count += 1就是死循环,这是很多初学者卡住的地方。我的建议是:能确定次数用for,不确定次数用while,别对着while硬数。

break和continue是循环里的两个“控制杆”。break用来强制跳出整个循环,continue跳过本次循环剩下的语句、直接进入下一轮。在实战里最常见的场景是“找到符合条件的第一个元素就停手”:

for data in data_list: if data["status"] == "success": process(data) break

这个写法比在循环里加一堆标志位干净得多。还有一个叫for...else的语法,很多人不知道:如果for循环正常结束(没被break打断),就会执行else分支。这在“搜索全部数据后仍未找到”的场景下特别好用,比如判断一个数是不是素数。

4. 函数与作用域:Python定义函数的核心语法

4.1 def定义函数:把代码块装进“盒子”

函数是组织和复用代码的最基本单位。Python里定义一个函数用def关键字:

def add(x, y): result = x + y return result

def后面是函数名,括号里是参数,冒号下面缩进的代码块是函数体,return把结果返回给调用方。如果没写return,函数会默认返回None,这个细节值得记住,因为很多人在调试时发现“函数没返回值”,其实是在函数里只做了打印、没写return。

函数的命名习惯我也提醒一句:Python官方推荐用全小写加下划线,比如calculate_total,不是小驼峰calculateTotal。在Python社区里,代码风格的一致性是融入团队的基本要求。

4.2 参数类型:默认参数、关键字参数、可变参数

Python函数的参数系统是它的一大特色,灵活得惊人。核心就几种:

位置参数:调用时按顺序传参:

def greet(name, greeting): return f"{greeting}, {name}" greet("小明", "你好")

关键字参数:调用时指定参数名,顺序任意:

greet(greeting="你好", name="小明")

默认参数:定义时给参数一个默认值,调用时不传就用默认值:

def connect(host, port=8080): pass

这里有个极其重要的天坑:默认参数不要用可变对象(列表、字典),要用就用None。因为默认值只在函数定义时计算一次,如果你写def add_item(item, container=[]),多次调用会把元素累积到同一个列表里,这是经典的“可变默认参数”陷阱。正确写法:

def add_item(item, container=None): if container is None: container = [] container.append(item) return container

可变参数用*args和**kwargs,分别接收“任意多个位置参数”和“任意多个关键字参数”:

def log(*args, **kwargs): print("位置参数:", args) print("关键字参数:", kwargs) log(1, 2, name="tom", age=18)

*args打包成元组,**kwargs打包成字典,这是很多框架源码里必定出现的高频语法。

4.3 作用域规则:local、global与nonlocal

Python的作用域规则用一句话概括:在函数内赋值就是局部变量,只能影响函数内部。看个案例:

total = 100 def change(): total = 200 # 这是新的局部变量,不是上面的total change() print(total) # 输出100

函数内部的total = 200会在函数作用域里新建一个局部变量,外面的total毫发无损。如果你确实想在函数里修改全局变量,得先声明global total:

total = 100 def change(): global total total = 200 change() print(total) # 输出200

但我的实际经验是:全局变量能不用就不用。函数间通过参数和返回值传递数据,比用全局变量改来改去好调试得多。函数嵌套时还有nonlocal关键字,用于在内层函数中修改外层函数的局部变量,这个在闭包和装饰器里会用到,后面讲进阶语法再细说。

5. 数据结构核心操作:切片、推导式、字典的实用语法

5.1 切片操作:Python数组切片命令的“头尾不看”规则

切片是Python里使用频率最高的语法之一,列表、字符串、元组都支持。基本形式是seq[start:stop:step],仍然遵循“含头不含尾”:

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(nums[2:5]) # [2, 3, 4],下标2到4,不含5 print(nums[:3]) # [0, 1, 2],开头到下标2 print(nums[5:]) # [5, 6, 7, 8, 9],下标5到末尾 print(nums[::2]) # [0, 2, 4, 6, 8],步长为2 print(nums[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0],反转列表

这是程序员几乎每天都会打交道的语法,尤其[::-1]反转列表,在回文判断、逆序处理里特别常见。字符串切片也是同理,想提取文件名的后缀,直接file_name[-3:]就拿到最后三个字符。

切片的另一个实用工具是split和join,处理文本时它们是切片的好搭档:

line = "192.168.1.1:8080" host, port = line.split(":")

但我用切片时想提醒一句别踩坑:切片会产生一个新的列表对象,如果原列表很大,切片会复制出一份内存,不是引用。想要“不复制、只视图”的话得用itertools.islice或者拿到数组长度后用循环处理,这个看场景取舍。

5.2 列表推导式:Python里最优雅的循环语法

列表推导式是我最爱的Python语法,没有之一。它能把循环和筛选浓缩成一行:

squares = [x * x for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

它等价于:

squares = [] for x in range(10): squares.append(x * x)

加一个条件变成“筛选+转换”:

even_squares = [x * x for x in range(20) if x % 2 == 0]

这种写法一定要学会,因为它在Python工程里出现频率太高了。包括爬虫清洗列表、数据分析里批量转换数据、构造测试用例,处处都是推导式。

与之对应的是生成器表达式,写法一致但用圆括号:

gen = (x * x for x in range(1000000))

差别在于:列表推导式一次性把1百万个元素全部算好存在内存里,生成器表达式是“用到哪个算哪个”,省内存。在处理大文件或海量数据时,我基本都写成生成器表达式,除非真的需要重复访问列表。

5.3 字典操作:Python的查询效率担当

字典是以键值对方式存储数据的内置结构,查询速度非常快。Python构造邻接矩阵、统计词频、缓存计算结果都是用它。基本操作:

user = {"name": "tom", "age": 18} user["city"] = "上海" # 新增键值 print(user["name"]) # 取值 print(user.get("gender", "未知")) # 取不到返回默认值,比直接user["gender"]安全

遍历字典有几种方式:

for key in user: # 只遍历键 pass for value in user.values(): # 只遍历值 pass for key, value in user.items(): # 键值对同时遍历 pass

统计词频是字典的一个经典用法:

text = "hello world hello python" word_count = {} for word in text.split(): word_count[word] = word_count.get(word, 0) + 1

get(word, 0)的意思是:如果word不在字典里,就用0作为初始值,这样每一次遇到就+1。这个写法比先判断再更新的三行代码简洁得多。如果你需要按插入顺序记录,Python 3.7之后的字典默认就是有序的,直接遍历就能按顺序输出。

字典还有个“冰封”用法,就是defaultdict,来自collections模块,可以让“键不存在时自动生成默认值”,省去手动判断:

from collections import defaultdict word_count = defaultdict(int) for word in text.split(): word_count[word] += 1 # 初始就是0,int()的默认值

Python的矩阵操作也经常用嵌套字典或嵌套列表来完成。比如构建邻接矩阵表示图结构:

graph = {1: [2, 3], 2: [3, 4], 3: [4]}

这种“键-列表”的结构在算法题里太常用了,李白打酒这类递归回溯题也躲不开字典和列表的组合操作。

6. 文件操作与异常捕获:让Python脚本“扛得住事”

6.1 文件读取与写入:打开方式不对会踩大坑

Python内置的文件操作语法非常简洁,核心就是open()函数配合with语句:

with open("data.txt", "r", encoding="utf-8") as f: content = f.read()

with会自动管理文件的打开和关闭,就算中间出异常,文件也会被正确关闭,这是Python最推荐的写法,避免你手写f.close()忘记调用。打开模式有很多,常用的:

模式含义文件不存在时
r只读报错
w清空写入创建
a追加写入创建
rb二进制只读报错

读文件的常见方式有三种:read()一次性读全部、readline()逐行读、readlines()读成行列表。处理超大文件时,我推荐用迭代式逐行读取:

with open("huge_log.txt", "r", encoding="utf-8") as f: for line in f: # 每行处理 pass

这种写法不会一次性把整个文件载入内存,内存占用非常稳定。写文件时注意编码问题,尤其Windows环境下,默认编码是gbk,读写中文一定要显式指定encoding="utf-8",不然会乱码或者直接报UnicodeDecodeError。

还有一个常见需求是处理JSON配置文件,Python的json模块就是为此准备的:

import json data = {"name": "tom", "skills": ["python", "sql"]} with open("config.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False)

ensure_ascii=False是关键,否则中文会被转成\uXXXX的ASCII转义序列,可读性极差。

6.2 异常处理:Try/Except的深层逻辑

程序一旦运行起来,面对的是不可控的外部世界:文件不存在、网络断开、数据格式不对、除数为零。Python的异常处理语法是:

try: num = int(input("请输入数字: ")) result = 100 / num except ValueError: print("输入的不是数字") except ZeroDivisionError: print("不能除以0") else: print("计算成功:", result) finally: print("无论成功失败都会执行")

try放可能出错的代码,except按异常类型分别捕获,else只有在没异常时执行,finally不管有没有异常都执行——通常用来做清理工作。这个语法核心是:不要用一把大except:把所有异常都吞掉,那样会让bug石沉大海。至少要把Exception打印出来。

实际开发里,我常常把文件解析这类容易出错的逻辑包成工具函数:

def parse_json_file(path): try: with open(path, "r", encoding="utf-8") as f: return json.load(f) except FileNotFoundError: print("文件不存在:", path) return None except json.JSONDecodeError: print("JSON格式错误:", path) return None

我见过太多新手写爬虫、写数据处理脚本时,几行代码崩溃就结束,就是因为没把输入数据的异常考虑进去。学会异常处理不是“防御式编程的教条”,而是让脚本能在出问题时给足线索、继续运行下去的最佳手段。

7. 进阶语法核心:装饰器、生成器与协程

7.1 装饰器:Python语法里最“魔法”的存在

装饰器的核心是“在不修改原函数代码的前提下,给函数增加额外功能”。它本质上是一个接收函数、返回新函数的函数:

def timer(func): def wrapper(*args, **kwargs): import time start = time.time() result = func(*args, **kwargs) print(f"{func.__name__} 耗时 {time.time() - start:.4f} 秒") return result return wrapper @timer def slow_function(): import time time.sleep(1) return "done"

@timer这一行等价于slow_function = timer(slow_function)。调用slow_function()实际调用的是wrapper(),wrapper执行原函数前后分别记录时间和打日志,原函数代码不用改一个字。

装饰器在日志记录、权限校验、参数检查、缓存结果等场景极其常用。比如写Web页面时检查用户是否登录:

def login_required(func): def wrapper(*args, **kwargs): if not current_user: raise PermissionError("请先登录") return func(*args, **kwargs) return wrapper @login_required def get_profile(): return "这里是个人资料"

如果你用Flask、Django、FastAPI写后端,会看到大量@app.route、@requires_auth这类装饰器,它们本质上都是Python语法核心的延伸。想进阶,装饰器是绕不开的高地。

7.2 生成器与迭代器:Python for循环背后的真相

生成器是让我从“会用Python”到“懂Python”的转折点。先搞明白迭代器:任何可以用for...in遍历的对象,本质都是迭代器。列表、元组、字典、文件对象都是。生成器是一种“懒惰”的迭代器,它不一次性存数据,而是每次产出一个值。

定义生成器最简单的方法是把函数里的return改成yield:

def countdown(n): while n > 0: yield n n -= 1 for num in countdown(3): print(num) # 输出 3 2 1

yield会把函数变成一个生成器对象,每次调用next()时,代码从上一次暂停的位置继续执行,直到下一个yield或函数结束。这种“暂停-恢复”的机制非常省内存。比如生成斐波那契数列:

def fibonacci(limit): a, b = 0, 1 while a < limit: yield a a, b = b, a + b

如果你用列表一次性算几百万个数,内存直接爆掉;用生成器就非常舒服,算到哪是哪。这也是Python在大数据处理上能跟其他语言掰手腕的原因之一。

7.3 协程初探:Python异步语法的最小闭环

协程是并发编程的语法基础,理解它之前先记住一句话:协程不是并行,而是“协作式交替执行”。Python 3.5之后引入了async/await语法,定义协程用async def,等待一个耗时操作用await:

import asyncio async def hello(): print("开始执行") await asyncio.sleep(1) print("执行完毕") asyncio.run(hello())

await asyncio.sleep(1)的意思是:把控制权交出去,等1秒后回来继续执行。在这1秒里,事件循环可以跑去执行别的协程,所以多个协程合在一起,总耗时往往远小于串行执行。实际开发里最常见的例子是并发HTTP请求:

import asyncio import httpx async def fetch(url): async with httpx.AsyncClient() as client: resp = await client.get(url) return resp.status_code async def main(): urls = ["https://example.com"] * 10 results = await asyncio.gather(*[fetch(url) for url in urls]) print(results) asyncio.run(main())

协程语法对新手来说有点绕,我建议先掌握两个点就行:async def定义协程,await后面跟耗时操作;多个协程用asyncio.gather一起跑。学Python爬虫、做量化交易回测、写高性能服务的人,迟早都要跟协程打交道。但别急,先把前面的函数、生成器搞扎实,协程才会顺理成章。

8. 常见问题排查与语法学习路线

8.1 常见语法报错速查:先定位再修复

语法核心学完,剩下来就是跟报错打交道。我列几个出现频率最高的报错,对照排查:

报错信息主要原因解决方案
IndentationError缩进不一致或混用了空格和Tab统一用4个空格,编辑器显示空格
SyntaxError: invalid syntax括号没闭合、漏了冒号、中英文符号混用检查行尾冒号,看是不是中文全角字符
NameError: name 'xxx' is not defined变量名拼写错或变量未定义检查拼写和赋值顺序
TypeError: unsupported operand type(s)不同类型直接运算,比如字符串和整数相加先做类型转换,或isinstance判断
IndexError: list index out of range下标越界检查列表长度,用len()或try
KeyError: 'xxx'字典键不存在用.get(key, 默认值)或先判断in
UnicodeDecodeError文件编码问题打开文件时指定encoding="utf-8"
ModuleNotFoundError没安装对应包或者包名拼错pip install包名,注意大小写

报错不是灾难,是程序给你的线索。我自己的排查习惯是:先看错误类型,再看“最后一行的具体位置”,然后顺着调用栈往上找第一处自己写的代码。对于TypeError这种,我经常在报错前加两行print(type(x)),快速确认变量到底是什么类型,比干瞪眼快得多。

8.2 从语法核心到实战:把知识转化为判断力

学会了语法本身还不够,得能写出“像样”的代码。我给自己带的实习生定过一条经验:语法核心从学到会用,要过三关。

第一关是“抄写关”。把入门教程里的代码案例亲手敲一遍,不用背,但要敲。这个过程中你的手指会记住缩进、冒号、括号这些容易被眼睛忽略的细节。

第二关是“改写关”。拿一个练手题目,比如计算PTA上的经典题“李白打酒”,题目大意是李白带着酒壶,遇店加一倍,遇花喝一斗,要推算经过不同事件后的酒量变化。这种题目条件清晰、逻辑密度恰当,特别适合练分支、循环、列表推导式。如果觉得自己写不出来,先读别人的解法,再自己重写一遍,不要只看不写。

第三关是“封装关”。把自己写的脚本改造成函数式结构:把主流程抽成main()函数,把子任务拆成小函数,把重复出现的代码块提取出来。这一步做完,才算真正把语法核心内化成“工程能力”。

我觉得很难给出一条人人适用的路线图,但有一个原则可以分享:不要沉迷于“刷语法清单”,而是用一个具体的小项目把语法串起来。比如写一个统计某目录下所有文件的扩展名分布的小脚本,或者把邻接矩阵用字典和列表实现一遍,这些项目自然而然会把文件操作、字典、循环、推导式全部调动起来。语法核心这关过了,后面学库、学框架,都会快得惊人。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询