Python 全栈 60 天精通之路

传统的 Python 教程

我见过很多的 Python 讲解教程和书籍,它们大都这样讲 Python:

先从 Python 的发展历史开始,介绍 Python 的基本语法规则,Python 的 list, dict, tuple 等数据结构,然后再介绍字符串处理和正则表达式,介绍文件等 IO 操作,再介绍异常处理, 就这样一章一章的。

很多都是枯燥的讲理论,越看越累,越累越不想看。

那么,有没有比这更好的方法呢?

这个 Python 专栏亮点

因为我也有过那段“自学” Python 的迷茫时期,所以我深知一个好的系统学习规划和老师讲解,是能够达到事半功倍省下我们程序员更多青春的关键。

所以我提炼出过往五年多的工作经验,并和远在美国学府进修 AI 专业博士后的老师一起撰写出了这个 60 天的专栏。

别的老师在介绍知识点时都会说“这东西是什么”,但我不想这样做。我觉得“为什么这东西是这样”或者“在什么场景适应什么需求有什么好处才会用这东西”,反而更能让你们对知识本身会有更深刻的理解。

本着有趣有味,纯碎干货,实用至上的原则,专栏五大特色:

第一,案例教学。 纯碎的理论知识学起来很枯燥,但是结合一个一个的小案例,以此切入,学起来更爽。

第二,尽量做到有趣。 图文并茂,加上有趣的例子、有趣的小项目,学起来更有乐趣。

第三,自成体系。 就像侦探片那样,一步一步,一环扣一环地铺开 Python 技术栈。

第四,剖析一些 Python 常见的面试题。 将理论知识讲解,结合案例,同时配备相关面试题,彻底打通理论知识。

第五,项目实战。 不仅会有实战环境部署方案,还有实际的项目:Python GUI 开发项目,Kaggle 数据分析项目,机器学习实战项目。

专栏目录

为了让你们在自学时能依据自身的学习基础量体裁衣,我将整个 Python 内容按天划分,不仅能减轻你们每天的学习负担,而且还能有更效的检验学习效果。

一 Python 基础篇

Day 1:Python 两大特性和四大基本语法

Day 2:Python 四大数据类型总结

Day 3:list 和 tuple 的基本操作、深浅拷贝和切片操作详细等 5 个方面总结(附图形形象解释)

Day 4:list 和 tuplel 的 13 个经典使用案例

Day 5:dict 和 set 基本操作、字典视图等 6 个方面详解总结附图形阐述

Day 6:dict 和 set 的 15 个经典使用例子

Day 7:数学运算、逻辑运算和进制转化相关的 16 个内置函数

Day 8:16 个类型函数和 10 个类对象相关的内置函数大盘点

Day 9:Python 字符串和正则介绍总结

Day 10:Python 文件操作 11 个案例总结

Day 11:Python 时间模块使用逻辑大盘点

二 Python 实战环境搭建

Day 12:Python 四种常用开发环境总结

Day 13:Python 安装包常见问题及解决方法,通过两个实际案例展开

Day 14:五分钟入门 7 个 Web、爬虫、打包工具 Pyinstaller 等包介绍和入门案例总结

Day 15:五分钟入门 8 个数据分析、机器学习和深度学习包和框架和入门案例总结

Day 16:Pyinstaller 打包过程详解

三 Python 进阶篇

Day 17:Python 列表生成式高效使用的 12 个案例

Day 18:Python 对象间的相等性比较 is,in,id,== 等使用总结

Day 19:yield 关键字和生成器用法四个方面总结及三个例子,nonlocal 关键字和 global 关键字使用总结

Day 20:高阶函数、迭代器、装饰器等 20 个内置函数大盘点

Day 21:Python 应用正则的三个案例和推荐一个正则验证工具

Day 22:Python 多线程使用逻辑通俗易懂的总结

Day 23:Python 高效节省内存的方法总结(进一步提升 yield 用法)

Day 24:Python 最被低估的库 collections 使用总结

Day 25:Python 函数的五类参数,inspect 模块查看参数类型及参数赋值规则总结

Day 26:Python 函数式编程总结,包括闭包,nonlocal 关键字等的使用总结

Day 27:Python 装饰器的本质解密,结合三个装饰器的案例

Day 28:Python 常见的 12 个坑点合集

四 Python 数据分析篇

Day 29:NumP 入门高效使用逻辑,掌握这五方面功能

Day 30:NumPy 进阶高效使用逻辑,掌握这五方面功能

Day 31:NumPy 的广播机制规则解读和应用

Day 32:Pandas 读写文件五类问题及 38 个参数总结

Day 33:Pandas 更强的方括号操作,iterrows, itertuples 和 merge 处理速度比较分析,特有的 setindex,resetindex,reindex 操作

Day 34:Pandas 数据透视功能 4 大函数使用总结

Day 35:Pandas 数据分箱的两种方法,转换为哑变量(dummy)的两种方法,连接两张表的四种不同方法总结

Day 36:开发常见异常汇总:Unhashable Type, 读取文件最常见的4个异常,SettingWithCopyWarning

五 数据分析实战篇

Day 37:绘图神奇 Pyecharts 快速手上的方法详细总结,从 Charts 和 Options 两大模块入手

Day 38:Matplotlib 绘图原理总结,绘制多图的三种方法总结,12 种常用图完整代码解析以及制作动画方法总结

Day 39:基于 Kaggle 电影影评数据集 Pandas 数据分析实战-数据预处理阶段

Day 40:基于 Kaggle 电影影评数据集 Pandas 数据分析实战-挖掘出喜剧 Top50 榜单

Day 41:PyQt 制作 GUI 实战:通过制作小而美的计算器学会使用 PyQt

六 基础算法篇

Day 42:关于入门算法、机器学习和深度学习我的一些思考总结

Day 43:八个排序算法原理总结和 Python 完整代码实现

Day 44:动态规划算法和案例总结

Day 45:面试常考 Leetcode 算法题分析和总结

七 机器学习算法篇

Day 46:必备统计学知识:概率,期望,方差,标准差,协方差,相关系数,t 检验,F 检验,卡方检验

Day 47:机器学习必备的数学基础知识:最常用的求导公式,矩阵特征值分解等

Day 48:机器学习不得不知的概念:样本空间,特征向量,维数,泛化能力,归纳偏好等

Day 49:机器学习之 9 种常见的概率分布

Day 50:OLS 线性回归实战上篇:机器学习回归原理详细介绍,包括假设和原理,梯度下降求权重

Day 51:OLS 线性回归实战下篇:手写不调包实现线性回归算法实战

Day 52:贝叶斯分类案例解析和编写

Day 53:贝叶斯算法实战:实现单词拼写纠正器

Day 54:高斯混合模型聚类原理分析和求解总结

Day 55:聚类模型实战:不调包实现多维数据聚类案例

Day 56:机器学习常用聚类算法大盘点包括原理和使用注意事项

Day 57:机器学习降维算法之 PCA 原理推导和例子解析

Day 58:Kaggle 机器学习分类任务案例实战

八 经验分享

Day 59: 美国名校博士、AI 专家 Alicia 关于如何学习数学、机器学习、数据分析的总结

Day 60:专栏总结和我过往 5 年算法经验分享

专栏亮点

  1. 70 多个案例教学全面解析
  2. 环环相扣助你形成知识体系
  3. 最新 Python 面试题配套讲解
  4. 项目实战带你彻底打通全栈
  5. 两位大厂和美国 AI 博士带你全方位清扫升级障碍

适合人群

  1. Python 语言爱好者
  2. Python 语言进阶
  3. Python 数据分析爱好者
  4. 广大程序员想入门算法者
  5. 机器学习算法入门
  6. 机器学习算法进阶
  7. Python 和人工智能爱好者

作者简介

avatar

zglg,5 年算法开发工作经验,知名互联网公司高级算法工程师,创建的 Python 案例 GitHub 库一个月 star 量从 0 到 1700+,被 AI 权威媒体量子位报道;

avatarAlicia,美国名校数学专业博士毕业,惠普高级数据分析师,现就读于美国顶尖学府 AI 专业博士后,具有丰富的工作和科研经历。

购买须知

  • 本专栏为图文内容,共计 60 篇。
  • 付费用户可享受文章永久阅读权限。
  • 本专栏为虚拟产品,一经付费概不退款,敬请谅解。
  • 本专栏可在 GitChat 服务号、App 及网页端 gitbook.cn 上购买,一端购买,多端阅读。

订阅福利

  • 订购本专栏可获得专属海报(在 GitChat 服务号领取),分享专属海报每成功邀请一位好友购买,即可获得 25% 的返现奖励,多邀多得,上不封顶,立即提现。
  • 提现流程:在 GitChat 服务号中点击「我-我的邀请-提现」。
  • 购买本专栏后,服务号会自动弹出入群二维码和暗号。如果你没有收到那就先关注微信服务号「GitChat」,或者加我们的小助手「GitChatty6」咨询。(入群方式可查看第 4 篇文末说明)。

课程内容

Day 1:Python 两大特性和四大基本语法

Python 语言使用率越来越高,使用 Python 不仅可以做 GUI 开发,Web 开发,还能进行数据处理,数据探索性分析(EDA),更是进行数据挖掘,机器学习和深度学习等的首选语言。

基于 Python 的包更是枝繁叶茂,遍地开花,tiobe 编程语言排行榜最新统计显示 Python 是增长最快的语言。

image-20200131192231967

这得益于 Python 语言语法简单,开发效率高,集成系统非常方便。

Python 相关的就业机会也是非常多,并且待遇优厚。

因此,不管从易用性,还是工作机会和待遇来说,Python 都是 IT 从业者需要掌握的语言,接下来我们开始 Python 之旅。

Python 语言两大特性

Python 是一门动态的、强类型语言。

什么是动态语言?

要了解什么是动态语言,要首先了解类型检查。类型检查是验证类型约束的过程,编译器或解释器通常在编译阶段或运行阶段做类型检查。

类型检查就是查看变量和它们的类型,然后判断表达式是否合理。例如,不能拿一个string 类型变量除以浮点数变量。

类型检查发生在程序运行阶段(run time)的是动态类型语言(dynamically typed languages). 常见的动态语言包括:Python, Javascrpit, PHP

类型检查发生在编译阶段(compile time)的是静态类型语言(statically typed languages). 常见的静态类型语言包括:C, C++, Java, C#, Scala

什么是强类型语言?

强类型语言是指:不管是在编译阶段还是运行阶段,一旦某种类型绑定到变量后,此变量便会持有此类型,并且不能同其他类型在计算表达式时混合使用。

例如,在交互式工具IPython中输入如下两行代码:

In [1]: a = 5In [2]: a = a + 's'

程序会抛出TypeError异常:unsupported operand type(s) for +: 'int' and 'str', 不支持 int变量和 str变量相加。

常见的强类型语言有:Python, Java, C#, Scala.

与之对应的是弱类型语言,弱类型语言容易与其他类型混合计算。弱类型语言代表 Javascript支持如下操作:

var data = 5data = data + 'xiaoming' //string和int结合自动转化为string

常见的弱类型语言有:C, C++, PHP, Javascript.

按照是否为静态/动态语言,弱类型/强类型两个维度总结常用的语言分类。

img

四大基本语法

主要从变量命名基本规则,等方面总结 Python 的基本语法规则

命名规则

Python 的变量命名规则主要包括两条:

  • 允许包括英文、数字以及下划线(_),不能以数字开头
  • 名称区分大小写

特别说明以下划线开头的变量是有特殊意义的:

  • 类变量若以单下划线(_)开头,代表不能直接被访问,类似于C#的受保护型变量(protected),表示不能通过import module_name而导入。
  • 类变量若以双下划(__)开头,表示为类的私有成员,不能被导入和其他类变量访问。
  • 以双下划开头和双下划线结尾的变量是 Python 里的专用标识,有特殊的身份。如 Python 自定义类中都包括__init____add__方法,如果不重写__add__去执行两个类加法操作,程序会抛TypeError异常。只有重写后,才能正常执行加法操作。

Python 变量命名习惯一般遵守蛇形命名法(snake case):

  • 一般变量命名,book_idbook_store_count
  • 类名首字符为大写,如Python内置模块collections.abc中的Iterable类,我们自定义的Book类等;
  • 类方法名:get_store_count();
  • 其他特殊变量,全部大写M_PI,MAX_VEHICLE_SPEED

这与Java命名方法不同,Java最典型的命名方法是驼峰命名法(camel case).

缩进原则

python 最具特色的地方就是用缩进代替Java, C++中的{},缩进的层级结构表示代码的逻辑层次。

比如,自定义一个Book类,重写__add__方法计算两类书的库存量和。Python 的缩进方法,一般为4个字符。

代码行class Book(object) 与代码行# 定义类的参数的缩进,此处为 4 个字符;代码行def __add__(self,book):return所在行缩进也是 4 个字符;通过这种层级结构展现出代码的逻辑层次。

class Book(object):    # 定义类的参数    def __init__(self,book_id, book_name, book_store_count):        self.book_id = book_id        self.book_name = book_name        self.book_store_count = book_store_count    # 重写加法操作        def __add__(self,book):        return self.book_store_count + book.book_store_countstore_count = Book(1,'python入门书',100) + Book(2,'机器学习入门书',200)print(store_count) # 300

缩进格式,行间空行数,变量和等号空格等 Python编码规范参考PEP8. autopep8包遵循PEP8的所有规范,安装此包后可自动实现遵循编码规范,推荐使用。

特殊关键字

Python 有 35 个关键字:

False      await      else       import     passNone       break      except     in         raiseTrue       class      finally    is         returnand        continue   for        lambda     tryas         def        from       nonlocal   whileassert     del        global     not        withasync      elif       if         or         yield

自定义变量名不能与它们重复。

常用且不同于其他常用语言 c++和 Java 的关键字,如:

  • TrueFalse 用于表示值的真假,在Javatrueflase;
  • 逻辑反操作 Python 使用not而 Java 是!
  • None表示空值,如数据库的字段取值为空,Javanull
  • Python 两个条件同时满足使用 and而 Java 是&&
  • 两者满足其一,Python 使用orJava使用||
  • Python 使用elif而 Java 是else if;

其他比较特殊的关键字,如:

  • del用于删除可迭代对象中某个元素;
  • def用于定义函数;
  • yield用于定义生成器(generator)函数;
  • globalnonlocal一种应用是 Python 函数式编程的闭包场景;
  • pass一种应用是 Python 中接口定义,也是 Python 语言特有的一个关键字。

这些关键字的用法会在后续文章中更为详细的介绍,在此先只要对它们形成一个整体上的认识就行。

特殊运算符

Python 的运算符包括:

+       -       *       **      /       //      %      @<<      >>      &       |       ^       ~       :=<       >       <=      >=      ==      !=

大部分运算符应该被熟知,重点介绍 3 个比较特殊的://, **, :=

  • //用于两个数值相除且向下取整,与 Python 的math模块中floor功能一致:
In [1]: 5//2Out[1]: 2In [2]: 5//4.5Out[2]: 1.0
  • **用于幂运算:
In [1]: 2**3Out[1]: 8
  • :=是 2019 年 Python3.8 版本里刚刚才支持的运算符,形象的称为海象运算符.
n = len(a)if n > 10:    print(f"{n}大于10")

如果使用海象运算符,写法上更为精简:

if (n := len(a)) > 10:    print(f"{n}大于10")
  • Python 比较运算符还支持链式比较,应用起来非常方便,比如:
i = 3print(1< i < 3) # Falseprint(1 < i <= 3) # True
  • 另外,运算符 @ 用于装饰器功能,下面会介绍一种使用场景。

小结

Python 学习第一天,首先认识 Python 两大特征,动态语言、强类型,动态指代码运行时才被编译器一行一行翻译执行,强类型指被绑定一个类型后便不能修改,不能与其他类型混用。

四大基本语法,总结了 Python 的命名规则,缩进原则,特殊关键字,特殊运算符,为后面的学习打下基础。

Day 2:Python 四大数据类型总结

基本数据类型

数值型

Python 中的数据皆是对象,比如被熟知的int整型对象,float双精度浮点型,bool逻辑对象,它们都是单个元素。举两个例子:

  • 前缀加0x,创建一个十六进制的整数:
0xa5 # 等于十进制的 165
  • 使用e创建科学计数法表示的浮点数:
1.05e3 # 1050.0

容器型

可容纳多个元素的容器对象,常用的比如:list列表对象, tuple元组对象, dict字典对象, set集合对象。 Python 定义这些类型的变量,语法非常简洁。

举例如下:

  • 使用一对中括号[],创建一个list型变量:
lst = [1,3,5] # list变量
  • 使用一对括号(),创建一个tuple型对象:
tup = (1,3,5) # tuple变量
  • 使用一对花括号{}另使用冒号:,创建一个dict对象:
dic = {'a':1, 'b':3, 'c':5} # dict变量
  • 仅使用一对花括号{},创建一个set对象:
s = {1,3,5} # 集合变量

Python 的容器类型,list, dict, tuple, set 等能方便地实现强大的功能,下面列举几个:

1) 去最求平均

def score_mean(lst):    lst.sort()    lst2=lst[1:(len(lst)-1)]    return round((sum(lst2)/len(lst2)),1)lst=[9.1, 9.0,8.1, 9.7, 19,8.2, 8.6,9.8]score_mean(lst) # 9.1

2) 打印 99 乘法表

打印出如下格式的乘法表

1*1=11*2=2   2*2=41*3=3   2*3=6   3*3=91*4=4   2*4=8   3*4=12  4*4=161*5=5   2*5=10  3*5=15  4*5=20  5*5=251*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=361*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=491*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=641*9=9   2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81

一共有 10 行,第i行的第j列等于:j*i

其中,

i取值范围:1<=i<=9

j取值范围:1<=j<=i

根据例子分析的语言描述,转化为如下代码:

for i in range(1,10):    ...:     for j in range(1,i+1):    ...:         print('%d*%d=%d'%(j,i,j*i),end="\t")    ...:     print()

3) 样本抽样

使用sample抽样,如下例子从 100 个样本中随机抽样 10 个。

from random import randint,samplelst = [randint(0,50) for _ in range(100)]print(lst[:5])# [38, 19, 11, 3, 6]lst_sample = sample(lst,10)print(lst_sample) # [33, 40, 35, 49, 24, 15, 48, 29, 37, 24]

字符串

注意 Python 中没有像C++表示的字符类型(char),所有的字符或串都被统一为str对象。如单个字符c的类型也为str.

str类型会被经常使用,先列举 5 个被高频使用的方法:

  • strip用于去除字符串前后的空格:
In [1]: '  I love python\t\n  '.strip()Out[1]: 'I love python'
  • replace用于字符串的替换:
In [2]: 'i love python'.replace(' ','_')Out[2]: 'i_love_python'
  • join用于合并字符串:
In [3]: '_'.join(['book', 'store','count'])Out[3]: 'book_store_count'
  • title用于单词的首字符大写:
In [4]: 'i love python'.title()Out[4]: 'I Love Python'
  • find用于返回匹配字符串的起始位置索引:
In [5]: 'i love python'.find('python')Out[5]: 7

举个应用字符串的案例,判断 str1 是否由 str2 旋转而来。

字符串stringbook旋转后得到bookstring,写一段代码验证str1是否为str2旋转得到。

转化为判断:str1是否为str2+str2的子串

def is_rotation(s1: str, s2: str) -> bool:    if s1 is None or s2 is None:        return False    if len(s1) != len(s2):        return False    def is_substring(s1: str, s2: str) -> bool:        return s1 in s2    return is_substring(s1, s2 + s2)

测试

r = is_rotation('stringbook', 'bookstring')print(r)  # Truer = is_rotation('greatman', 'maneatgr')print(r)  # False

字符串的匹配操作除了使用str封装的方法外,Python 的re正则模块匹配字符串,功能更加强大且写法极为简便,广泛适用于网络爬虫和数据分析领域。

下面这个例子实现的是:密码安全检查,使用正则表达式非常容易实现。

密码安全要求:1)要求密码为 6 到 20 位; 2)密码只包含英文字母和数字

pat = re.compile(r'\w{6,20}') # 这是错误的,因为\w通配符匹配的是字母,数字和下划线,题目要求不能含有下划线# 使用最稳的方法:\da-zA-Z满足`密码只包含英文字母和数字`pat = re.compile(r'[\da-zA-Z]{6,20}')

选用最保险的fullmatch方法,查看是否整个字符串都匹配:

pat.fullmatch('qaz12') # 返回 None, 长度小于6pat.fullmatch('qaz12wsxedcrfvtgb67890942234343434') # None 长度大于22pat.fullmatch('qaz_231') # None 含有下划线pat.fullmatch('n0passw0Rd')Out[4]: <re.Match object; span=(0, 10), match='n0passw0Rd'>

自定义类型

Python 使用关键字 class定制自己的类,_self__表示类实例对象本身。一个自定义类内包括属性、方法,还有建立类是系统自带的方法。

类(对象)

class dog(object)

以上定义了一个dog对象,它继承于根类object.

类的属性

def __init__(self, name, dtype):     self.name = name     self.dtype = dtype

以上定义了 dog 对象的两个属性:name, dtype,通过init,这个系统函数是每个对象自带的。

类的方法

def shout(self):    print('I'm %s, type: %s' % (self.name, self.dtype))

注意,对象的方法参数必须要有 self,引用属性时,必须前面添加 self.name 等。

类的实例

xiaohuaDog = dog('xiaohua','quanType')

xiaohuaDog是 dog 对象的实例.

下面的 shout() 方法,是一个 public 方法,能在外部被其他模块调用。

def shout(self):    pass

如果在 shout 前面添加2个_后,此方法变为私有方法,只能在内部使用。

属性前加 2 个_后,属性变为私有属性。通过此机制改变属性的可读性或可写性。

def get_type(self):    return __type

通过get_type函数,就相当于 type 修改为可读、不可写的。

再看一个例子。

自定义一个最精简的Book类,它继承于系统的根类object

class Book(object):    pass

使用 Python 自带的装饰器@property创建一个属性book_store_count:

    @property    def book_store_count(self):        return self._book_store_count    @book_store_count.setter    def book_store_count(self, val):        self._book_store_count = val

使用属性book_store_count

python_intro = Book()python_intro.book_store_count = 100print('store_count of python_intro is {0}'.format(    python_intro.book_store_count))  # store_count of python_intro is 100

关于创建类内属性的原理此处不展开,会在后面章节中通俗易懂的详细论述。

小结

今天学习了 Python 的四大基本数据类型,数值型,int, float 等;容器性,list, dict, tuple, set 等;字符型,str 与正则介绍;自定义类的基本语法规则,class, 属性和方法等。

Day 3:list 和 tuple 的基本操作、深浅拷贝和切片操作详细等 5 个方面总结

列表

列表(list)作为 Python 中最常用的数据类型之一,是一个可增加、删除元素的可变容器。

基本操作

创建 list 的方法极其简单,使用一对中括号[],如下创建三个 list:

empty = []lst = [1,'xiaoming',29.5,'17312662388']lst2 = ['001','2019-11-11',['三文鱼','电烤箱']]

empty在内存中的示意图:

1574822445967

lst在内存中的示意图:

1574821820948

lst2在内存中的示意图:

1574821753563

使用 python 的内置函数len求 list 内元素个数:

len(empty) # 0len(lst) # 4len(lst2) # 3

依次遍历lst内每个元素并求对应类型,使用for in对遍历,内置函数type得到类型:

for _ in lst:    print(f'{_}的类型为{type(_)}')

打印结果如下,列表 lst 内元素类型有 3 种,因此 Python 的列表不要求元素类型一致。

1的类型为<class 'int'>xiaoming的类型为<class 'str'>29.5的类型为<class 'float'>17312662388的类型为<class 'str'>

如何向 lst2 的第三个元素['三文鱼','电烤箱']内再增加一个元素'烤鸭', 首先使用整数索引取出这个元素:

sku = lst2[2] # sku又是一个列表

sku 变量位于栈帧中,同时指向 lst2[2]:

1574822492043

然后使用列表的append方法增加元素,append默认增加到 sku 列表尾部:

sku.append('烤鸭')print(sku) # ['三文鱼', '电烤箱', '烤鸭']

1574822603342

此时想在 sku 指定索引 1 处插入牛腱子,使用列表的insert方法:

sku.insert(1,'牛腱子')print(sku) # ['三文鱼', '牛腱子', '电烤箱', '烤鸭']

1574822644827

在购买烤鸭和牛腱子后,发现超出双十一的预算,不得不放弃购买烤鸭,使用 pop 方法可直接移除列表尾部元素:

item = sku.pop() # 返回烤鸭print(sku) # ['三文鱼', '牛腱子', '电烤箱']

1574822687219

发现还是超出预算,干脆移除三文鱼,pop 因为只能移除表尾元素,幸好列表有remove方法:

sku.remove('三文鱼') # 更好用:sku.remove(sku[0])print(sku) # ['牛腱子', '电烤箱']

1574822769243

深拷贝

打印 lst2,发现第三个元素也对应改变,因为 sku 引用 lst2 的第三个元素,sku 指向的内存区域改变,所以 lst2 也会相应改变。

print(lst2) # ['001', '2019-11-11', ['牛腱子', '电烤箱']]

这种引用就是浅复制(shallow copy).

如果不想改变 lst2 的第三个元素,就需要深复制出 lst2 的这个元素,列表上有 copy 方法可实现深复制:

lst2 = ['001','2019-11-11',['三文鱼','电烤箱']] # 这是lst2的初始值

可视化此行代码,lst2 位于全局帧栈中,其中三个元素内存中的可视化图如下所示:

1574820784839

sku_deep = lst2[2].copy() # 这是深复制(deep copy)

此时可视化图为如下,因为深拷贝 lst2[2],所以 sku_deep 位于栈帧中指向一块新的内存空间:

1574820818329

此时,再对 skudeep 操作,便不会影响 lst2[2] 的值,如下修改 skudeep 的第一个元素(Python 的列表索引从 0 开始编号), lst2 未受到任何影响。

sku_deep[0] = '腱子'print(lst2[2]) # ['三文鱼','电烤箱']

修改 lsku_deep 时,自然不会影响 lst2[2],因为它们位于不同的内存空间中,如图所示 lst2[2] 中的第一个元素依然是三文鱼,而不是腱子.

1574820760556

切片

Java 和 C++ 中,访问数组中的元素只能一次一个,但 Python 增加切片功能为访问列表带来极大便利。利用内置函数 range(start,stop,step) 生成序列数据,并转为 list 类型:

a = list(range(1,20,3))print(a) # [1, 4, 7, 10, 13, 16, 19]

使用a[:3]获取列表 a 的前三个元素,形象称这类操作为切片,切片本身也是一个列表:[1,4,7];使用a[-1]获取a的最后一个元素,返回int型,值为19;使用a[:-1]获取除最后一个元素的切片:[1, 4, 7, 10, 13, 16]使用a[1:5]生成索引为 [1,5) (不包括索引5)的切片:[4, 7, 10, 13];使用a[1:5:2]生成索引 [1,5) 但步长为2的切片:[4,10];使用a[::3]生成索引 [0,len(a)) 步长为3的切片:[1,10,19];使用a[::-3]生成逆向索引 [len(a),0) 步长为3的切片:[19,10,1].

逆向:从列表最后一个元素访问到第一个元素的方向

特别地,使用列表的逆向切片操作,只需一行代码就能逆向列表:

def reverse(lst):    return lst[::-1]

调用reverse函数:

ra = reverse(a)print(ra) # [19, 16, 13, 10, 7, 4, 1]

说完列表,还有一个与之很相似的数据类型:元祖(tuple).

元祖

元祖既然是不可变对象,自然也就没有增加删除元素的方法。

基本操作

使用一对括号(())就能创建一个元祖对象,如:

a = () # 空元祖对象b = (1,'xiaoming',29.5,'17312662388')c = ('001','2019-11-11',['三文鱼','电烤箱'])

它们都是元祖,除了 list 是用[]创建外,其他都与 list 很相似,比如都支持切片操作。

特别注意:一个整数加一对括号,比如(10),返回的是整数。必须加一个逗号(10, )才会返回元祖对象

列表和元祖都有一个很好用的统计方法count,实现对某个元素的个数统计:

from numpy import randoma = random.randint(1,5,10) # 从[1,5)区间内随机选择10个数at = tuple(a) # 转tuple:(1, 4, 2, 1, 3, 3, 2, 3, 4, 2)at.count(3) # 统计 3 出现次数,恰好也为 3 次

可变与不可变

文章开头提到列表是一个可变容器,可变与不可变是一对很微妙的概念,因为网上经常出现,所以再重点总结下。

创建一个列表 a = [1,3,[5,7],9,11,13],存储示意图:

1574825725117

执行a.pop()后删除最后一个元素:

1574825793763

删除后:

1574825814256

再在索引 3 处增加一个元素 8,a.insert(3,8),插入后如下:

1574825848339

因此,对列表而言,因为它能增加或删除元素,所以它是可变的。

但是,如果仅仅在列表 a 中做这一步操作:

a[2].insert(1,6) #在`a[2]`(也是一个列表)中插入元素6

插入后可视化图:

1574826103718

对于“可变”这个概念而言,这就不是真正让 a 可变的操作。

tuple就是一个典型的不可变容器对象,对它而言,同样也可以修改嵌套对象的取值,但这并没有真正改变 tuple 内的元素。

如下所示,有一个元祖 a

a =(1,3,[5,7],9,11,13)

a 的存储示意图如下:

1574833081653

下面插入一个元素 6:

a[2].insert(1,6)

可以看到,a 内元素没增没减,长度还是 6

1574833217247

这就是不可变对象的本质,元祖一旦创建后,长度就被唯一确定。但是,对于 list 而言,列表长度会有增有减,所以它是可变的。

小结

今天总结了列表的基本操作,重要深浅拷贝问题,以及基本的切片操作;元祖(tuple)的基本操作;前者是可变对象,后者是不可变对象,意味着一旦创建,后面就不允许增加删除元素。

Day 4:list 和 tuplel 的 13 个经典使用案例
Day 5:dict 和 set 基本操作、字典视图等 6 个方面详解总结
Day 6:dict 和 set 的 15 个经典使用例子
Day 7:数学运算、逻辑运算和进制转化相关的 16 个内置函数
Day 8:16 个类型函数和 10 个类对象相关的内置函数大盘点
Day 9:Python 字符串和正则介绍总结
Day 10:Python 文件操作 11 个案例总结
Day 11:Python 时间模块使用逻辑大盘点
Day 12:Python 四种常用开发环境总结
Day 13:Python 包安装的两个实际案例(包括安装遇到的各种问题及解决方法)
Day 14:7 个Web、爬虫、打包工具 Pyinstaller 等包介绍和入门案例总结
Day 15:8 个数据分析、机器学习和深度学习包和框架和入门案例总结
Day 16:Pyinstaller 打包过程详解
Day 17:Python 列表生成式高效使用的 12 个案例
Day 18:Python 对象间的相等性比较等使用总结
Day 19:yield 关键字和生成器用法 4 个方面总结及 3 个例子,nonlocal 关键字和 global 关键字使用总结
Day 20:高阶函数、迭代器、装饰器等 20 个内置函数大盘点
Day 21:Python 应用正则的三个案例和推荐一个正则验证工具
Day 22:Python 多线程使用逻辑通俗易懂的总结
Day 23:Python 高效节省内存的方法总结
Day 24:Python 最被低估的库 collections 使用总结
Day 25:Python 函数的五类参数,inspect 模块查看参数类型及参数赋值规则总结
Day 26:Python 函数式编程总结,包括闭包,nonlocal 关键字等的使用总结
Day 27:Python 装饰器的本质解密,结合三个装饰器的案例
Day 28:Python 常见的 12 个坑点合集
Day 29:NumP 入门高效使用逻辑,掌握这五方面功能
Day 30:NumPy 进阶高效使用逻辑,掌握这五方面功能
Day 31:NumPy 的广播机制规则解读和应用
Day 32:Pandas 读写文件五类问题及 38 个参数总结
Day 33:Pandas 更强的方括号操作,iterrows、itertuples 和 merge 处理速度比较分析,特有的 set_index,reset_index,reindex 操作
Day 34:Pandas 数据透视功能 4 大函数使用总结
Day 35:Pandas 数据分箱的两种方法,转换为哑变量(dummy)的两种方法,连接两张表的四种不同方法总结
Day 36:开发常见异常汇总:Unhashable Type, 读取文件最常见的 4 个异常,SettingWithCopyWarning
Day 37:绘图神奇 Pyecharts 快速手上的方法详细总结,从 Charts 和 Options 两大模块入手
Day 38:Matplotlib 绘图原理总结,绘制多图的三种方法总结,12 种常用图完整代码解析以及制作动画方法总结
Day 39:基于 Kaggle 电影影评数据集 Pandas 数据分析实战-数据预处理阶段
Day 40:基于 Kaggle 电影影评数据集 Pandas 数据分析实战-挖掘出喜剧 Top50 榜单
Day 41:PyQt 制作 GUI 实战—通过制作小而美的计算器学会使用 PyQt
Day 42:关于入门算法、机器学习和深度学习我的一些思考总结
Day 43:八个排序算法原理总结和 Python 完整代码实现
Day 44:动态规划算法和案例总结
Day 45:面试常考 Leetcode 算法题分析和总结
Day 46:必备统计学知识:概率,期望,方差,标准差,协方差等
Day 47:机器学习必备的数学基础知识:最常用的求导公式,矩阵特征值分解等
Day 48:机器学习不得不知的概念:样本空间,特征向量,维数,泛化能力,归纳偏好等
Day 49:机器学习之 9 种常见的概率分布
Day 50:OLS 线性回归实战上篇:机器学习回归原理详细介绍,包括假设和原理,梯度下降求权重
Day 51:OLS 线性回归实战下篇:手写不调包实现线性回归算法实战
Day 52:贝叶斯分类案例解析和编写
Day 53:贝叶斯算法实战:实现单词拼写纠正器
Day 54:高斯混合模型聚类原理分析和求解总结
Day 55:聚类模型实战:不调包实现多维数据聚类案例
Day 56:机器学习常用聚类算法大盘点包括原理和使用注意事项
Day 57:机器学习降维算法之 PCA 原理推导和例子解析
Day 58:Kaggle 机器学习分类任务案例实战
Day 59:美国名校博士、AI 专家 Alicia 关于如何学习数学、机器学习、数据分析的总结
Day 60:专栏总结和我过往 5 年算法经验分享

阅读全文: http://gitbook.cn/gitchat/column/5e37978dec8d9033cf916b5d

  • 2
    点赞
  • 1
    评论
  • 13
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值