Python 与编程基础概念:给零基础学习者的生活化解释
如果把编程想得太神秘,它会显得很难。其实,一个程序最基本的工作只有三步:
接收输入 → 处理数据 → 产生输出
可以把程序想成一家奶茶店:
- 顾客说“我要一杯少糖奶茶”,这是输入。
- “奶茶、少糖、中杯”是程序要处理的数据。
- 店员按照配方制作,这是函数在工作。
- 奶茶机的设计图像一个类,实际的一台奶茶机是一个对象。
- 配方册和工具箱像模块。
- 制作过程记录在工作日志里,这就是 log(日志)。
- 如果珍珠用完了,就出现了异常。
- 最后交给顾客的奶茶,就是输出。
下面逐个拆开解释。
1. 程序的输入(Input)
一句话解释
输入就是从程序外部进入程序的信息。
程序不会读心。要让它工作,我们必须把需要的信息交给它。
生活比喻
去奶茶店点单时,你告诉店员:
一杯中杯奶茶,少糖,加珍珠。
这句话就是奶茶店收到的输入。如果你什么都不说,店员就不知道该做什么。
常见输入来源
| 输入来源 | 例子 |
|---|---|
| 键盘 | 用户输入姓名 |
| 函数参数 | 把价格和数量交给计算函数 |
| 文件 | 读取 CSV、Excel、图片 |
| 数据库 | 查询用户或订单数据 |
| 网络 API | 获取天气、行情或新闻 |
| 传感器 | 手机获取位置、温度或加速度 |
Python 小例子
name = input("请输入你的名字:")
print("你好," + name)
运行时输入:
小明
变量 name 得到的数据就是字符串 "小明"。
函数也能接收输入:
def make_tea(sugar):
return f"制作一杯{sugar}糖奶茶"
result = make_tea("少")
这里的 "少" 是传给函数的输入。
小白易错点
input() 得到的内容默认是字符串,即使用户输入的是 18:
age_text = input("请输入年龄:")
print(type(age_text)) # <class 'str'>
如果要拿它做数学计算,需要先转换:
age = int(age_text)
print(age + 1)
2. 程序的输出(Output)
一句话解释
输出就是程序处理完后,送到程序外部的结果。
生活比喻
顾客点单是输入,店员制作后交出来的奶茶是输出。
输出不一定是在屏幕上显示一句话,也可以是一张图、一份文件或一段声音。
常见输出形式
| 输出去向 | 例子 |
|---|---|
| 屏幕或终端 | print("计算完成") |
| 函数调用者 | return total |
| 文件 | 保存 CSV、图片、报告 |
| 数据库 | 写入一条订单记录 |
| 网络 | API 返回 JSON |
| 硬件 | 控制灯亮起或电机转动 |
print 和 return 不一样
这是初学者最容易混淆的地方之一。
def add_with_print(a, b):
print(a + b)
def add_with_return(a, b):
return a + b
print() 像店员把结果喊给你听;return 像店员把做好的东西真正交到你手上,让你还能继续使用。
result_1 = add_with_print(2, 3)
print(result_1) # None,因为函数没有 return
result_2 = add_with_return(2, 3)
print(result_2 * 10) # 50
3. 数据(Data)
一句话解释
数据是程序读取、保存、计算和传递的具体信息。
例如:
"小明"
18
99.5
True
["奶茶", "咖啡", "果汁"]
这些都是数据。
生活比喻
数据像仓库里的货物。程序可以:
- 把货物搬进来:读取数据;
- 给货物贴标签:保存到变量;
- 加工货物:计算或修改数据;
- 把货物运出去:输出数据。
变量像贴了名字的收纳盒:
product_name = "珍珠奶茶"
price = 12.5
stock = 100
product_name、price 和 stock 是盒子上的标签,右边是盒子里当前装的数据。
数据、变量和值的区别
观察下面这行代码:
price = 12.5
price是变量名;12.5是值;- 这个值是一份数据;
float是这份数据的数据类型。
变量里的值可以改变:
price = 12.5
price = 15.0
第二行执行后,price 指向的新值是 15.0。
4. 数据类型(Data Type)
一句话解释
数据类型说明一份数据是什么,以及可以对它做什么操作。
生活比喻
数据类型像快递箱上的标签:
- “食品”可以吃;
- “玻璃”要轻拿轻放;
- “电器”要通电使用。
箱子里虽然都有“东西”,但不同东西的处理方式不同。
同样,Python 知道数字可以相加,文字可以拼接:
print(10 + 20) # 30
print("10" + "20") # 1020
两段代码都用了 +,但因为数据类型不同,结果也不同。
Python 常见数据类型
| 类型 | 中文理解 | 示例 |
|---|---|---|
int |
整数 | 18、-3 |
float |
小数 | 12.5、0.01 |
str |
字符串,即文字 | "Python" |
bool |
布尔值,只有真或假 | True、False |
list |
有顺序、可修改的一组数据 | ["茶", "咖啡"] |
tuple |
有顺序、通常不修改的一组数据 | (10, 20) |
dict |
用“键”查“值”的数据 | {"name": "奶茶", "price": 12} |
set |
不重复元素的集合 | {"奶茶", "咖啡"} |
NoneType |
暂时没有值 | None |
可以用 type() 查看类型:
print(type(18)) # <class 'int'>
print(type(12.5)) # <class 'float'>
print(type("Python")) # <class 'str'>
print(type(["奶茶", "咖啡"])) # <class 'list'>
类型转换
类型转换像把同一份内容换一种包装:
age_text = "18"
age_number = int(age_text)
price = 12.8
price_text = str(price)
但不是所有内容都能随便转换:
int("十八") # 会产生 ValueError 异常
5. 函数(Function)
一句话解释
函数是一段被起了名字、可以重复调用的操作步骤。
函数通常做三件事:
接收参数 → 执行处理 → 返回结果
生活比喻
函数像奶茶店的一张标准配方:
输入:杯型、甜度
处理:加茶、加奶、加糖、摇匀
输出:一杯奶茶
有了配方,店员不用每次都重新发明做法。
Python 小例子
def calculate_total(price, quantity):
total = price * quantity
return total
bill = calculate_total(12.5, 3)
print(bill) # 37.5
这里:
def表示“定义一个函数”;calculate_total是函数名;price和quantity是参数;12.5和3是调用时传入的实际参数值;return total把结果交还给调用者。
为什么要用函数
- 避免复制相同代码;
- 给一组操作起一个容易理解的名字;
- 把大问题拆成小问题;
- 方便测试和修改。
没有参数或没有返回值也可以
def say_hello():
print("你好!")
say_hello()
这个函数不接收参数,也没有明确的 return。Python 会自动让它返回 None。
6. 高阶函数(Higher-order Function)
一句话解释
高阶函数是能接收其他函数作为参数,或者能返回一个函数的函数。
这个名字听起来很高级,但思路并不复杂。
生活比喻
把普通函数想成一名会做某件事的员工:
- 小王会“打九折”;
- 小李会“减 5 元”。
高阶函数像一位店长。店长自己不规定一定用哪种优惠,而是接收一个“优惠方案”,再把它应用到价格上。
def ten_percent_off(price):
return price * 0.9
def reduce_five(price):
return price - 5
def apply_discount(price, discount_function):
return discount_function(price)
print(apply_discount(100, ten_percent_off)) # 90.0
print(apply_discount(100, reduce_five)) # 95
apply_discount 接收了另一个函数 discount_function,所以它是高阶函数。
注意,传递函数本身时不要加括号:
apply_discount(100, ten_percent_off) # 传入函数,正确
apply_discount(100, ten_percent_off()) # 先调用函数,而且缺少参数,会报错
Python 中常见的高阶函数
sorted() 可以接收一个函数,告诉它“按什么规则排序”:
products = [
{"name": "奶茶", "price": 12},
{"name": "咖啡", "price": 18},
{"name": "果汁", "price": 10},
]
sorted_products = sorted(
products,
key=lambda product: product["price"],
)
这里的 lambda 是一个简短的匿名函数。它告诉 sorted():请按照每个商品的 price 排序。
高阶函数的价值是把“固定流程”和“可替换规则”分开。
7. 对象(Object)
一句话解释
对象是程序中的一个具体事物,它既能保存数据,也能提供与这些数据有关的操作。
生活比喻
一台真实的奶茶机是一个对象。它有:
- 属性:品牌、颜色、当前水温;
- 行为:加热、搅拌、停止。
在编程中,属性通常是对象保存的数据,行为通常由方法提供。
Python 小例子
message = "hello"
print(message.upper()) # HELLO
print(message.startswith("h")) # True
message 是一个字符串对象:
- 它保存了
"hello"; - 它有
.upper()和.startswith()等方法。
列表也是对象:
drinks = ["奶茶", "咖啡"]
drinks.append("果汁")
print(drinks)
.append() 是列表对象提供的方法。
Python 中“很多东西都是对象”
数字、字符串、列表、函数,甚至类本身,在 Python 中都是对象。初学时不必钻研这句话的全部细节,只要先记住:
对象不只是一个值,它还知道自己能做哪些操作。
8. 类(Class)
一句话解释
类是创建同一类对象的设计图;对象是根据设计图创建出来的具体实例。
生活比喻
- “奶茶机设计图”是类;
- 店里编号为 A01 的真实奶茶机是一个对象;
- 编号为 A02 的另一台机器也是一个对象。
两台机器来自同一张设计图,所以有相似的结构和功能,但可以有不同的品牌、颜色和状态。
Python 小例子
class Drink:
def __init__(self, name, price):
self.name = name
self.price = price
def describe(self):
return f"{self.name},价格 {self.price} 元"
milk_tea = Drink("珍珠奶茶", 12)
coffee = Drink("拿铁", 18)
print(milk_tea.describe())
print(coffee.describe())
这里:
Drink是类;milk_tea和coffee是两个对象,也叫两个实例;__init__在创建对象时负责设置初始数据;self.name和self.price是对象的属性;describe()是对象的方法;self代表“当前正在操作的这个对象”。
类和对象的关系
| 类 | 对象 |
|---|---|
| 设计图 | 按图生产出的具体物品 |
Drink |
milk_tea |
| 描述共同结构和行为 | 保存自己的实际状态 |
| 通常只定义一次 | 可以创建很多个 |
什么时候需要自己写类
当一组数据和相关操作经常一起出现,而且你要创建多个同类事物时,类会很有用。
如果只是写一个很短的计算,普通函数通常已经足够,不必为了“看起来高级”而强行写类。
9. 模块(Module)
一句话解释
模块通常就是一个 .py 文件,用来集中存放相关的变量、函数和类。
生活比喻
模块像一个有标签的工具箱:
math工具箱放数学工具;logging工具箱放日志工具;- 自己写的
discounts.py可以放优惠计算工具。
把工具分类收好,比把所有东西堆在一个文件里更容易寻找和复用。
使用 Python 自带模块
import math
print(math.sqrt(16)) # 4.0
math 是模块,sqrt 是其中的平方根函数。
也可以只导入需要的工具:
from math import sqrt
print(sqrt(16))
自己写一个模块
假设有文件 discounts.py:
def ten_percent_off(price):
return price * 0.9
在另一个同目录的 Python 文件里可以这样使用:
from discounts import ten_percent_off
print(ten_percent_off(100))
模块、包和库的简单区别
| 名称 | 初学者可以这样理解 |
|---|---|
| 模块 module | 一个 Python 工具文件 |
| 包 package | 装着多个相关模块的文件夹 |
| 库 library | 为某类任务准备的一整套可复用工具 |
日常交流中,人们有时会把这些词混着用。初学阶段先理解“导入现成工具并复用”最重要。
10. NumPy
一句话解释
NumPy 是 Python 中高效处理大量数字和多维数组的基础工具库。
NumPy 不是 Python 的内置语法,通常需要安装后再导入。它的常用别名是 np:
import numpy as np
生活比喻
普通 Python 列表像一个杂物篮,可以同时放数字、文字等不同东西。
NumPy 数组更像一排规格统一的储物格,通常装同一种类型的数据,因此可以成批、高效地处理。
Python 列表和 NumPy 数组的区别
python_list = [1, 2, 3]
print(python_list * 2) # [1, 2, 3, 1, 2, 3]
列表乘以 2 表示重复两遍。
import numpy as np
numbers = np.array([1, 2, 3])
print(numbers * 2) # [2 4 6]
NumPy 数组乘以 2,会让每个元素都乘以 2。这种一次对整批数据运算的方式常叫“向量化运算”。
常见操作
import numpy as np
prices = np.array([10.0, 12.0, 11.0, 15.0])
print(prices.mean()) # 平均值
print(prices.max()) # 最大值
print(prices.min()) # 最小值
print(prices + 1) # 每个价格都加 1
二维数组可以想成一个数字表格:
sales = np.array([
[10, 20, 30],
[15, 25, 35],
])
print(sales.shape) # (2, 3),2 行 3 列
NumPy 适合做什么
- 数值计算;
- 矩阵和数组运算;
- 统计计算;
- 科学计算;
- 作为 Pandas、机器学习和绘图库的底层基础之一。
11. Pandas
一句话解释
Pandas 是 Python 中处理带行列标签的表格数据和时间序列数据的常用工具库。
常用别名是 pd:
import pandas as pd
生活比喻
如果 NumPy 像一大片规则的数字储物格,那么 Pandas 更像一张有:
- 行号;
- 列名;
- 不同类型的列;
- 筛选、排序、分组功能
的智能 Excel 表。
两个核心结构
Series:带索引的一列数据;DataFrame:由多列数据组成的表格。
DataFrame 小例子
import pandas as pd
orders = pd.DataFrame({
"product": ["奶茶", "咖啡", "果汁"],
"price": [12, 18, 10],
"quantity": [2, 1, 3],
})
orders["total"] = orders["price"] * orders["quantity"]
print(orders)
结果类似:
product price quantity total
0 奶茶 12 2 24
1 咖啡 18 1 18
2 果汁 10 3 30
筛选总价大于 20 的订单:
large_orders = orders[orders["total"] > 20]
print(large_orders)
计算每种商品的销售总额:
sales_by_product = orders.groupby("product")["total"].sum()
print(sales_by_product)
Pandas 适合做什么
- 读取 CSV、Excel、Parquet 等文件;
- 清洗缺失值和错误数据;
- 按条件筛选;
- 排序和分组统计;
- 合并多张表;
- 处理日期和时间序列;
- 为分析、画图和机器学习准备数据。
NumPy 和 Pandas 怎么选
| 需求 | 更常用的工具 |
|---|---|
| 主要是规则的数字数组、矩阵计算 | NumPy |
| 需要列名、索引、筛选、分组和表格处理 | Pandas |
它们不是竞争关系。Pandas 与 NumPy 配合紧密,实际项目中经常一起使用。
12. Log(日志)
一句话解释
日志是程序运行时主动留下的过程记录,用来说明何时发生了什么。
生活比喻
日志像奶茶店的值班记录:
09:00 开店
09:05 收到第 1 个订单
09:08 订单制作完成
10:30 珍珠库存不足
顾客只关心最终拿到的奶茶,但店员和管理者需要这些过程记录来排查问题。
为什么不总是用 print
print() 适合学习和临时查看。正式程序中的日志通常还能记录:
- 时间;
- 严重程度;
- 来自哪个模块;
- 详细错误信息;
- 输出到终端或日志文件。
Python 日志示例
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s | %(levelname)s | %(message)s",
)
logging.info("程序开始")
logging.warning("珍珠库存不足")
logging.error("订单保存失败")
常见日志等级
| 等级 | 用途 |
|---|---|
DEBUG |
很详细的调试信息 |
INFO |
程序正常运行的重要节点 |
WARNING |
出现风险,但程序还能继续 |
ERROR |
某个操作失败 |
CRITICAL |
非常严重,程序可能无法继续 |
日志不是越多越好。好的日志应当帮助人回答:
程序运行到了哪里?用了什么关键条件?为什么失败?
注意:log 也可能表示数学中的对数
在数学和 NumPy 代码里,log 常表示自然对数:
import numpy as np
print(np.log(np.e)) # 约等于 1.0
所以看到 log 时要结合上下文判断:
logging.info(...)说的是程序日志;np.log(...)说的是数学对数。
13. 异常(Exception)
一句话解释
异常是程序运行过程中出现的、打断正常流程的特殊情况。
生活比喻
奶茶店正常流程是:
接单 → 制作 → 交付
但制作时可能遇到:
- 顾客输入了不存在的杯型;
- 价格文字无法转换成数字;
- 原料用完;
- 收款系统断网。
这些都像程序中的异常。
常见异常
int("十二") # ValueError:值无法转换
10 / 0 # ZeroDivisionError:除数不能为 0
items[10] # IndexError:列表位置不存在
order["phone"] # KeyError:字典里没有这个键
如果异常没有被处理,程序通常会停止,并显示 traceback(错误追踪信息)。它会告诉我们:
- 异常类型;
- 错误说明;
- 出错文件和行号;
- 错误经过了哪些函数。
traceback 不是“可怕的红字”,而是程序留给我们的故障路线图。通常先从最后一行看异常类型和原因。
用 try 和 except 处理可预期异常
price_text = input("请输入价格:")
try:
price = float(price_text)
except ValueError:
print("价格必须是数字")
else:
print(f"价格是 {price} 元")
finally:
print("输入处理结束")
执行顺序可以这样理解:
| 关键字 | 含义 |
|---|---|
try |
尝试执行可能失败的代码 |
except |
指定异常发生后怎么办 |
else |
没发生异常时执行 |
finally |
无论是否发生异常,最后都执行 |
自己主动抛出异常
当输入违反业务规则时,可以用 raise 主动报告:
def calculate_total(price, quantity):
if price < 0:
raise ValueError("价格不能是负数")
if quantity < 0:
raise ValueError("数量不能是负数")
return price * quantity
不要把所有异常悄悄吞掉
下面的写法会让真正的问题消失,通常不推荐:
try:
result = risky_operation()
except Exception:
pass
更好的做法是:
- 只捕获你知道如何处理的异常;
- 给用户清楚的提示;
- 必要时写入日志;
- 无法正确处理时,让异常继续暴露。
14. 把所有概念串起来
下面这个小程序模拟奶茶订单统计:
import logging
import numpy as np
import pandas as pd
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s | %(message)s",
)
class Drink:
"""饮品类:创建具体饮品对象的设计图。"""
def __init__(self, name, price):
if price < 0:
raise ValueError("价格不能是负数")
self.name = name
self.price = price
def calculate_total(self, quantity):
if quantity < 0:
raise ValueError("数量不能是负数")
return self.price * quantity
def ten_percent_off(amount):
"""普通函数:把金额打九折。"""
return amount * 0.9
def apply_discount(amount, discount_function):
"""高阶函数:接收另一个函数作为优惠规则。"""
return discount_function(amount)
def build_order_table(drinks, quantities):
"""把对象和数量转换成 Pandas 表格。"""
rows = []
for drink, quantity in zip(drinks, quantities):
rows.append({
"product": drink.name,
"price": drink.price,
"quantity": quantity,
"total": drink.calculate_total(quantity),
})
return pd.DataFrame(rows)
try:
# 数据和对象
drinks = [
Drink("奶茶", 12),
Drink("咖啡", 18),
Drink("果汁", 10),
]
# 输入数据
quantities = [2, 1, 3]
# 函数处理后得到 Pandas DataFrame
orders = build_order_table(drinks, quantities)
# NumPy 数组和数值计算
totals = orders["total"].to_numpy()
average_order = np.mean(totals)
# 高阶函数
original_total = orders["total"].sum()
discounted_total = apply_discount(original_total, ten_percent_off)
# 日志记录过程
logging.info("成功生成 %s 条订单", len(orders))
# 输出
print(orders)
print(f"平均订单金额:{average_order:.2f} 元")
print(f"优惠后总金额:{discounted_total:.2f} 元")
except ValueError as error:
logging.error("订单数据不正确:%s", error)
在这个例子中:
| 概念 | 对应内容 |
|---|---|
| 输入 | quantities 和饮品价格等原始信息 |
| 输出 | 订单表、平均金额和优惠后金额 |
| 数据 | 名称、价格、数量、总金额 |
| 数据类型 | 字符串、整数、列表、DataFrame 等 |
| 函数 | ten_percent_off()、build_order_table() |
| 高阶函数 | apply_discount() 接收优惠函数 |
| 类 | Drink |
| 对象 | Drink("奶茶", 12) 等实例 |
| 模块 | logging、numpy、pandas |
| NumPy | 把金额转成数组并计算平均值 |
| Pandas | 创建和处理订单表 |
| log | 记录订单生成成功或失败 |
| 异常 | 用 raise 报告非法数据,用 try/except 处理 |
15. 一张图记住它们的关系
输入(键盘、文件、参数、API)
↓
数据与数据类型
↓
处理数据 ← 函数(可重复的步骤)
↑ ← 对象(数据 + 操作)← 类(对象的设计图)
↑ ← 模块(分类收纳函数和类)
↑ ← NumPy(数组与数值计算)
↑ ← Pandas(表格与时间序列)
↓
输出(结果、文件、图表、API)
处理过程 ──留下记录──→ Log 日志
处理过程 ──遇到意外──→ 异常
16. 最后用一句话复习
| 概念 | 一句话记忆 | 奶茶店比喻 |
|---|---|---|
| 程序的输入 | 进入程序的信息 | 顾客点单 |
| 程序的输出 | 程序交出的结果 | 做好的奶茶 |
| 数据 | 程序处理的具体信息 | 商品、价格、数量 |
| 数据类型 | 数据的类别和操作规则 | 快递箱上的物品标签 |
| 函数 | 可重复调用的一套步骤 | 奶茶配方 |
| 高阶函数 | 能接收或返回函数的函数 | 能更换优惠方案的店长 |
| 对象 | 有数据也有操作的具体事物 | 一台真实奶茶机 |
| 类 | 创建同类对象的设计图 | 奶茶机设计图 |
| 模块 | 分类收纳代码的工具箱 | 配方或工具柜 |
| NumPy | 高效处理数字数组 | 规格统一的数字储物格 |
| Pandas | 处理带标签的表格数据 | 智能 Excel 表 |
| Log | 程序运行过程的记录 | 门店值班日志 |
| 异常 | 打断正常流程的特殊情况 | 原料不足或输入错误 |
最重要的主线仍然是:
输入数据
→ 按数据类型理解它
→ 用函数或对象处理它
→ 借助模块、NumPy、Pandas 等工具
→ 用日志记录过程
→ 用异常机制面对意外
→ 得到输出
不必一次背下所有术语。先能看懂它们分别在解决什么问题,再通过小程序反复使用,概念就会慢慢变成直觉。