Python Basics: Syntax, Data Structures, and File Handling
和C语言学习的不同之处,这次的整体构建会更加的重视实践,一个比较优秀的基础和实践的练习才能够保证有比较充足的经验,此时看各种官方的文档就会更加的容易了
开篇
Python应用领域和职业发展分析
简单的说,Python是一个“优雅”、“明确”、“简单”的编程语言。
- 学习曲线低,非专业人士也能上手
- 开源系统,拥有强大的生态圈
- 解释型语言,完美的平台可移植性
- 动态类型语言,支持面向对象和函数式编程
- 代码规范程度高,可读性强
Python在以下领域都有用武之地。
- 后端开发 - Python / Java / Go / PHP
- DevOps - Python / Shell / Ruby
- 数据采集 - Python / C++ / Java
- 量化交易 - Python / C++ / R
- 数据科学 - Python / R / Julia / Matlab
- 机器学习 - Python / R / C++ / Julia
- 自动化测试 - Python / Shell
作为一名Python开发者,根据个人的喜好和职业规划,可以选择的就业领域也非常多。
- Python后端开发工程师(服务器、云平台、数据接口)
- Python运维工程师(自动化运维、SRE、DevOps)
- Python数据分析师(数据分析、商业智能、数字化运营)
- Python数据挖掘工程师(机器学习、深度学习、算法专家)
- Python爬虫工程师
- Python测试工程师(自动化测试、测试开发)
给初学者的几个建议:
- Make English as your working language. (让英语成为你的工作语言)
- Practice makes perfect. (熟能生巧)
- All experience comes from mistakes. (所有的经验都源于你犯过的错误)
- Don’t be one of the leeches. (不要当伸手党)
- Either outstanding or out. (要么出众,要么出局)
简单的描述和优缺点
- 简单明了,学习曲线低,比很多编程语言都容易上手。
- 开放源代码,拥有强大的社区和生态圈,尤其是在数据分析和机器学习领域
- 解释型语言,天生具有平台可移植性,代码可以工作于不同的操作系统 Cpython仍然占据主流 也就是解释器是C写的
- 对两种主流的编程范式(面向对象编程和函数式编程)都提供了支持。
- 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
变量和简单的数据类型
一些变量命名规则
- 变量名由字母、数字和下划线构成,数字不能开头
- 对大小写敏感
- 含空格禁止
- 避免使用保留函数和语法关键字
- 小写l和大写O容易被误读为数字 谨慎使用
- 大写全部字母表示常量 普通变量全部小写使用下划线连接
- 受保护的实例属性用单个下划线开头(后面会讲到)
- 私有的实例属性用两个下划线开头(后面会讲到)
1 | # type函数可以查看变量的类型 由于不要求提前声明变量,我们可以直接进行赋值,类型交给解释器选择 |
数
Python是一个相当自由的语言 没有各种数定义的约束让我们使用起来非常的轻松 无论是整数还是浮点都可以自由使用 Python会提供给你一个让你满意的答案
比较重要的和C的区别是 他拥有 ** 表示乘方 并且 / 表示普通的除法 %表示余数
字符串
简单的字符串介绍
使用单引号 双引号括起来的是字符串 这些不同的引号规则是为了你能在句子里面顺利的使用引号
1 | s1 = 'hello, world!' |
可以在字符串中使用\(反斜杠)来表示转义,也就是说\后面的字符不再是它原来的意义,在\后面还可以跟一个八进制或者十六进制数来表示字符
1 | s1 = '\141\142\143\x61\x62\x63' |
如果想要使用 ‘ \ ‘在字符串里,则需要给他也来一层转义有
1 | s1 = "\\dsadasdasd\\" |
字符串方法
方法是Python对数据执行的操作 他和函数不一样 具体的区别我们会在以后再说
对字符串的基础方法有
1 | .title() .upper() .lower() |
字符串中的变量
如想想要在字符串的输出中增加一些变量的内容,就需要这点
1 | first_name="ada" |
f 字符串是在python3.6以后引入的 他之前的格式是 是一个关于字符串的方法
1 | full_name="{} {}".format(first_name,last_name) |
这类似于我们前面研究的使用 %d 等占位符的字符串输出,如
1 | a, b = 5, 10 |
强制类型转换
Python中内置的函数对变量类型进行转换,用于处理类型不合适的情况,函数如下
int():将一个数值或字符串转换成整数,可以指定进制。float():将一个字符串转换成浮点数。str():将指定的对象转换成字符串形式,可以指定编码。chr():将整数转换成该编码对应的字符串(一个字符)。ord():将字符串(一个字符)转换成对应的编码(整数)。
注释
1 | import this |
列表
列表是一系列按照一定顺序排列的元素 和数组的不同之处是对元素的类型没有任何限制 但是正如集合论的开篇所讲 人们很少把一些毫无关系的量放在一起 所以列表的命名多采用名词复数;
事实上,字符串就是一种列表
1 | bicycles=['trek','redline','cannondale'] |
修改列表
1 | bicycles[0]=bus |
列表的组织
1 | bicycles.sort() |
数值列表
列表非常适合存储数字 正如数组一样 但是Python为我们提供了很多更简单的工具来实现他
1 | for value in range(1,5): |
使用列表的一部分
1 | players=list(range(1,11)) |
元组
元组和列表是非常相似的 实际上他和列表唯一的区别就是元组创建后不可以被修改 实际上元组就是为了避免列表被不小心修改而产生的
1 | players=(23,434) |
分支
基础的内容
在Python中,要构造分支结构可以使用if、elif和else关键字。所谓关键字就是有特殊含义的单词,像if和else就是专门用于构造分支结构的关键字,很显然不能够使用它作为变量名
1 | for car in cars: |
列表和PEP 8
1 | if cars: |
集合 字典
字典类似C语言的结构 他旨在把各种不同类型但是相关的数组组成一个便于访问的单元 而非列表一般存储平级数据;集合则和数学上的集合是一致的。
集合
Python中的集合跟数学上的集合是一致的,不允许有重复元素,而且可以进行交集、并集、差集等运算。 我们在研究一些比较单一的统计项 set是一个很好的选择
1 | # 创建集合的字面量语法 |
使用字典
1 | alien_0={'color':'green','points':5} |
1 | favorite_languages = { |
遍历字典
很明显对字典进行遍历是不能忽视的一个问题 但是只有键值对的字典该怎么遍历呢
1 | for key,value in favorite_languages.items(): |
嵌套
很明显的 字典和列表使我们目前为止学到的非常有用的数据类型 甚至可以说是一种好用的数据结构 他们之间的嵌套是自然的 也是复杂的
1 | alien_0={'color':'green','points':5} |
用户输入与循环
遍历列表
1 | bicycles=['trek','redline','cannondale'] |
冒号和缩进是Python循环的特征 缩进部分结束循环自然结束 也就是说Python的缩进更加接近自然语言 for in循环基于列表实现
1 | # 如果应该缩进的地方完全没有缩进 Python会提供报错提示 |
input函数
1 | message = input("Tell me some thing : ") |
while循环
for in 循环在 Python 中基于列表运行 当然他是有用的 但是有时候仅仅 for 循环并不够用 如果要构造不知道具体循环次数的循环结构,我们推荐使用while循环。while循环通过一个能够产生或转换出bool值的表达式来控制循环,表达式的值为True则继续循环;表达式的值为False则结束循环。
1 | currrent = 1 |
while循环与字典和列表
我们为什么会引出这一个分标题 for 循环对于列表的兼容性非常好 为什么要舍近求远
for 循环当然非常有效 但是我们不建议在for 循环的过程中修改元素 他应该只用于遍历 如果要在遍历的同时修改列表 字典 请使用while循环结构 便于Python追踪
1 | while list: |
函数
定义函数及其参数
函数是提升编写效率的重要存在 我们前面使用的 input sorted 都是函数 现在我们来讲讲编写属于自己的函数
1 | def greet_user(): |
有返回值和参数的函数
很明显的我们见过有返回值的函数 但是前面编写函数的时候没有说怎么又返回值 so now
1 | def greet_user(): |
任意数量参数
1 | def make_pizza(*toppings): |
用模块管理函数
关于模块化:由于Python没有函数重载的概念,那么后面的定义会覆盖之前的定义,也就意味着两个函数同名函数实际上只有一个是存在的;
那么怎么解决这种命名冲突呢?答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过import关键字导入指定的模块就可以区分到底要使用的是哪个模块中的函数
1 | import pizza |
对于模块化问题,我们需要引入一个重要的判断
1 | if __name__ == '__main__': |
关于变量作用域
没有定义在任何一个函数中 这是一个全局变量(global variable) 定义在某个函数中的变量 是一个局部作用域的变量 但是如果函数中嵌套了函数 一个局部变量被另一个作用域访问了 此时称为嵌套作用域 函数会根据局部作用域 嵌套作用域 全局作用域 内置作用域(语言保留的标识符)的顺序对变量进行寻找 以最优先找到的那个为准 现在应该能理解我们对变量作用域做的那些不精确描述和理解了
1 | global a |
正则表达式
在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要,正则表达式就是用于描述这些规则的工具,换句话说正则表达式是一种工具,它定义了字符串的匹配模式(如何检查一个字符串是否有跟某种模式匹配的部分或者从一个字符串中将与模式匹配的部分提取出来或者替换掉)。
正则表达式很好理解,就是一套用于匹配字符串的语言,Python对正则表达式也提供了支持。
正则表示式
| 符号 | 解释 | 示例 | 说明 |
|---|---|---|---|
| . | 匹配任意字符 | b.t | 可以匹配bat / but / b#t / b1t等 |
| \w | 匹配字母/数字/下划线 | b\wt | 可以匹配bat / b1t / b_t等 但不能匹配b#t |
| \s | 匹配空白字符(包括\r、\n、\t等) | love\syou | 可以匹配love you |
| \d | 匹配数字 | \d\d | 可以匹配01 / 23 / 99等 |
| \b | 匹配单词的边界 | \bThe\b | |
| ^ | 匹配字符串的开始 | ^The | 可以匹配The开头的字符串 |
| 可以匹配.exe结尾的字符串 | |||
| \W | 匹配非字母/数字/下划线 | b\Wt | 可以匹配b#t / b@t等 但不能匹配but / b1t / b_t等 |
| \S | 匹配非空白字符 | love\Syou | 可以匹配love#you等 但不能匹配love you |
| \D | 匹配非数字 | \d\D | 可以匹配9a / 3# / 0F等 |
| \B | 匹配非单词边界 | \Bio\B | |
| [] | 匹配来自字符集的任意单一字符 | [aeiou] | 可以匹配任一元音字母字符 |
| [^] | 匹配不在字符集中的任意单一字符 | [^aeiou] | 可以匹配任一非元音字母字符 |
| * | 匹配0次或多次 | \w* | |
| + | 匹配1次或多次 | \w+ | |
| ? | 匹配0次或1次 | \w? | |
| {N} | 匹配N次 | \w{3} | |
| {M,} | 匹配至少M次 | \w{3,} | |
| {M,N} | 匹配至少M次至多N次 | \w{3,6} | |
| | | 分支 | foo|bar | 可以匹配foo或者bar |
| (?#) | 注释 | ||
| (exp) | 匹配exp并捕获到自动命名的组中 | ||
| (?<name>exp) | 匹配exp并捕获到名为name的组中 | ||
| (?:exp) | 匹配exp但是不捕获匹配的文本 | ||
| (?=exp) | 匹配exp前面的位置 | \b\w+(?=ing) | 可以匹配I’m dancing中的danc |
| (?<=exp) | 匹配exp后面的位置 | (?<=\bdanc)\w+\b | 可以匹配I love dancing and reading中的第一个ing |
| (?!exp) | 匹配后面不是exp的位置 | ||
| (?<!exp) | 匹配前面不是exp的位置 | ||
| *? | 重复任意次,但尽可能少重复 | a.*b a.*?b |
将正则表达式应用于aabab,前者会匹配整个字符串aabab,后者会匹配aab和ab两个字符串 |
| +? | 重复1次或多次,但尽可能少重复 | ||
| ?? | 重复0次或1次,但尽可能少重复 | ||
| {M,N}? | 重复M到N次,但尽可能少重复 | ||
| {M,}? | 重复M次以上,但尽可能少重复 |
说明: 如果需要匹配的字符是正则表达式中的特殊字符,那么可以使用\进行转义处理,例如想匹配小数点可以写成\.就可以了,因为直接写.会匹配任意字符;同理,想匹配圆括号必须写成\(和\),否则圆括号被视为正则表达式中的分组。
Python中的正则表达式
Python提供了re模块来支持正则表达式相关操作,下面是re模块中的核心函数。
| 函数 | 说明 |
|---|---|
| compile(pattern, flags=0) | 编译正则表达式返回正则表达式对象 |
| match(pattern, string, flags=0) | 用正则表达式匹配字符串 成功返回匹配对象 否则返回None |
| search(pattern, string, flags=0) | 搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None |
| split(pattern, string, maxsplit=0, flags=0) | 用正则表达式指定的模式分隔符拆分字符串 返回列表 |
| sub(pattern, repl, string, count=0, flags=0) | 用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count指定替换的次数 |
| fullmatch(pattern, string, flags=0) | match函数的完全匹配(从字符串开头到结尾)版本 |
| findall(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回字符串的列表 |
| finditer(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回一个迭代器 |
| purge() | 清除隐式编译的正则表达式的缓存 |
| re.I / re.IGNORECASE | 忽略大小写匹配标记 |
| re.M / re.MULTILINE | 多行匹配标记 |
说明: 上面提到的re模块中的这些函数,实际开发中也可以用正则表达式对象的方法替代对这些函数的使用,如果一个正则表达式需要重复的使用,那么先通过compile函数编译正则表达式并创建出正则表达式对象无疑是更为明智的选择。
例子
1 | """ |
上面在书写正则表达式时使用了“原始字符串”的写法(在字符串前面加上了r),所谓“原始字符串”就是字符串中的每个字符都是它原始的意义,说得更直接一点就是字符串中没有所谓的转义字符
如果要从事爬虫类应用的开发,那么正则表达式一定是一个非常好的助手,因为它可以帮助我们迅速的从网页代码中发现某种我们指定的模式并提取出我们需要的信息,当然对于初学者,要编写一个正确的适当的正则表达式可能并不是一件容易的事情(当然有些常用的正则表达式可以直接在网上找找)
文件与异常
这一章和下一章都不会引入新的程序设计知识 他们只是为了提高程序的适用性 可用性 稳定性
从文件中读取数据
1 | #Python默认从当前运行的程序所在的位置寻找要打开的文件 |
写入文件
1 | with open('file_name.txt','w') as file_object: |
异常
代码不出现错误是不可能的 大多时候 代码遇到错误的时候会终止运行 但是用户用着用着突然崩溃了并不是什么好体验 所以Python提供了异常这一特殊的对象用来处理这些错误 当他遇到不知所措的错误时 会创建一个异常对象 如果我们编写了处理异常对象的代码 程序会继续运行 而不是反馈trackback
异常使用try-except代码块来处理 记得告诉用户我们出了什么错误 而不是一个正常人完全看不懂的trackback
1 | try: |
存储数据
任何的程序被关闭的时候总要存储一些数据到文件中 模块json是一个很好的模块 他原本是java开发的 但是很快变成了一种常见的格式 被很多开发者使用
1 | import json |
测试
测试代码的目的非常简单 你希望你提交的代码里面尽量不含有任何bug 或者说哪怕出现问题 你的代码也能向预期一样工作 这里我们只会介绍简单的测试方法
1 | #首先我们需要被测试的代码 |
Python标准库提供了模块unittest作为代码测试工具 单元测试衡量函数的某个方面没问题 测试用例是一组单元测试 全覆盖的测试是一整套测试 一般我们只会在项目广泛使用的时候进行全覆盖 正常只需要对程序的重要行为编写测试
1 | import unittest |
前面是对函数的测试 现在来考虑测试类能否顺利的工作(测试一般是因为你修改了原始代码 你需要保证你的修改不影响他应该有的功能)
1 | #下面是一些比较常用的unittest模块断言方法 |
测试类往往是在测试类中的方法 所以和测试函数有很多相近的地方 他们使用完全相同的开头 完全一样的定义测试类(实例)的方式 也是选择在方法中使用这个类或者函数的一部分功能 实际上测试用例里面就是对原始函数或者类的完全使用 最后使用断言来判断 实际上是完全一样的 代码如下
1 | class AnonymousSurvey(): |
Python的测试会在运行时给与一些反馈
每完成一个单元测试都会打印一些字符 通过时打印句点 测试引发错误打印E 断言失败时打印F
Python的基础内容到这里就结束了 我们需要完成一些项目来作为实践并且复习学到的知识 不过那就不必在这个文件里面继续进行了 编辑器才是真正应该待的地方
- Title: Python Basics: Syntax, Data Structures, and File Handling
- Author: Hyacehila
- Created at : 2023-03-18 13:32:22
- Link: https://hyacehila.github.io//blog/2023/03/18/python-basics-learning-notes/
- License: This work is licensed under CC BY-NC-SA 4.0.