前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

Python基础小结(一) 从语法到标准库的入门笔记

首页2019-12-10 17:40:39Back-End
python编程基础

起因很具体:手上有一堆埋点数据要做分析,Excel 已经拉不动了,同事甩过来一句「用 Python 吧,pandas 十行搞定」。我平时写前端,JavaScript 用得熟,本以为换个语言就是换套语法,结果第一天就被缩进、元组和 is 这几个东西绊住了好几次。

这篇是我边学边记的整理稿。它不是教程,更像是一份「JavaScript 写多了的人来学 Python 会在哪里卡住」的对照笔记,每个知识点后面尽量补一句为什么这么设计、什么时候会翻车。代码能跑的都跑过一遍,跑不通的地方我也标出来了。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • Python 的定位和特点,以及它为什么慢却还是数据分析首选
  • 注释、命名、保留字这些语法地基,和 input / eval / print 三个入门函数
  • 基本类型的分类,以及类型判断为什么推荐 isinstance 而不是 type
  • 序列的共性,可变类型与不可变类型的分界线在哪
  • 运算符里最容易记混的 is 与 ==
  • 循环、条件、枚举的写法
  • 闭包、lambda、map / reduce / filter 与装饰器
  • 面向对象的类变量、实例变量、私有成员和继承
  • 正则、内建函数、标准库全景
  • 异常处理与 JSON 序列化
  • 一个能跑的原生爬虫例子
  • datetime 和 random 两个高频库的用法
  • 列表推导式等日常提效技巧

这篇偏细节和代码,配套的 Python基础小结(二)是一整套思维导图,负责把知识结构串起来,两篇搭配着看会顺一些。

# 一、导语

先说 Python 是个什么语言。它是解释型语言,源码不需要提前编译成机器码,交给解释器逐行执行。改完就能跑,跨平台成本很低,代价是执行速度比 C、Java 这类编译型语言慢。

那它能做什么:

  • 大数据分析
  • 自动化运维与自动化测试
  • web 开发,常用框架有 flask、django
  • 机器学习,比如 TensorFlow
  • 胶水语言,比如混合 C++、Java 编程,把其他语言编写的模块连接在一起

最后那条「胶水语言」值得多说一句。Python 自己跑得不快,但它能很轻松地把 C 写的高性能库包起来调用。所以做数据分析时你写的是 Python,真正干活的是 NumPy 里的 C 代码。这就解释了那个常见的疑问,既然慢为什么大家还都用它?因为慢的那部分早就被换掉了,留给你的是开发效率。

Python 语言的特点

  • 语法简洁
  • 可跨平台
  • 应用广泛
  • 支持中文
  • 强制可读:通过强制缩进体现语句间的逻辑关系,提高了程序的可读性
  • 模式多样:语法层面同时支持面向过程和面向对象两种编程方式
  • 粘性扩展:通过接口和函数集成其他语言编写的代码
  • 开源理念
  • 库类丰富

「强制可读」这条是从 JavaScript 转过来最不习惯的地方。别的语言用花括号划分代码块,缩进只是风格;Python 把缩进写进了语法,缩进错了直接是语法错误。适应之后其实挺好,团队里再也不会有人为大括号换不换行吵架。这里有个坑要注意,Tab 和空格混用会报 TabError,官方推荐统一用 4 个空格,编辑器里配好自动转换。

Python 语言开发环境配置

  • Python 解释器
  • IDLE 开发环境
  • 交互式启动
  • 文件式启动
  • Python 语言集成开发环境 PyCharm

刚入门用自带的 IDLE 或者命令行的交互式解释器就够了,写一行看一行结果,学语法最快。项目大起来再换 PyCharm 或者 VS Code 配 Python 插件。

# 二、基本知识

这一节是语法地基,看着枯燥,但后面每一处报错基本都能追回到这里。

# 注释

注释是辅助性文字,不被执行。单行注释以 # 开头:

# 这是注释
@前端进阶之旅: 代码已经复制到剪贴板

多行注释以 '''(3 个单引号)开头和结尾:

'''
这是注释
这也是注释
这还是注释
'''
@前端进阶之旅: 代码已经复制到剪贴板

三引号那种严格来说不是注释语法,它是一个没有赋值给任何变量的字符串字面量,解释器算出来之后就丢掉了,效果上等同于注释。写在函数或类的第一行时它有正式身份,叫文档字符串,help() 和 IDE 的提示都读它。

# 命名

命名是为变量关联标识符的过程,用于确保程序元素的唯一性。规则有四条:

  • 标识符由字母、数字、下划线(和汉字)等字符及其组合构成
  • 标识符的首字符不能是数字,且中间不能出现空格
  • 标识符对大小写敏感
  • 不能和保留字重名

汉字确实能当变量名,但除了写演示代码没什么实用价值,团队协作里别这么干。命名风格上,Python 社区用下划线分隔的 user_name 而不是驼峰的 userName,这一点和 JavaScript 相反,PEP 8 里写得很明确。

# 保留字

保留字(Keyword)也被称为关键字,是被编程语言内部定义并保留使用的标识符,不能拿来当变量名。

Python 的标准库提供了一个 keyword 模块,可以输出当前版本的所有关键字:

>>> import keyword
>>> ls = keyword.kwlist
>>> ls
>>> len(ls)
33
@前端进阶之旅: 代码已经复制到剪贴板

Python 3 早期版本有 33 个保留字

  • True
  • False
  • None
  • and
  • as
  • assert
  • break
  • class
  • continue
  • def
  • del
  • elif
  • else
  • except
  • finally
  • for
  • from
  • global
  • if
  • import
  • in
  • is
  • lambda
  • nonlocal
  • not
  • or
  • pass
  • raise
  • return
  • try
  • while
  • with
  • yield

这个 33 是当时跑出来的数字,现在得改一下。从 Python 3.7 开始 async 和 await 正式成为关键字,keyword.kwlist 的长度变成了 35。3.10 之后又引入了 match、case、_ 这三个软关键字,它们不在 kwlist 里,而是单独放在 keyword.softkwlist,仍然可以当变量名用。所以别背数字,直接在你自己的解释器里跑一次 len(keyword.kwlist) 最靠谱。

# input() 函数

使用 input() 函数从控制台获得用户输入,它以字符串类型返回结果。

这里有个新手必踩的坑:不管用户输入的是不是数字,input() 拿到的永远是 str。想做加法得先 int() 转一次,否则 '1' + '2' 会得到 '12' 而不是 3。

# eval() 函数

eval(<字符串>) 函数的作用是把输入的字符串当成 Python 表达式来求值并执行。

x = eval(input("请输入:"))
@前端进阶之旅: 代码已经复制到剪贴板

这样写确实省事,用户输入 1+2 直接得到 3。但生产代码里别用它接用户输入,因为 eval 会执行任意表达式,输入里塞一句删文件的代码它也照跑。只需要把字符串转成数字或者列表字典,用 int()、float() 或者 ast.literal_eval(),后者只解析字面量,不执行代码。

# print() 函数

print() 函数可以输出字符信息,也可以用字符的形式输出变量。输出字符信息时,直接把待输出内容传给它;输出变量值时,用槽格式配合 format() 方法将变量和字符串结合到一起输出。

print('{}今年{}岁'.format('poetries', 22))
@前端进阶之旅: 代码已经复制到剪贴板

Python 3.6 之后有了更短的 f-string 写法,print(f'{name}今年{age}岁'),直接把变量写进大括号里,可读性好很多,现在基本是首选。原来的 % 格式化和 format() 仍然能用,读老代码时会遇到。

# 函数

函数可以理解为对一组表达特定功能的表达式的封装,把特定功能的代码写在一个函数里,程序的模块化更好,也便于阅读和复用。通过保留字 def 自定义函数。

# 文件操作

文件读写是最容易忘记收尾的一类操作。

Python 文件操作的模式与常用方法

图里 r、w、a、b、+ 这几个模式要分清。w 是写入并清空原有内容,a 是追加,用错一个字母就是把文件清空了。带 b 的是二进制模式,读图片、压缩包必须用它。

# 使用with操作文件
with open(os.path.dirname(__file__) + '/blog.text','w') as f:
    f.write(json.dumps(data))
@前端进阶之旅: 代码已经复制到剪贴板

这段用的是 with 语句。它的价值在于不管代码块里发生什么,哪怕中间抛异常,退出时都会自动帮你关闭文件句柄。手写 f = open(...) 加 f.close() 也能跑,但只要中间抛了异常,close 就执行不到,句柄一直被占着。所以文件操作一律用 with,这条没有例外。

顺带补一个坑,open() 在不同系统上的默认编码不一样,读中文文本时最好显式写 encoding='utf-8',不然在 Windows 上很容易撞上 UnicodeDecodeError。

除了纯文本,日常还会碰到路径、图片、Excel 这几类操作,标准库和常用第三方库的分工是这样的。

Python 路径操作模块 os.path 与 pathlib Python 图片处理相关库 Python 操作 Excel 的常用库 文本与其他格式文件的处理方式

路径这块推荐直接上 pathlib。它把路径当对象处理,拼接用 / 运算符,Path('a') / 'b' / 'c.txt' 比 os.path.join 直观,而且天然跨平台,不用操心 Windows 的反斜杠。老代码里 os.path 更常见,新写的建议换。

# 三、基本类型

先看全景。

Python 基本数据类型分类

类型判断的两个方式

  • type 判断基本类型,如 type(10) == int,不推荐
  • isinstance(值, 类型),也可以传一个元组一次判断多种,如 isinstance(值, (int, float, str))
    • 例:isinstance(1, int)

为什么不推荐 type?因为它做的是精确相等比较,不认继承关系。一个继承自 int 的子类实例,type(x) == int 是 False,而 isinstance(x, int) 是 True。面向对象里子类应该能当父类用,isinstance 才符合这个预期。

下面是各个类型的细节:

  • Number
    • int
    • float
    • complex 复数,如 36j
  • Bool
    • bool('') / bool([]) / bool({}) / bool(0) / bool(None)
    • 都会转化为 False
  • 字符串 str(序列)
    • 单引号
    • 双引号
    • 三引号(可以换行写多行字符串,和 ES6 的反引号类似)
    • 在字符串前面加一个 r,它就不是普通字符串而是原始字符串,会原样输出,print(r'\n88fafa') 里的 \n 不会被转义
  • list 列表(序列)
  • tuple 元组(序列)
  • 集合 set(无序,没有索引,不能切片,元素唯一不能重复,只有 value 没有 key),写法如 {1,2,3,4}
    • 1 in {1,2,3}
    • 1 not in {1,2,3,4}
    • 两个集合求差集 {1,2,3} - {4,5}
    • 两个集合求交集 {1,2,3,4} & {2,3}
    • 并集 {1,2,3,4,5,6} | {3,4,7}
    • 定义一个空的集合用 set()
  • 字典 dict(key-value 成对出现,这是它和只有 value 的集合最大的差别)
    • 由很多 key-value 组成,不能有相同的键
    • key 必须是不可变类型,可以是 int / str / tuple
    • value 可以是 int / str / float / list / set / dict
    • 定义一个空的字典用 {}

原文这里把字典写成了「有 key 无 value」,是笔误,字典当然是键值成对的,我按实际行为改过来了。倒是空集合那条要记牢,{} 得到的是空字典不是空集合,想要空集合只能写 set()。

那为什么字典的 key 必须用不可变类型呢?因为字典靠 key 的哈希值决定数据存在哪个槽位。如果 key 存进去之后还能被修改,哈希值就变了,之前存的那条数据再也定位不到。列表可变,所以不能当 key;元组不可变,可以。

fe
  • 一、导语
  • 二、基本知识
    • 注释
    • 命名
    • 保留字
    • input() 函数
    • eval() 函数
    • print() 函数
    • 函数
    • 文件操作
  • 三、基本类型
  • 四、序列,元组、字符串、列表
  • 五、运算符
  • 六、循环、条件、枚举
  • 七、枚举
  • 八、闭包、模块、函数、变量作用域
    • 模块
    • 闭包
    • 匿名函数 lambda
    • map函数
    • reduce函数
    • filter函数
  • 九、装饰器
  • 十、面向对象
  • 十一、正则表达式
  • 十二、内建函数
  • 十三、标准库
  • 十四、异常处理
  • 十五、JSON操作
  • 十六、爬虫
  • 十七、常用库
    • datetime库
    • random库
  • 十八、技巧
  • 十九、Python知识体系
  • 二十、更多参考
  • 总结
  • 参考

← Python基础小结(二) 用思维导图梳理语法到并发ES6 系统复习 ES2015 ES2016 ES2017 ES2018 ES2019 特性全梳理 →