1. 概述

变量是给数据起的名字。我们不必每次都直接面对一段字符串、一个数字或一组列表,而是先给它一个容易理解的名字,后面通过这个名字使用数据。

main.py
1
name = "小微"
2
age = 18
3
4
print(name)
5
print(age)

这里的 nameage 就是变量,"小微"18 是它们当前指向的数据。

初学时可以先把 name = "小微" 读成“让变量 name 指向字符串 "小微"”。等理解了这个关系,就不容易把 Python 变量误解成只能存放一种固定类型的盒子。

2. 创建、读取和修改变量

Python 使用等号 = 进行赋值。第一次给一个名字赋值时,这个名字就创建出来了;之后再次赋值,就是让它指向新的数据。

main.py
1
message = "欢迎学习 Python"
2
print(message)
3
4
message = "今天继续学习变量"
5
print(message)

第二次赋值不会修改原来的字符串,而是让 message 改为指向新的字符串。变量名相同,当前指向的数据可以不同。

正在加载图示...

变量的值可以参与计算、拼接和条件判断:

main.py
1
price = 30
2
quantity = 2
3
total = price * quantity
4
5
print(f"总价是 {total} 元")

等号右边先计算,得到结果后再赋给等号左边的变量。因此,total 保存的是 price * quantity 的计算结果。

如果直接读取一个还没有创建的变量,Python 会抛出 NameError

main.py
1
print(username) # NameError:username 还没有定义

把变量放在使用它的代码之前,是最简单也最可靠的习惯。

3. 语言特性

在一些语言中,创建变量时要先写明它只能保存什么类型。Python 不需要这样做:

main.py
1
score = 100
2
name = "小微"
3
enabled = True

Python 会根据右侧的值,运行时确定它对应的类型。也就是说,下面的代码是合法的:

main.py
1
value = 18
2
print(type(value))
3
4
value = "十八"
5
print(type(value))

这叫做动态类型:类型检查和类型确定发生在运行过程中,而不是写变量声明时。它让代码更简洁,但也意味着拼写错误或类型不匹配,往往要到运行代码时才会暴露。

但是要注意,python 不会自动把所有类型拼在一起。比如,数字和字符串不能直接相加:

main.py
1
age = 18
2
message = "年龄:" + age # TypeError

需要先明确转换类型,或者使用 f-string 进行拼接:

main.py
1
age = 18
2
3
message = "年龄:" + str(age)
4
print(message)
5
6
print(f"年龄:{age}")

Python 的这种表现通常被称为强类型:语言不会在不明确的情况下悄悄替你转换不兼容的类型。动态类型解决的是“什么时候确定类型”,强类型解决的是“不同类型能不能直接参与操作”,它们不是一回事。

需要特别注意:变量名保存的是对象引用

在 Python 中,变量更像一个标签,贴在对象上。多个变量可以同时指向同一个对象:

main.py
1
languages = ["Python"]
2
another_name = languages
3
4
another_name.append("LangChain")
5
print(languages) # ['Python', 'LangChain']

another_name = languages 没有复制列表,而是让两个名字指向同一个列表对象。因此通过其中一个名字修改列表,另一个名字看到的内容也会改变。

这也是 Python 中“赋值”和“复制”需要区分的原因。如果确实需要一份独立的列表,可以显式复制:

main.py
1
languages = ["Python"]
2
another_name = languages.copy()
3
4
another_name.append("LangChain")
5
print(languages) # ['Python']
6
print(another_name) # ['Python', 'LangChain']

变量本身没有固定类型,它当前指向的对象有类型。type() 可以查看对象类型,isinstance() 可以判断对象是否属于某个类型:

main.py
1
value = 18
2
3
print(type(value))
4
print(isinstance(value, int))
5
print(isinstance(value, str))

这种设计也支持 Python 常见的鸭子类型思想:函数通常关心对象能做什么,而不是它具体属于哪个类。例如,只要对象支持 len(),就可以传给下面的函数:

main.py
1
def show_length(value):
2
return len(value)
3
4
print(show_length("Python"))
5
print(show_length(["FastAPI", "LangChain"]))

有些对象创建后不能直接修改,这类对象叫不可变对象,例如整数、字符串和元组。对它们进行“修改”时,Python 实际上会创建一个新对象,再让变量名指向新对象:

main.py
1
message = "你好"
2
message += ",小微"
3
print(message)

列表和字典属于常见的可变对象,可以在原对象上修改内容:

main.py
1
tasks = ["阅读"]
2
tasks.append("写代码")
3
print(tasks) # ['阅读', '写代码']

理解这一区别很重要:重新给变量赋值,是改变变量名的指向;调用 append() 这类方法,是直接修改可变对象本身。

4. 命名规则

变量名必须遵守几条语法规则:

  • 只能包含字母、数字和下划线,不能包含空格和连字符;
  • 不能以数字开头;
  • 区分大小写,nameName 是两个不同的名字;
  • 不能使用 Python 的关键字,例如 ifforclassdef
main.py
1
user_name = "小微" # 推荐:使用下划线分隔单词
2
user2 = "小明" # 可以:数字不能放在开头
3
4
# 2users = "错误" # 错误:不能以数字开头
5
# user-name = "错误" # 错误:连字符会被解释为减号

除了语法规则,项目还需要统一命名习惯。Python 社区通常使用 snake_case 命名变量和函数,使用大写字母加下划线表示希望保持不变的常量:

main.py
1
DEFAULT_TIMEOUT = 30
2
user_name = "小微"
3
4
def build_message(user_name: str) -> str:
5
return f"你好,{user_name}!"

DEFAULT_TIMEOUT 只是命名约定,Python 不会阻止别人重新给它赋值。大写名称的作用是提醒协作者:这个值在程序运行期间最好不要修改。

5. 常见的数据类型

变量可以指向各种对象,最常见的类型包括:

类型示例用途
int18整数
float3.14小数
str"Python"文本
boolTrueFalse是或否
NoneTypeNone表示“目前没有值”
list["Python", "FastAPI"]有顺序、可修改的一组数据
tuple("Python", "FastAPI")有顺序、通常不修改的一组数据
dict{"name": "小微"}用键查找值
main.py
1
name = "小微"
2
skills = ["Python", "FastAPI"]
3
profile = {"name": name, "skills": skills}
4
last_login = None
5
6
print(profile["name"])
7
print(last_login)

None 不是字符串,也不是数字。它通常用来表示“还没有结果”“暂时未知”或“这里有意留空”。判断它时,推荐使用 is None

main.py
1
if last_login is None:
2
print("用户还没有登录记录")

6. 多个变量一起赋值

Python 支持在一行中给多个变量赋值:

main.py
1
first_name, last_name = "小", "微"
2
print(first_name, last_name)

等号右侧的值会按照顺序交给左侧的变量。这种写法叫序列解包,也可以用来交换两个变量的值:

main.py
1
left = "左边"
2
right = "右边"
3
4
left, right = right, left
5
print(left) # 右边
6
print(right) # 左边

如果左右数量对不上,Python 会提示解包数量错误。需要接收剩余内容时,可以使用带星号的变量:

main.py
1
first, *middle, last = [1, 2, 3, 4]
2
print(first) # 1
3
print(middle) # [2, 3]
4
print(last) # 4

7. 在 FastAPI 和 LangChain 中使用变量

前面创建 FastAPI 服务时,变量负责把配置、请求数据和模型调用连接起来:

main.py
01
import os
02
03
from fastapi import FastAPI
04
from pydantic import BaseModel
05
from langchain_openai import ChatOpenAI
06
07
app = FastAPI()
08
09
model_name = os.environ["DEEPSEEK_MODEL"]
10
api_key = os.environ["DEEPSEEK_API_KEY"]
11
base_url = os.environ.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com")
12
13
model = ChatOpenAI(
14
model=model_name,
15
api_key=api_key,
16
base_url=base_url,
17
)
18
19
class ChatRequest(BaseModel):
20
question: str
21
22
@app.post("/chat")
23
async def chat(request: ChatRequest) -> dict[str, str]:
24
response = await model.ainvoke(request.question)
25
answer = response.content
26
return {"answer": answer}

这里的 model_nameapi_keybase_url 都是变量。它们让配置读取、模型创建和接口处理各自有清楚的名字。request.question 是请求对象中的变量,response 是模型返回的消息对象,answer 则保存最终要返回给浏览器的文本。

不要为了少写几行代码,把所有逻辑压成一条很长的表达式。给中间结果起一个有意义的名字,调试时可以直接打印或检查它,也方便之后把模型逻辑拆到独立模块。

订阅后可阅读剩余内容
LangChain Python
已发布5计划发布50目标已完成10%