Python 入门篇:前端开发者的 AI 预备课

本篇按前端开发者的习惯对照 JavaScript,把 Python 环境、核心语法、模块、文件和日志过一遍,为后面写训练脚本、调 NumPy、PyTorch 打底。读完应能独立跑通脚本、管好虚拟环境、读写文件。

Python 是一种高级、解释型、面向对象的编程语言,由 Guido van Rossum 于 1991 年首次发布。语法靠缩进划分代码块,标准库和科学计算生态完整,是机器学习与 AI 工程的主流语言。

学习准备

Anaconda 安装

Anaconda 是面向数据分析、机器学习、科学计算的 Python、R 发行版,自带解释器、常用库和环境管理。

两大块:

  • 预装科学计算库:NumPy、SciPy、Pandas、Matplotlib、Seaborn、Scikit-learn,以及 Jupyter Notebook。
  • conda:包管理 + 环境管理。除了 Python 包,还能装 C、C++ 库、CUDA、MKL 等非 Python 依赖,并创建互相隔离的虚拟环境。

只想要轻量环境时,可以用 Miniconda(只有 conda 和 Python,库按需再装),或标准库自带的 venv。本篇以 Anaconda 为例。

安装步骤(以 macOS Apple silicon 为例;Windows、Linux 在同一页选对应安装包):

  • 打开 https://www.anaconda.com/download
  • 在 Download Now 里点 Skip Registration,下载当前系统的 Anaconda Distribution 图形安装包(不要死记某个日期的文件名,以官网当时提供的为准)
  • 按安装向导完成
  • 打开终端,能打出版本号即成功:
conda --version
python --version

Jupyter Notebook、Lab

Jupyter Notebook 是网页里的交互式编辑器:代码、说明文字、运行结果写在同一份 .ipynb 里,按单元格分段执行。适合数据分析、画图、调模型、写带结果的笔记。

JupyterLab 是其后继界面,带文件树、多标签和终端,现在更常用。Anaconda 两者都带:

jupyter notebook   # 经典 Notebook
jupyter lab        # JupyterLab(推荐)

第一个 Python 程序

在 Jupyter 中运行

  • 打开 Anaconda Navigator,在 JupyterLab 上点 Launch。
  • 浏览器打开 http://localhost:8888/lab(端口以终端提示为准)。
  • 在 Notebook → Python(conda env:base)新建 Untitled.ipynb
  • 在单元格里写代码,点 Run,结果出现在单元格下方。
print("Hello,Jupyter Lab!")
name = "AI!"
print(f"I am {name}。")

在 Notebook 里跑同目录的 .py 文件:

# hello.py 需与当前 Notebook 在同一目录
%run hello.py

在终端运行 .py 文件

python hello.py

核心语法

变量与数据类型

Python 是动态类型:赋值即创建变量,不必先声明类型。

类型 Python JS 对照 示例
字符串 str string "hello"
整数 int number 42
浮点数 float number 3.14
布尔值 bool boolean TrueFalse
空值 NoneType nullundefined None
列表 list array [1, 2, 3]
字典 dict objectMap {"key": "value"}
元组 tuple 无直接对应(不可变序列) (1, 2, 3)
集合 set Set {1, 2, 3}

与 JavaScript 的关键差异

  • 没有 letconstvar,直接 name = "…"
  • 布尔是 TrueFalse,空值是 None,首字母都大写。
  • 语句末尾不必写分号(写了也不报错)。
  • 用缩进表示代码块,不用 {}
name = "前端开发者"       # str
age = 28                 # int
height = 1.75            # float
is_learning = True       # bool
result = None            # 空值
ls = [10, 20, "hello", True, 3.14]
tup = (1, 2, "python", False)
d = {
    "name": "张三",
    "age": 25,
    "score": 95.5,
}

类型查看与转换

print(type(name))         # <class 'str'>
print(type(age))          # <class 'int'>
print(type(is_learning))  # <class 'bool'>

str_age = str(age)        # "28"
int_height = int(height)  # 1(向 0 截断,不是四舍五入)
float_age = float(age)    # 28.0
bool_value = bool(age)    # 非 0 → True;0、""、[]、None → False

字符串

单引号、双引号都可以(没有 JS 那种反引号字符串)。带变量用 f"…{expr}…",对应 JS 的模板字面量。

hello = "Hello"
word = "World"
message = f"{hello}{word}"
print(message)

multi_line = """
这是第一行
这是第二行
这是第三行
"""
print(multi_line)

常用方法

  • upper()lower():全大写、全小写。
  • capitalize():首字母大写,其余小写。
  • title():每个单词首字母大写。
  • swapcase():大小写对调。
  • strip([chars])lstriprstrip:去首尾(或左、右)字符,默认去空格、\t\n
  • findrfind:找子串,返回下标,找不到返回 -1
  • indexrindex:同上,找不到抛 ValueError
  • count(sub, start, end):统计出现次数。
  • replace(old, new, count):替换,count 限制次数。
  • zfill(width):左侧补 0。
  • centerljustrjust:对齐并填充。
  • expandtabs(tabsize):把 \t 展开成空格。
  • splitrsplitsplitlines:切割。
  • partitionrpartition:按第一次、最后一次分隔符切成三元组。
  • str.join(iterable):用当前字符串作分隔符拼接。
  • startswithendswith:前缀、后缀判断。
  • isdigitisalphaisalnumisspaceislowerisupperistitle:字符类别判断。isdigit() 只认 0-9
s = "  Hello Python  "
s.lower()
s.upper()
s.capitalize()
s.title()
s.swapcase()

s.strip()
s.lstrip()
s.rstrip()

s.isdigit()
s.isalpha()
s.isalnum()
s.isspace()

s.startswith("He")
s.endswith("on")

msg = "hello python hello"
msg.find("hello")
msg.index("hello")
msg.rfind("hello")
msg.rindex("hello")
msg.count("hello")

data = "lizhao,杭州,下雨"
lst = data.split(",")
",".join(lst)

"5".zfill(3)        # "005"
"hello".center(10)
"hello".ljust(10)
"hello".rjust(10)

切片s[start:end:step],左闭右开。越界不报错,自动截断。

s = "ABCDEFGHIJ"

print(s[1:4])      # BCD
print(s[0:3])      # ABC
print(s[:4])       # ABCD
print(s[4:])       # EFGHIJ
print(s[:])        # 复制整串
print(s[::2])      # ACEGI
print(s[1::2])     # BDFHJ
print(s[-3:])      # HIJ
print(s[-5:-2])    # FGH
print(s[::-1])     # 逆序
print(s[8:2:-1])
print(s[2:100])    # 越界截断

注意:字符串不可变,这些方法都返回新串,不改原串。

列表

列表可混放任意类型,用下标读写。负数下标从末尾数,JS 数组没有这种写法。

numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", True, None]

print(numbers[0])    # 1
print(numbers[-1])   # 5
print(numbers[-2])   # 4

numbers[2] = 99
print(numbers)

常用方法

  • append(item):末尾追加一个元素。
  • insert(index, item):在下标处插入。
  • extend(iterable):把另一个可迭代对象的元素逐个接上。
  • pop(index):按下标删除并返回;默认删最后一个。
  • remove(item):删第一个匹配值,没有则报错。
  • clear():清空,留下 []
  • lst[index] = 值:按下标改值。
  • index(item, start, end):查下标,找不到报错。
  • count(item):计数。
  • sort()sort(reverse=True):原地排序。
  • reverse():原地反转。
  • copy():浅拷贝(等价 lst[:])。
  • lst[start:end]:切片,得到新列表。
  • innot in:是否包含。
  • +*:拼接、重复,返回新列表。
  • len(lst):长度。
lst = [10, 20, 30]

lst.append(40)
lst.insert(1, 15)
lst.extend([50, 60])
lst.index(20)
lst.count(10)
lst.pop()
lst.remove(15)
lst.reverse()
lst.sort()
lst.sort(reverse=True)
lst.copy()
lst.clear()

lst[0] = 99

a = [1, 2]
b = [3, 4]
print(a + b)
print(a * 3)
print(2 in a)

注意appendextendinsertpopremoveclearsortreverse 改原列表;indexcountcopy 以及 +、切片不改原列表。

列表推导式:一行完成映射 + 过滤,对应 JS 的 mapfilter

numbers = [1, 2, 3, 4, 5, 6]

doubled = [n * 2 for n in numbers]
# JS: numbers.map(n => n * 2)

evens = [n for n in numbers if n % 2 == 0]
# JS: numbers.filter(n => n % 2 === 0)

result = [n * 2 for n in numbers if n % 2 == 0]
# JS: numbers.filter(n => n % 2 === 0).map(n => n * 2)

切片规则与字符串相同:

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(numbers[2:6])    # [2, 3, 4, 5]
print(numbers[:4])     # [0, 1, 2, 3]
print(numbers[6:])     # [6, 7, 8, 9]
print(numbers[-4:])    # [6, 7, 8, 9]
print(numbers[::2])    # [0, 2, 4, 6, 8]
print(numbers[::-1])   # 反转

元组

元组是不可变序列,写成 (1, 2, 3)。能下标、切片、解包,不能 append 或按位赋值。适合做函数多返回值、字典的键(元素本身也必须不可变)。只有一个元素时必须写逗号:(1,),否则 (1) 只是加了括号的整数。

tup = (1, 2, "python")
a, b, c = tup
print(tup[0], len(tup))

字典

字典是键值对,接近 JS 对象。键必须是不可变类型:字符串、数字、元组。

常用方法

  • dict[key] = value:没有则新增,有则覆盖。
  • update(...):批量写入,可传入字典或关键字参数。
  • setdefault(key, 默认值):已有键则不动;没有则写入默认值,并返回对应 value。
  • dict[key]:取值,键不存在抛 KeyError
  • get(key, 默认值):键不存在返回 None 或默认值,不抛错。
  • keys()values()items():键、值、键值对视图。
  • pop(key, [默认值]):删除并返回 value;无默认值且键不存在则报错。
  • popitem():删除并返回最后插入的 (key, value)(Python 3.7+ 字典保序)。
  • clear():清空。
  • copy():浅拷贝。
user = {
    "name": "lizhao",
    "city": "杭州",
    "weather": "台风",
}

user["job"] = "前端开发"
user["name"]
user.get("weather")
user.get("job", "未知")
job = user.pop("job")
del user["city"]

user.update({"company": "ABC"})
user.setdefault("city", "杭州")
user.setdefault("name", "李兆")  # 已有 name,不改

print(list(user.keys()))
print(list(user.values()))
print(list(user.items()))
print("name" in user)
print("phone" not in user)

user.clear()

遍历

user = {
    "name": "lizhao",
    "city": "杭州",
    "weather": "台风",
}

for key, value in user.items():
    print(f"{key}: {value}")

for key in user.keys():
    print(key)

for value in user.values():
    print(value)

字典推导式

squares = {x: x**2 for x in range(5)}
print(squares)

numbers = [1, 2, 3, 4, 5]
even_squares = {x: x**2 for x in numbers if x % 2 == 0}
print(even_squares)

集合

集合是不重复、无序的元素堆,写法 {1, 2, 3},对应 JS 的 Set。空集合必须写 set(){} 是空字典。支持 | 并、& 交、- 差。

s = {1, 2, 2, 3}
s.add(4)
print(s)          # {1, 2, 3, 4}
print(2 in s)

运算符

操作 JavaScript Python
相等 === ==(值相等,不随便做 JS 那种类型强制转换)
同一对象 ===(引用类型) is
不相等 !== !=is not
比较 > < >= <= 相同
逻辑与或非 && `\ \ `! andornot
成员 arr.includes(x) x in list

判断是否为 Noneis Noneis not None,不要写 == None

a = 10
b = 20

if a > 5 and b < 30:
    print("两个条件都成立")

if a > 15 or b > 15:
    print("至少一个条件成立")

if not a > 15:
    print("a 不大于 15")

fruits = ["苹果", "香蕉"]
if "苹果" in fruits:
    print("有苹果")
if "西瓜" not in fruits:
    print("没有西瓜")

条件判断

与 JS 相近,两处不同:分支关键字是 elif,代码块靠缩进而不是 {}

score = 85
if score >= 90:
    grade = "优秀"
elif score >= 80:
    grade = "良好"
elif score >= 60:
    grade = "及格"
else:
    grade = "不及格"

print(grade)

循环

for 接近 JS 的 for...of,直接遍历元素。需要下标时用 enumerate。没有 count++,要写 count += 1

ls = ["A", "B", "C"]

for e in ls:
    print(e)

for i, e in enumerate(ls):
    print(f"第{i + 1}个是{e}")

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

函数

def 定义。pass 表示空函数体,相当于 JS 的空 {}return a, b, c 实际返回一个元组,可以解包。

def greet(name):
    return f"你好,{name}!"

print(greet("前端"))


def placeholder():
    pass


def get_user():
    return "lizhao", "杭州", "下雨"

name, city, weather = get_user()
print(name, city, weather)

模块导入

模块(Module) 就是一个 .py 文件,可被其他文件 import

执行 import xxx 时,解释器按 sys.path 查找,常见顺序是:

  1. 当前脚本所在目录(交互式则是启动目录)
  2. 环境变量 PYTHONPATH 里的目录
  3. 标准库
  4. site-packages(第三方包,相当于 node_modules
import math
print(math.pi)
print(math.sqrt(16))
print(math.pow(2, 3))

from math import sqrt, pi, pow
print(pi)
print(sqrt(16))

import numpy as np
import pandas as pd
data = np.array([1, 2, 3])

from math import sqrt as square_root
print(square_root(25))

from math import * 会把模块里的名字倒进当前命名空间,容易重名,只适合演示,正式代码用 import math 或按名导入。

内置模块

无需安装即可用:

  • os:操作系统、文件、环境变量
  • sys:运行时、命令行参数
  • math:数学函数
  • json:JSON 读写
  • datetime:日期时间
  • random:随机数
  • re:正则
  • collectionsCounterdequedefaultdict 等(JS 的 MapSet 更接近内置 dictset
  • pathlib:面向对象的路径(见文件一节)

自定义模块

# utils.py
PI = 3.14159

def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

def greet(name):
    return f"你好,{name}!"

class Calculator:
    @staticmethod
    def subtract(a, b):
        return a - b
import utils
print(utils.PI)
print(utils.add(3, 5))
print(utils.Calculator.subtract(10, 3))

包(Package) 是装着多个模块的目录。

Python 3.3 起,没有 __init__.py 的目录也可以当命名空间包导入。常规项目仍建议保留 __init__.py:标明这是一个包,并在里面写初始化、__all__(控制 from package import * 导出哪些名字)。

package/
├── __init__.py
├── math_utils.py
├── string_utils.py
└── data/
    ├── __init__.py
    └── processor.py
import package.math_utils
result = package.math_utils.add(3, 5)

from package import math_utils
result = math_utils.add(3, 5)

from package.math_utils import add
result = add(3, 5)

from package.data.processor import process_data

安装第三方模块

pip 相当于 npm、yarn、pnpm。在 conda 环境里也可以用 conda install

pip install requests
pip install numpy pandas
pip install flask
pip install pandas==1.5.0

pip freeze > requirements.txt
pip install -r requirements.txt

虚拟环境

pip install 默认装进当前解释器的全局(或当前已激活环境)。多个项目共用一套包会互相踩版本。虚拟环境给每个项目单独一份 Python 和依赖,作用接近每个前端项目自己的 node_modules

用 conda:

conda create -n myenv python=3.11
conda activate myenv
conda install numpy pandas
conda deactivate
conda env list

不用 Anaconda 时,标准库写法是 python -m venv .venv,再激活后用 pip。

文件操作

读写文件用内置 open(),再配合 read()write()。文本请显式写 encoding="utf-8",避免 Windows 默认编码把中文读乱。

打开文件

模式 说明
'r' 只读(默认)。文件必须存在。
'w' 写入。存在则清空覆盖,不存在则创建。
'a' 追加。在末尾写,不存在则创建。
'x' 独占创建。已存在则报错。
'r+' 读写,文件必须存在。
'w+' 读写,存在则覆盖,不存在则创建。

二进制再加 b,如 'rb''wb'。文本模式可写 'rt't 可省略。

file = open("file.txt", "r", encoding="utf-8")
file = open("image.jpg", "rb")

文件读取

优先用 with,离开块时自动关闭,避免漏掉 close()

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

# 不推荐:容易忘记 close
file = open("file.txt", "r", encoding="utf-8")
content = file.read()
print(content)
file.close()

逐行读:

# 遍历文件对象,适合大文件
with open("file.txt", "r", encoding="utf-8") as file:
    for line in file:
        print(line.strip())

# 一次读成列表
with open("file.txt", "r", encoding="utf-8") as file:
    lines = file.readlines()
    for line in lines:
        print(line.strip())

# 自己控制何时读下一行
with open("file.txt", "r", encoding="utf-8") as file:
    while True:
        line = file.readline()
        if not line:
            break
        print(line.strip())

读指定个数(文本模式下按字符,不是按字节):

with open("file.txt", "r", encoding="utf-8") as file:
    chunk = file.read(100)
    print(chunk)

文件写入

with open("output.txt", "w", encoding="utf-8") as file:
    file.write("这是第一行内容\n")
    file.write("这是第二行内容\n")

with open("output.txt", "a", encoding="utf-8") as file:
    file.write("这是追加的第三行内容\n")

文件与路径

os.path 是函数式写法;pathlib.Path 更面向对象,新代码优先用它。

import os
from pathlib import Path

if os.path.exists("f.txt"):
    print("文件存在")
print(os.path.isfile("file.txt"))
print(os.path.isdir("file.txt"))

file_path = Path("file.txt")
if file_path.exists():
    print(file_path.is_file(), file_path.is_dir())
import os
from pathlib import Path

if not os.path.exists("data/output"):
    os.makedirs("data/output")

Path("data/output").mkdir(parents=True, exist_ok=True)
import os
from pathlib import Path

print(os.path.join("data", "output", "result.txt"))

root = Path("data")
print(root / "output" / "result.txt")

异常处理(try、except)

运行期无法继续时,Python 会抛出异常。不捕获则程序中止并打印栈。

概念 Python JavaScript
抛出 raise throw
捕获 try、except try、catch
总会执行 finally finally
无异常时 else 无直接对应
基类 Exception Error
自定义 class MyError(Exception) class MyError extends Error
try:
    result = 10 / 0
except Exception as e:
    print(f"发生了错误:{e}")
    print(f"错误类型:{type(e).__name__}")
def divide_numbers(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        print("除零错误!")
        return None
    except TypeError:
        print("类型错误!请传入数字")
        return None
    else:
        print("除法计算成功")
        return result
    finally:
        print("清理完成")

print(divide_numbers(10, 2))
print(divide_numbers(10, 0))
def validate_age(age):
    if age < 0:
        raise ValueError("年龄不能为负数!")
    if age > 150:
        raise ValueError("年龄不能超过150岁!")
    return f"年龄:{age},有效"

try:
    validate_age(-5)
except ValueError as e:
    print(f"验证失败:{e}")

日志记录

loggingprint 适合生产环境:能分级、同时打到控制台和文件,也能接到远程。

默认级别是 WARNINGDEBUGINFO 不会出现。下面把级别设成 DEBUG 之后,五行都会输出。

import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[
        logging.StreamHandler(),
        logging.FileHandler("app.log", encoding="utf-8"),
    ],
)

logging.debug("这是 DEBUG 级别")
logging.info("这是 INFO 级别")
logging.warning("这是 WARNING 级别")
logging.error("这是 ERROR 级别")
logging.critical("这是 CRITICAL 级别")

basicConfig 只在首次配置时生效;Notebook 里重复执行往往改不了已有配置,需要重启内核,或改用 logging.getLogger(name) 自己装 handler。

总结

Python 用缩进写块、动态类型,列表、字典、元组、集合对应前端最常用的几种结构。环境用 Anaconda 或 venv 隔离依赖,代码用 import 组织,文件用 with open 加 UTF-8,错误用 try、except,输出用 logging。这些够开始写 AI 相关的脚本;数值计算再接到 NumPy、Pandas、PyTorch。

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-08-18 22:07:38

results matching ""

    No results matching ""