├── 1-10 ├── 10、第三篇、小白看的 Python 基础教程,详细得很.md ├── 1、搭建Python环境和安装Pycharm.md ├── 2、搭建JupyterNotebook环境.md ├── 3、新手Jupyter不会用,我十招教你盘她.md ├── 4、学编程语言前,不了解Git,怎么入坑.md ├── 5、开始Github和码云之旅,新手如何上路.md ├── 6、乘胜追击,将剩下的Git知识点搞定.md ├── 7、连Pycharm都不知道怎么用,学什么Python.md ├── 8、第一篇、小白看的 Python 基础教程,详细得很.md └── 9、第二篇、小白看的 Python 基础教程,详细得很.md ├── 11-20 ├── 11、最后一篇,小白看的Python基础教程,详细得很.md ├── 12、深入Python列表和元组.md ├── 13、深入Python字典和集合.md ├── 14、深入Python条件和循坏.md ├── 15、深入Python输入和输出.md ├── 16、深入Python字符串.md ├── 17、深入Python异常处理.md ├── 18、深入Python函数.md ├── 19、深入Python匿名函数.md └── 20、深入Python迭代器和生成器.md ├── 21-30 ├── 21、深入Python强大的装饰器.md ├── 22、上篇 _ Python的进程和线程.md ├── 23、下篇 _ Python线程和进程.md ├── 24、深入Python多线程和多进程.md ├── 25、深入Python中的协程.md ├── 26、Python中的Time和os模块.md ├── 27、Python序列化pickle标准库.md ├── 28、Python中的日志处理logging模块.md ├── 29、Python标准库 collections.md └── 30、Python中的Json解析模块.md ├── 31-40 ├── 31、Python读写docx文件.md ├── 32、教你Python制作简单的二维码.md ├── 33、自从我会了Python中的PIL,发现了其实超级简单.md ├── 34、使用pytesser3 和pillow完成图形验证码的识别.md ├── 35、Python在window平台打包工具pyinstaller.md ├── 36、上篇 _ 教你玩转tkinter窗口.md ├── 37、下篇 _ tkinter实现一个翻译软件.md ├── 38、练习、Python判断一个信用卡号是否合理.md ├── 39、Python对象的深浅拷贝,练习冒泡排序.md └── 40、练习、Python的八皇后.md ├── 41-50 ├── 41、Python统计模块statistics.md ├── 42、MOOC课程 _ Python中的Scipy模块.md ├── 43、去年pandas的笔记.md ├── 44、Python中的statsmodels模块.md ├── 45、和我一起看看,国外的Python考试到底是怎么样(上篇).md ├── 46、和我一起看看,国外的Python考试到底是怎么样(下篇).md ├── 47、第二份国外的Python考试(上篇).md ├── 48、第二份国外的Python考试(下篇).md ├── 49、Mysql的命令总结和PyMysql.md └── 50、Redis数据库学习.md ├── 51-60 ├── 51、学会MongoDB数据库.md ├── 52、ViM的使用.md ├── 53、Linux基础命令,用户管理和文件系统总结(上篇).md ├── 54、Linux网络管理,软件安装,进程管理总结(中篇).md ├── 55、Linux磁盘管理和Shell编程(下篇).md ├── 56、教用Python中的turtle海龟画图(上篇).md ├── 57、教用Python中的turtle海龟画图(下篇).md ├── 58、Python中的正则表达式.md ├── 59、Python中的网络通信Socket.md └── 60、网络通信Socket模块实现文件传输.md ├── 61-70 ├── 61、Python中的smtplib和email实现邮件发送.md ├── 62、多线程真的比单线程快?那是因为你不知道Python中的全局解释器锁GIL.md ├── 63、面试最常见的问题:Python的垃圾回收机制到底是怎么样的?.md ├── 64、开始刷Leetcode之旅(Python版本).md ├── 65、Leetcode数组系列(上篇).md ├── 66、Leetcode数组系列(中篇).md ├── 67、Leetcode数组系列(下篇).md ├── 68、Python _ Leetcode链表系列(上篇).md ├── 69、Python _ Leetcode链表系列(中篇).md └── 70、Python _ Leetcode链表系列(下篇).md ├── 71-80 ├── 71、Python _ Leetcode字符串系列(上篇).md ├── 72、Python _ Leetcode字符串系列(下篇).md ├── 73、Python _ Leetcode数字系列(上篇).md ├── 74、Python _ Leetcode数字系列(下篇).md ├── 75、Python _ Leetcode哈希表系列.md ├── 76、Python _ Leetcode二分查找和分治算法系列.md ├── 77、Python _ Leetcode栈和队列系列.md ├── 78、Python _ Leetcode位运算系列.md ├── 79、Python _ Leetcode 二叉树系列(上篇).md └── 80、Python _ Leetcode 二叉树系列(中篇).md ├── 81-90 ├── 81、Python _ Leetcode 二叉树系列(下篇).md ├── 82、Python _ Leetcode贪心算法系列.md ├── 83、Python _ Leetcode双指针系列.md ├── 84、Python _ Leetcode回溯算法系列.md ├── 85、Python _ Leetcode数据结构之图和动态规划算法系列.md ├── 86、Python _ Leetcode深度和广度优先搜索算法系列.md ├── 87、Python _ 十大排序算法系列(上篇).md ├── 88、Python _ 十大排序算法系列(下篇).md ├── 89、Python的GUI系列 _ 使用PyQt5 快速构建一个GUI 应用.md └── 90、Python的GUI系列 _ QtDesigner进行界面设计.md ├── 91-99 ├── 91、Python的GUI系列 _ QT组件篇.md ├── 92、Python爬取深圳租房信息小案例.md ├── 93、Python使用百度云接口API实现截图,文字识别和语音合成.md ├── 94、一文带你玩转简单的flask.md ├── 95、轻松搞定Python中的Excel办公自动化系列.md ├── 96、轻松搞定Python中的PPT办公自动化系列.md ├── 97、轻松搞定Python中的PDF办公自动化系列.md ├── 98、轻松搞定Python中的Markdown系列.md └── 99、Python所学经验分享.md └── README.md /1-10/1、搭建Python环境和安装Pycharm.md: -------------------------------------------------------------------------------- 1 |  2 | @Author : By Runsen 3 | 4 | 5 | 6 | Python环境搭建(一) 7 | @[toc] 8 | 9 | # 1、 搭建Python的基础环境 10 | 11 | 12 | 安装python的基础环境。 13 | 14 | 首先,我们需要访问Python官网:https://www.python.org/。 15 | 16 | 17 | 18 | ![](https://img-blog.csdnimg.cn/20200510185558709.png) 19 | 20 | 21 | 目前Python更新到3.8.2版本,这里我不建议大家安装Python3.8.2版本,而是选择安装Python3.6或者3.7稳定版。 22 | 23 | 24 | ![](https://img-blog.csdnimg.cn/20200510185650725.png) 25 | 26 | 下载后,双击下载包exe,进入 Python 安装向导,安装非常简单,你只需要使用默认的设置一直点击"下一步"直到安装完成即可,但是要记住在安装的过程需要选择“ADD Python3.6 to PATH",这样是为了添加Python到环境变量。 27 | 28 | 29 | 30 | ![](https://img-blog.csdnimg.cn/20200510185704207.png) 31 | 32 | 如果你选择的是默认安装而不是自定义安装,可以忽略以下步骤,如下图这页默认全选,点击Next 33 | 34 | 35 | ![](https://img-blog.csdnimg.cn/20200510185725205.png) 36 | 37 | 38 | 如下图,打对勾的保持默认即可,下面红框是选择安装路径,其实我选择自定义安装的目的就是不想把程序安装在c盘,点击Install 等待安装完成 39 | 40 | ![(https://img-blog.csdnimg.cn/20200510185750708.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDUxMDYxNQ==,size_16,color_FFFFFF,t_70) 41 | 下面这个就是安装成功了,安装成功,我们就点击关闭就可以了close 42 | 43 | 44 | 45 | 46 | 47 | ![](https://img-blog.csdnimg.cn/20200510185806525.png) 48 | 49 | 那截止到这这个环境是安装好了是吧,那接下来我们是不是Python环境验证一下。我们用win+R打开命令窗口, 输入cmd点击确定。 50 | 51 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200510185819568.png) 52 | 53 | 54 | 55 | 56 | 查看python版本,如下图可以看到是我们上面所安装的python 3.6.7 57 | 58 | ![](https://img-blog.csdnimg.cn/2020051018584552.png) 59 | python3.6之后版本都是有pip的,pip是Python安装包的管理工具,如下图可以看到安装python3.6.7之后就有了pip,如果是 command not found 那说明没有安装。 60 | 61 | 62 | ![](https://img-blog.csdnimg.cn/20200510185900328.png) 63 | 64 | 65 | 下面,我们在命令窗口中,输入python,打开python最原始的交互环境,打印一个hello python,也就是print("hello python) 66 | 67 | 68 | 69 | 70 | ![在这里插入图片描](https://img-blog.csdnimg.cn/20200510185913497.png) 71 | 72 | 73 | 在这里输完之后直接点击回车,点击回车之后,然后Python执行我们的语句。打印这个hello python 74 | 在这里,window系统Python安装完毕。 75 | 76 | # 2、 安装Pycharm 77 | 78 | 79 | 80 | 81 | 82 | ![](https://img-blog.csdnimg.cn/20200510190124221.png) 83 | 84 | 选择下载window版本的Pycharm。 85 | 86 | 87 | 88 | ![](https://img-blog.csdnimg.cn/20200510190145246.png) 89 | 90 | 91 | 92 | 下载完成后,我们点击exe文件进行安装,安装会弹出下面界面,我们直接选择Next 93 | 94 | 95 | 96 | 97 | ![](https://img-blog.csdnimg.cn/20200510190158960.png) 98 | 99 | 100 | 下面界面就是选择安装目录。我们尽量不要默认安装,默认安装它是装C盘里了,你自己安装路径。但是注意注意有一点:安装路径千万不要中文。如果有中文的话可能会出问题。 101 | 102 | 103 | 104 | 105 | ![](https://img-blog.csdnimg.cn/20200510190219685.png) 106 | 107 | 108 | 然后点击下一步选择安装路径之后,点击下一步。 109 | 下一步完之后,它告诉你什么,创建一个桌面程序,它是64位的还是32位的,其实这里面不用多选 110 | 基本都是64位的操作系统。 111 | 112 | 113 | 114 | ![在这里插入图片描](https://img-blog.csdnimg.cn/20200510190300112.png) 115 | 点击下一步,我们不需要修改名字,直接点击install安装。 116 | 117 | 118 | 119 | ![](https://img-blog.csdnimg.cn/20200510190316166.png) 120 | 121 | 122 | 123 | 下面就是等待安装完成这个过程,不用管就等就行了,然后这就是安装完成了。 124 | 125 | ![](https://img-blog.csdnimg.cn/20200510190333204.png) 126 | 然后双击我们第一次使用PyCharm双击它,完之后弹出来一个小框,这个小框当中它是做什么的,就告诉我们是不是导入一些基本设置。我们第一次用之前也没有设置,那么就不导入了,直接就是do not,选择这个,然后OK。 127 | 128 | 129 | 130 | 131 | ![](https://img-blog.csdnimg.cn/20200510190352416.png) 132 | 133 | OK完,这里边必须要让你同意服务条款,这边是什么都不用管了。把右侧的这个滚动条滑到最底部 134 | 点击accept同意这个按钮。 135 | 136 | 137 | 138 | ![](https://img-blog.csdnimg.cn/2020051019041190.png) 139 | 140 | 下面,写一个Hello Python程序。 141 | 142 | 我们点击create new project,这个是创建一个新的项目 143 | 144 | 145 | ![](https://img-blog.csdnimg.cn/2020051019043439.png) 146 | 147 | 148 | 149 | 创建新的项目之后,这里面就要输入我们项目的存储路径以及项目名称了。那么我这里边直接把最后一个字段去改掉。其实这个就是我们自己的一个名称了。这个项目路径和项目名称添加完之后,你自己起名字就可以,然后我就在这里边点击create了,就开始创建了 150 | 151 | 152 | 153 | ![](https://img-blog.csdnimg.cn/20200510190501557.png) 154 | 155 | 156 | 157 | 我们接下来,和上一次一样的操作。第一步在我们自己的项目名称,项目名称的那里面,点击右键这是第一步,第二步,把鼠标指针挪到new上,选择new。第三步,然后点击python file,创建一个python文件 158 | 159 | 160 | 161 | ![](https://img-blog.csdnimg.cn/20200510190525196.png) 162 | 163 | 我们的代码就要写到这个文件里,然后输入hello,这hello其实是这个文件名字 164 | 165 | ![](https://img-blog.csdnimg.cn/20200510190542698.png) 166 | 然后点击OK,点击完OK之后呈现到大家面前是这么样的页面,它分两个区域,一个是python文件列表区域 167 | 168 | 这个其实是我们项目的所有的文件列表,现在我们只创建了一个文件叫hello.py。然后还有就是代码编写区域 169 | ,我们所有代码都要在代码编写区域当中来进行写。 170 | 171 | 172 | ![](https://img-blog.csdnimg.cn/20200510190607666.png) 173 | 174 | 那么这里我们要做什么,输入跟我们之前输的那个东西是一样的,也是那行代码print("hello Python")。输入完之后右键在空白区域,空白区域右键就可以了,它会弹出来这么一个框是吧。在这个框我们点击 RunHello,跑一下这个代码,在你的IDE的最下面就会出现hello Python 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | ![](https://img-blog.csdnimg.cn/20200510190625398.png) 184 | 185 | 186 | -------------------------------------------------------------------------------- /1-10/2、搭建JupyterNotebook环境.md: -------------------------------------------------------------------------------- 1 | @Author : By Runsen 2 | 3 | 4 | 5 | 搭建Jupyter Notebook环境(二) 6 | 7 | @[toc] 8 | 9 | 10 | 11 | # 1、Jupyter notebook历史 12 | 13 | Jupyter 创始人 Fernando Pérez 的说法,他最初的梦想是做一个综合 Ju (Julia)、Py (Python)和 R 三种科学运算语言的计算工具平台,所以将其命名为 Ju-Py-te-R。发展到现在,Jupyter 已经成为一个几乎支持所有语言,能够把软件代码、计算输出、解释文档、多媒体资源整合在一起的多功能科学运算平台。 14 | 15 | 在Pycham中只能运行一共py文件,而在Jupyter notebook可以运行一行代码就可以了。 16 | 17 | # 2 、环境搭建 18 | 19 | 你可以直接是通过 pip 命令安装。 20 | 21 | 22 | ```clike 23 | pip install jupyter 24 | ``` 25 | 26 | 你也可以下载anaconda 27 | 28 | 29 | 30 | 31 | Anaconda官网下载链接:https://www.anaconda.com/distribution/#download-section,选择Python3版本的安装包下载即可 32 | 33 | 34 | ![](https://img-blog.csdnimg.cn/20200510224126168.png) 35 | 36 | 37 | 38 | 39 | 40 | 如果下载速度过慢,可以选择安装Anaconda的清华镜像,网址https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive 41 | 42 | 43 | 下载完成之后,直接双击安装包安装即可。安装后添加清华镜像源解决conda install 下载速度慢的问题,打开Anaconda Prompt命令行,依次添加命令 44 | 45 | 46 | 47 | ```clike 48 | conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ 49 | conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/ 50 | conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/ 51 | conda config --set show_channel_urls yes 52 | ``` 53 | 54 | 之前说清华源,不适应了,现在OK,可以使用清华源 55 | 56 | 57 | 58 | # 3、 conda常见命令 59 | 60 | conda不仅可以方便安装,更新,卸载工具包,而且安装时能自动安装相应的依赖包。conda命令多数时候是在配置虚拟环境时使用,下面是conda常见命令 61 | 62 | ```python 63 | conda list //查看当前的包 64 | conda search request //查找request库 65 | conda install request //安装request库 66 | conda uninstall request //删除request库 67 | conda update request //更新request库 68 | ``` 69 | 70 | 很多时候不同的库依赖不同的依赖包,需要创建虚拟环境,下面是conda创建虚拟环境的常用命令 71 | 72 | ``` 73 | conda info --envs //查看安装好的环境 74 | # deeplearn代指克隆得到的新环境的名称,base代指被克隆的环境的名称 75 | conda create --name deeplearn --clone base 76 | # 激活虚拟环境 77 | activate envname //for windows 78 | source activate envname //for liunx and mac 79 | # 退出虚拟坏境 80 | deactivate 81 | #查看当前的包 82 | conda list 83 | ``` 84 | 85 | ![](https://img-blog.csdnimg.cn/20200510225507691.png) 86 | 87 | 88 | ```clik 89 | #查看安装好的环境 90 | conda info --envs 91 | ``` 92 | 93 | 94 | 95 | ![](https://img-blog.csdnimg.cn/20200510225537392.png) 96 | 97 | 98 | 99 | 100 | 101 | # 4、虚拟环境搭建 102 | 103 | 在创建的虚拟环境上运行jupyter notebook,但发现在notebook中的python其实并没有运行在指定的虚拟环境引擎上,只需要安装nb_conda_kernels插件即可解决,注意是在base环境下安装,而不是虚拟环境 104 | 105 | ```clike 106 | (base) conda install nb_conda_kernels 107 | ``` 108 | 109 | 安装成功后,在kernel -> change kernel中即可切换到指定的虚拟环境 110 | 111 | ![](https://img-blog.csdnimg.cn/20200510224404138.png) 112 | 你可以可以新建Notebook的时候设置kernel 113 | 114 | 115 | 116 | ![](https://img-blog.csdnimg.cn/20200510224300139.png) 117 | 118 | 119 | # 5、 修改jupyter notebook的打开路径 120 | 121 | 122 | 123 | 124 | 安装好jupyter notebook 后打开的是默认文档位置,需要来修改存放文件的路径。 125 | 126 | 下面教大家修改jupyter notebook的打开路径 127 | 128 | 打开jupyter notebook 文件所在的位置 129 | 130 | ![](https://img-blog.csdnimg.cn/20190217140534777.png) 131 | 右键, 打开属性 132 | ![](https://img-blog.csdnimg.cn/2019021714085440.png) 133 | 134 | 按照下图配置参数 135 | ![](https://img-blog.csdnimg.cn/2019021714135627.png) 136 | 这样打开jupyter notebook就不是默认文档位置了。 137 | 138 | 139 | ![](https://img-blog.csdnimg.cn/20200510224701876.png) 140 | 141 | 142 | 143 | # 6、 pip 和conda的区别 144 | 145 | 146 | 147 | 148 | 149 | conda可以让你同时管理安装处理有关的python任务和跟python无关任务,即pip可以允许在任何环境中安装 python包,conda允许你在conda环境中安装任何语言包(包括C语言或者python)。 150 | 151 | 152 | conda使用一个新的包格式,你不能交替使用conda和pip, 153 | 154 | 因为pip不能安装和解析conda的包格式。可以使用这两个工具,但是它们是不能交互的。 155 | 156 | 157 | 158 | conda安装库是在一个地方,而且需要根据Python的环境和依赖库而定,比如numpy的版本有的过高,导致安装这个库使用的时候报错。 159 | 160 | 161 | pip安装就是根据Python的版本而定,有的时候conda安装不了,可以采用pip安装。 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /1-10/3、新手Jupyter不会用,我十招教你盘她.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | @Author : By Runsen 4 | 5 | 上次教大家搭建好了Jupyter,并学习了一些conda命令。 6 | 7 | 如果你是新手,Jupyter不会用,那么我教你盘她 8 | @[toc] 9 | 10 | 11 | 12 | # 1、官方文档 13 | 14 | 安装好了anaconda只好,大家应该见到这些玩意,还有一个spider我删除了,有Pycharm就可以不要spider了。我这里的jupyter是设置了deeplearn为默认环境,所以有jupyter后面多了deeplearn。 15 | ![](https://img-blog.csdnimg.cn/20200510230541144.png) 16 | 17 | 我们点击那个Navigator,等一下就可以下面的图片了。 18 | 19 | 20 | ![](https://img-blog.csdnimg.cn/20200510230905927.png) 21 | 我们选择learning,点击jupyter就可以看文档了。大家学习都是要这样,先去官方文档。 22 | 23 | ![](https://img-blog.csdnimg.cn/2020051023101055.png) 24 | 25 | 浏览器就来到了:https://jupyter.org/documentation.html 26 | 27 | 28 | 29 | ![](https://img-blog.csdnimg.cn/20200510231149252.png) 30 | 31 | 然后,我们点击jupyter notebook 32 | 33 | 34 | 来到官方文档:https://jupyter-notebook.readthedocs.io/en/stable/ 35 | 36 | 读英文不行啊,建议大家安装Chrome,直接翻译中文简体。 37 | 38 | ![](https://img-blog.csdnimg.cn/20200510231403855.png) 39 | 这里建议停留十分钟,大家把jupyter的官方文档看一遍,再继续看下面。 40 | 41 | # 2、创建一个jupter notebook 42 | 下面,我们就真正开始学习Jupyter ,我不想抄官方文档,就把自己的经验那出来算了。 43 | 44 | 45 | 46 | 该页面是启动之后默认打开的页面。我们可以看到当前目录下已有的文件,可以查看已有的jupyter 文件(灰色表示未在运行,绿色表示正在运行),可以点击查看子目录下的内容,jupyter 默认访问的是8888端口 47 | 48 | ![](https://img-blog.csdnimg.cn/2020051023215453.png) 49 | 50 | 51 | 52 | 创建一个jupter notebook非常的简单,点击右侧的New,选择Python3会在新的页面中建立一个未命名的notebook文件,选择Text File会新的页面中建立一个未命名的txt文件,选择Folder会在当前页面中建立一个未命名文件夹,选择Terminal会在新的页面中建立Terminal。 53 | 54 | ![](https://img-blog.csdnimg.cn/20200510232402410.png) 55 | 56 | 57 | 58 | 下面就是新建的内容 59 | ![](https://img-blog.csdnimg.cn/20200510232421600.png) 60 | 61 | 62 | 63 | 64 | 重命名直接点击文件名就可以了。 65 | 66 | ![](https://img-blog.csdnimg.cn/20200510232528566.png) 67 | 68 | 可以在左侧进行勾选,对文件夹进行重命名,移动或删除,对文件进行复制,重命名,移动,编辑和删除。 69 | 70 | 71 | 72 | ![](https://img-blog.csdnimg.cn/20200510232642912.png) 73 | 74 | 75 | ![](https://img-blog.csdnimg.cn/20200510232757852.png) 76 | 如果这个后台删除了,那么你就访问不了你的jupyter了。 77 | 78 | 79 | 80 | # 3、 Notebook使用 81 | 82 | 83 | 84 | 下面,教大家学习一下Notebook使用 85 | 、![](https://img-blog.csdnimg.cn/20200510233001843.png) 86 | 87 | 88 | 现在我们在help中点击Notebook help,来到了官方的教程,建议你还是看一看。 89 | 90 | ![](https://img-blog.csdnimg.cn/20200510233259224.png) 91 | 92 | 官方的教程的网页 93 | ![](https://img-blog.csdnimg.cn/20200510233449759.png) 94 | # 4、 编辑模式 95 | 96 | 97 | 98 | 每一个cell有两种模式:命令模式和编辑模式。 99 | 100 | 101 | 102 | ![](https://img-blog.csdnimg.cn/20200510234214589.png) 103 | 104 | 105 | 如下图所示:最左侧是蓝色的条是命令模式,是绿色的条表示编辑模式(此时cell中有光标,可以进行代码编写)。在命令模式下,按下enter或者鼠标单击代码框可以进入编辑模式。在编辑模式下,按下esc或者鼠标单击代码框左侧区域即可进入命令模式。 106 | 107 | 108 | 109 | ![](https://img-blog.csdnimg.cn/20200510234332838.png) 110 | 111 | 112 | 在编辑模式下,按住SHIFT+ENTER就可以运行代码了。 113 | 114 | 115 | 116 | 117 | 118 | # 5、命令模式 119 | 120 | 121 | 命令模式就是使用Markdown。 122 | 123 | ![](https://img-blog.csdnimg.cn/20200510234800502.png) 124 | 125 | ![](https://img-blog.csdnimg.cn/20200510235339934.png) 126 | 127 | 在命令模式下,可以按住下面的键,实现下面的效果。 128 | 129 | 130 | - 按下A:向上增加空白的cell 131 | 132 | - 按下B:向下增加空白的cell 133 | 134 | - 按下D两次(DD):删除该cell 135 | 136 | - 按下X:剪贴该cell 137 | 138 | - 按下V:粘贴该cell 139 | 140 | - 按下L:打开、关闭行号 141 | 142 | 143 | - 按下M:进入Markdown模式 144 | 145 | - 按下Y:退出Markdown模式,回到代码编辑模式 146 | 147 | 148 | 149 | 当进入Markdown模式的时候,cell左边的 In【】会消失掉 150 | 151 | 152 | 153 | # 6、Markdown语法 154 | 155 | 156 | 我直接把CSDN上的Markdown给你搬过来。 157 | 158 | 下面是常见的快捷键 159 | 160 | ![](https://img-blog.csdnimg.cn/20200510235521475.png) 161 | 162 | 163 | 164 | 目录,标题和文本样式 165 | 166 | ![](https://img-blog.csdnimg.cn/20200510235912274.png) 167 | 168 | 169 | ![](https://img-blog.csdnimg.cn/20200511000002261.png) 170 | 171 | 我觉得你还是写博客直接看CSDN的帮助文档算了。 172 | 173 | # 6、Latex数学公式 174 | 175 | Latex我不想写了,直接看我之前的文章 176 | 177 | [手把手教你插入数学公式,妈妈再也不用担心我写不了论文了](https://maoli.blog.csdn.net/article/details/105377233) 178 | 179 | 180 | 181 | 182 | 183 | # 7、Notebook小技巧 184 | 185 | 这篇文写得不错,总结了Notebook的27个小技巧,文章链接:http://liuchengxu.org/pelican-blog/jupyter-notebook-tips.html。这是原创,大家不要看那些转载的。 186 | 187 | 188 | 189 | # 8、保存文件 190 | 191 | 192 | 193 | 194 | 195 | 196 | 我们新建的名字叫ipynb,为什么我喜欢用Jupyter,就是因为可以保存很多类型的文件,比如pdf,html,markdowm,latex。 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | ![](https://img-blog.csdnimg.cn/20200510233632667.png) 209 | 210 | 211 | # 9、误删了怎么恢复 212 | 213 | 214 | 直接在一个单元格中输入:history (如图) 215 | 就会展示出历史代码(前提是你运行过的,否则不会打印出来) 216 | 217 | ![](https://img-blog.csdnimg.cn/20200511000624937.png) 218 | # 10、大招 219 | 我把大招留在最后,就是你遇到不会的模块怎么办 220 | 221 | 222 | 遇到代码不会怎么办? 223 | 224 | 225 | 226 | 227 | 228 | 229 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200511001045804.png) 230 | 231 | 232 | 233 | ![](https://img-blog.csdnimg.cn/20200511001207980.png) 234 | @Author : By Runsen 235 | 236 | -------------------------------------------------------------------------------- /1-10/6、乘胜追击,将剩下的Git知识点搞定.md: -------------------------------------------------------------------------------- 1 |  2 | @Author : By Runsen 3 | @Author : 2020/5/15 4 | 5 | 6 | 7 | 8 | 先上图回顾回顾 9 | ![](https://img-blog.csdnimg.cn/20190801172352872.png) 10 | ![](https://img-blog.csdnimg.cn/20190801172403911.png) 11 | 12 | 13 | @[TOC] 14 | 15 | 16 | # 1、对比文件 17 | 18 | 19 | ![](https://img-blog.csdnimg.cn/2020051519080911.png) 20 | 21 | 我先通过git log 查看以前的信息。对比文件的命名很简单 22 | 23 | 24 | ```css 25 | git diff HEAD HEAD^ -- 文件名 26 | ``` 27 | 28 | HEAD表示当前的版本,HEAD^ 表示上一个版本。 29 | ![](https://img-blog.csdnimg.cn/20200515190922878.png) 30 | 31 | 32 | # 2、文件删除 33 | 34 | 35 | 删除没有添加进版本库中的工作区中的文件,那直接删除不用做任何操作。 36 | 37 | 如果已添加进工作区但没有提交的文件,先要先撤回工作区 38 | 39 | 40 | 比如,现在我写了一个`文件添加到版本库.txt`。 41 | 42 | 43 | ![](https://img-blog.csdnimg.cn/20200515191245233.png) 44 | 45 | 46 | 47 | 先提交下,git status 查看状态,绿色就是在版本库。 48 | 49 | 50 | 51 | ![](https://img-blog.csdnimg.cn/2020051519143026.png) 52 | 现在就是使用 53 | 54 | 55 | 56 | ```css 57 | git reset HEAD 58 | 59 | ``` 60 | 61 | 62 | 就可以撤销了,不行git status 查看状态,红色就是在工作区。 63 | 64 | 65 | 66 | 67 | 68 | 69 | ![](https://img-blog.csdnimg.cn/20200515191748504.png) 70 | 71 | 72 | 如果我已提交到版本库,突然间我发现写错了代码,老板看了,肯定扣我工资 ,不行,我赶紧要回来。 73 | 74 | 75 | 76 | ![](https://img-blog.csdnimg.cn/20200515192532376.png?) 77 | 78 | 79 | 去码云看看,发现存在了。现在怎么把这个文件撤回呢? 80 | 81 | ![](https://img-blog.csdnimg.cn/20200515192615841.png) 82 | 83 | 84 | 有人说,我直接去Github码云上删除,恩,是一种办法,而且是一个猪办法 85 | 86 | 87 | 88 | ![](https://img-blog.csdnimg.cn/20200515193131734.png) 89 | 如果项目不是在你的账号创建的,就没资格用客户端删东西。 90 | 91 | 92 | 93 | 94 | 答案就是回滚,再提交,只需要执行: 95 | 96 | 97 | 98 | ```css 99 | git revert HEAD 100 | git push 101 | ``` 102 | 103 | 104 | ![](https://img-blog.csdnimg.cn/20200515193748656.png) 105 | 106 | 107 | 108 | 109 | 这时候就没有了 110 | ![](https://img-blog.csdnimg.cn/20200515193809887.png) 111 | 112 | # 3、创建分支 113 | 114 | 正常的开发项目中都是多人协作,每个人的任务一般不会一天就完成,如果把没有完成的代码提交到远程仓库会影响被人工作。git提供了分支的功能就不用担心了,可以创建一个自己的分支,在上面干活,想提交就提交,等到工作完成再一次性合并到原来的分支。 115 | 116 | 117 | 118 | 新建git仓库时会默认创建一个分支master,它叫主分支。一般情况我们不会直接在主分支上干活,它主要用来发布版本。 119 | 120 | 121 | 我创建一个开发分支develop 122 | 123 | 124 | 125 | ```css 126 | git branch develop 127 | ``` 128 | 129 | 130 | 再切换到develop分支 131 | 132 | ```css 133 | git checkout develop 134 | 135 | ``` 136 | 137 | ‘ 138 | ![](https://img-blog.csdnimg.cn/20200515194148130.png) 139 | 140 | 使用git branch命令查看当前分支。-b参数表示创建并切换。 141 | 142 | 143 | 144 | 如果想创建的时候,直接切换,直接-b参数 145 | 146 | 147 | ```css 148 | git checkout-b develop 149 | 150 | ``` 151 | 152 | 153 | # 4、合并分支 154 | 155 | 156 | 157 | 创建好develop分支,菜比的我,24小时之后开发完毕,提交: 158 | 159 | 160 | ![](https://img-blog.csdnimg.cn/20200515194525171.png) 161 | 162 | 163 | 164 | 165 | ```css 166 | $ git add . 167 | $ git commit -m '24小时之后开发完毕' 168 | 169 | ``` 170 | 171 | 172 | ![](https://img-blog.csdnimg.cn/20200515194625617.png) 173 | 174 | 现在切换到master 175 | 176 | 177 | ```css 178 | $ git checkout master 179 | Switched to branch 'master' 180 | ``` 181 | 182 | 183 | 查看工作区,你会发现刚才写的文件没有了,不要惊慌,因为那个提交是在develop分支上,现在Runsne把develop分支的工作合并到master分支上: 184 | 185 | 186 | ![](https://img-blog.csdnimg.cn/20200515194803519.png) 187 | 188 | 189 | 190 | 191 | 192 | ```css 193 | git merge develop 194 | ``` 195 | 196 | 197 | 198 | 199 | 200 | ![](https://img-blog.csdnimg.cn/20200515194857226.png) 201 | 202 | 203 | 204 | 这个时候就出现了 205 | ![](https://img-blog.csdnimg.cn/20200515194917844.png) 206 | 207 | 208 | 209 | # 5、删除分支 210 | 211 | 212 | 213 | 214 | 合并完之后你也可以删除掉develop分支: 215 | 216 | ```css 217 | $ git branch -d develop 218 | Deleted branch develop (was 25942c9)). 219 | $ git branch 220 | * master 221 | ``` 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | ![](https://img-blog.csdnimg.cn/20200515195109608.png) 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | OK搞定,把之前的Git文章全部删除 238 | 239 | 240 | ![](https://img-blog.csdnimg.cn/20200515195234117.png) 241 | -------------------------------------------------------------------------------- /11-20/12、深入Python列表和元组.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | @Author :Runsen 5 | 6 | 上面四篇文章总结了Python的基础。 7 | 8 | 9 | 在Pthon中数据结构是非常重要的,所以下面将深入Pyhon数据结构 10 | 11 | 12 | 13 | 14 | Python列表和元组总结 15 | 16 | @[TOC] 17 | 18 | # 什么是列表和元组 19 | 20 | 21 | 22 | 列表是动态的,长度大小不固定,可以随意地增加、删减或者改变 23 | 24 | 25 | 而元组是静态的,长度大小固定,无法增加删减或者改变 26 | 27 | 28 | 定义列表和函数 29 | 30 | ```python 31 | l = [1, 2, 'hello', 'world'] # 列表中同时含有 int 和 string 类型的元素 32 | l 33 | [1, 2, 'hello', 'world'] 34 | 35 | tup = ('jason', 22) # 元组中同时含有 int 和 string 类型的元素 36 | tup 37 | ('jason', 22) 38 | 39 | ``` 40 | 41 | 42 | 对于列表来说,由于其是动态的,我们只需简单地在列表末尾,加入 43 | 44 | 对于元组来说,实际上就是创建了一个新的元组,然后把原来两个元组的值依次填充. 45 | 46 | 47 | 48 | 49 | ```python 50 | tup = (1, 2, 3, 4) 51 | new_tup = tup + (5, ) # 创建新的元组 new_tup,并依次填充原元组的值 52 | new _tup 53 | (1, 2, 3, 4, 5) 54 | 55 | l = [1, 2, 3, 4] 56 | l.append(5) # 添加元素 5 到原列表的末尾 57 | l 58 | [1, 2, 3, 4, 5] 59 | 60 | ``` 61 | Python 中的列表和元组都支持负数索引,列表和元组都支持切片操作 62 | 63 | 64 | ```python 65 | l = [1, 2, 3, 4] 66 | l[-1] 67 | 4 68 | 69 | tup = (1, 2, 3, 4) 70 | tup[-1] 71 | 4 72 | 73 | 74 | list = [1, 2, 3, 4] 75 | l[1:3] # 返回列表中索引从 1 到 2 的子列表 76 | [2, 3] 77 | 78 | tup = (1, 2, 3, 4) 79 | tup[1:3] # 返回元组中索引从 1 到 2 的子元组 80 | (2, 3) 81 | 82 | ``` 83 | # 列表和元组常见的内置函数 84 | 85 | 86 | ```python 87 | l = [3, 2, 3, 7, 8, 1] 88 | l.count(3) 89 | 2 90 | l.index(7) 91 | 3 92 | l.reverse() 93 | l 94 | [1, 8, 7, 3, 2, 3] 95 | l.sort() 96 | l 97 | [1, 2, 3, 3, 7, 8] 98 | 99 | tup = (3, 2, 3, 7, 8, 1) 100 | tup.count(3) 101 | 2 102 | tup.index(7) 103 | 3 104 | list(reversed(tup)) 105 | [1, 8, 7, 3, 2, 3] 106 | sorted(tup) 107 | [1, 2, 3, 3, 7, 8] 108 | 109 | ``` 110 | # 列表和元组存储方式 111 | 112 | ```python 113 | l = [] 114 | l.__sizeof__() // 空列表的存储空间为 40 字节 115 | 40 116 | l.append(1) 117 | l.__sizeof__() 118 | 72 // 加入了元素 1 之后,列表为其分配了可以存储 4 个元素的空间 (72 - 40)/8 = 4 119 | l.append(2) 120 | l.__sizeof__() 121 | 72 // 由于之前分配了空间,所以加入元素 2,列表空间不变 122 | l.append(3) 123 | l.__sizeof__() 124 | 72 // 同上 125 | l.append(4) 126 | l.__sizeof__() 127 | 72 // 同上 128 | l.append(5) 129 | l.__sizeof__() 130 | 104 // 加入元素 5 之后,列表的空间不足,所以又额外分配了可以存储 4 个元素的空间 131 | 132 | ``` 133 | 元组的初始化速度,要比列表快 5 倍。 134 | 135 | ```python 136 | python3 -m timeit 'x=(1,2,3,4,5,6)' 137 | 20000000 loops, best of 5: 9.97 nsec per loop 138 | python3 -m timeit 'x=[1,2,3,4,5,6]' 139 | 5000000 loops, best of 5: 50.1 nsec per loop 140 | ``` 141 | 142 | 143 | 144 | 145 | 因此如果存储的数据和数量不变,选择元组 146 | 147 | 148 | 如果存储的数据或数量是可变的,选择列表 149 | 150 | 151 | 152 | 下面有两种方法创建列表,哪个初始化更快,运行时间更快。 153 | ```python 154 | 155 | # 创建空列表 156 | # option A 157 | empty_list = list() 158 | 159 | # option B 160 | empty_list = [] 161 | 162 | ``` 163 | ![](https://img-blog.csdnimg.cn/20190523000342208.png) 164 | 165 | 测试结果,虽然直接创建元组初始化速度最快,但是由于要用list函数转一道反而不如直接创建列表的速度快。 166 | -------------------------------------------------------------------------------- /11-20/13、深入Python字典和集合.md: -------------------------------------------------------------------------------- 1 |  2 | @Author :Runsen 3 | 4 | 5 | 6 | @[toc] 7 | 8 | # 字典和集合 9 | 10 | 字典是一系列无序元素的组合,其长度大小可变,元素可以任意地删减和改变。不过要注意,这里的元素,是一对键(key)和值(value) 11 | 12 | 13 | 相比于列表和元组,字典的性能更优,特别是对于查找、添加和删除,字典都能在常数的时间复杂度内完成 14 | 15 | 16 | 17 | 18 | 而集合和字典基本相同,唯一的区别,就是集合没有键和值的配对是一系列无序的、唯一的元素组合。 19 | 20 | ```python 21 | d1 = {'name': 'jason', 'age': 20, 'gender': 'male'} 22 | d2 = dict({'name': 'jason', 'age': 20, 'gender': 'male'}) 23 | d3 = dict([('name', 'jason'), ('age', 20), ('gender', 'male')]) 24 | d4 = dict(name='jason', age=20, gender='male') 25 | d1 == d2 == d3 ==d4 26 | True 27 | 28 | s1 = {1, 2, 3} 29 | s2 = Set([1, 2, 3]) 30 | s1 == s2 31 | True 32 | 33 | ``` 34 | 35 | 集合并不支持索引操作,因为集合本质上是一个哈希表,和列表不一样 36 | 37 | ```和集合 38 | s = {1, 2, 3} 39 | s[0] 40 | Traceback (most recent call last): 41 | File "", line 1, in 42 | TypeError: 'set' object does not support indexing 43 | ``` 44 | 45 | 想要判断一个元素在不在字典或集合内,我们可以用 value in dict/set 46 | 47 | ```和集合 48 | s = {1, 2, 3} 49 | 1 in s 50 | True 51 | 10 in s 52 | False 53 | 54 | d = {'name': 'Runsen', 'age': 20} 55 | 'name' in d 56 | True 57 | 'location' in d 58 | False 59 | 60 | ``` 61 | **字典的增删改** 62 | ```和集合 63 | In [1]: d = {'name': 'Runsen', 'age': 20}^M 64 | ...: 65 | 66 | In [2]: d['gender'] = 'male' 67 | 68 | In [3]: d['birthday'] = '1999-10-01' 69 | 70 | In [4]: d 71 | Out[4]: {'name': 'Runsen', 'age': 20, 'gender': 'male', 'birthday': '1999-10-01'} 72 | 73 | In [5]: d['birthday'] = '1999/10/01' 74 | 75 | In [6]: d.pop('birthday') 76 | Out[6]: '1999/10/01' 77 | 78 | In [8]: d 79 | Out[8]: {'name': 'Runsen', 'age': 20, 'gender': 'male'} 80 | 81 | 82 | In [9]: s = {1, 2, 3}^M 83 | ...: 84 | 85 | In [10]: s.add(4) 86 | 87 | In [11]: s 88 | Out[11]: {1, 2, 3, 4} 89 | 90 | In [12]: s.remove(4) 91 | 92 | In [13]: s 93 | Out[13]: {1, 2, 3}**** 94 | 95 | ``` 96 | 97 | **字典的升序和降序排序** 98 | ```和集合 99 | d = {'b': 1, 'a': 2, 'c': 10} 100 | d_sorted_by_key = sorted(d.items(), key=lambda x: x[0]) # 根据字典键的升序排序 101 | d_sorted_by_value = sorted(d.items(), key=lambda x: x[1]) # 根据字典值的升序排序 102 | d_sorted_by_key 103 | [('a', 2), ('b', 1), ('c', 10)] 104 | d_sorted_by_value 105 | [('b', 1), ('a', 2), ('c', 10)] 106 | ``` 107 | 108 | 109 | # 增删查找 110 | 111 | 字典和集合是进行过性能高度优化的数据结构,特别是对于查找、添加和删除操作 112 | 113 | 114 | **列表的做法** 115 | 116 | ```和集合 117 | 118 | # list version 119 | def find_unique_price_using_list(products): 120 | unique_price_list = [] 121 | for _, price in products: # A 122 | if price not in unique_price_list: #B 123 | unique_price_list.append(price) 124 | return len(unique_price_list) 125 | 126 | # products id 和 price 127 | products = [ 128 | (143121312, 100), 129 | (432314553, 30), 130 | (32421912367, 150), 131 | (937153201, 30) 132 | ] 133 | print('number of unique price is: {}'.format(find_unique_price_using_list(products))) 134 | 135 | # 输出 136 | number of unique price is: 3 137 | ``` 138 | 139 | 140 | **集合的做法** 141 | 142 | 143 | 144 | ```python 145 | 146 | # set version 147 | def find_unique_price_using_set(products): 148 | unique_price_set = set() 149 | for _, price in products: 150 | unique_price_set.add(price) 151 | return len(unique_price_set) 152 | 153 | products = [ 154 | (143121312, 100), 155 | (432314553, 30), 156 | (32421912367, 150), 157 | (937153201, 30) 158 | ] 159 | print('number of unique price is: {}'.format(find_unique_price_using_set(products))) 160 | 161 | # 输出 162 | number of unique price is: 3 163 | ``` 164 | 比较运行的时间,也就是性能 165 | 166 | ```python 167 | import time 168 | id = [x for x in range(0, 100000)] 169 | price = [x for x in range(200000, 300000)] 170 | products = list(zip(id, price)) 171 | 172 | # 计算列表版本的时间 173 | start_using_list = time.perf_counter() 174 | find_unique_price_using_list(products) 175 | end_using_list = time.perf_counter() 176 | print("time elapse using list: {}".format(end_using_list - start_using_list)) 177 | ## 输出 178 | time elapse using list: 41.61519479751587 179 | 180 | 181 | # 计算集合版本的时间 182 | start_using_set = time.perf_counter() 183 | find_unique_price_using_set(products) 184 | end_using_set = time.perf_counter() 185 | print("time elapse using set: {}".format(end_using_set - start_using_set)) 186 | # 输出 187 | time elapse using set: 0.008238077163696289 188 | ``` 189 | 190 | 191 | 在性能上集合完爆列表 192 | 193 | 194 | 195 | 对于字典,哈希表存储了哈希值,键和值这桑三个元素 196 | 197 | ![](https://img-blog.csdnimg.cn/20190523142853281.png) 198 | 199 | 200 | 201 | 202 | 203 | 字典和集合都是无序的数据结构,其内部的哈希表存储结构,保证了查找,插入,删除操作的高效性。所以,字典和集合通常运用在对元素的查找,去重 204 | 205 | 206 | 207 | 208 | 初始化字典的方式有两种方法,比较下哪一种更高效, 209 | 210 | ```python 211 | In [20]: timeit a ={'name':"runsen",'age':20} 212 | 127 ns ± 0.8 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) 213 | 214 | In [21]: timeit b =dict({'name':"runsen",'age':20}) 215 | 438 ns ± 3.41 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 216 | 217 | ``` 218 | 第一种,因为不用调用相关的函数 219 | 220 | 221 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS83NjUxNjE3Yy1hMWM0LTRjMGEtYjkyNC04YmMxMzk3NTAwODkucG5n?x-oss-process=image/format,png) 222 | 223 | 224 | 字典的键可以是一个列表吗?下面这段代码中,字典的初始化是否正确 225 | 226 | ```python 227 | In [22]: d = {'name': 'Runsen', ['education']: [' primary school', 'junior middle school']}^M 228 | ...: 229 | --------------------------------------------------------------------------- 230 | TypeError Traceback (most recent call last) 231 | in 232 | ----> 1 d = {'name': 'Runsen', ['education']: [' primary school', 'junior middle school']} 233 | 234 | TypeError: unhashable type: 'list' 235 | 236 | In [23]: d = {'name': 'Runsen', ('education'): [' primary school', 'junior middle school']}^M 237 | ...: 238 | ...: 239 | 240 | In [24]: d 241 | Out[24]: {'name': 'Runsen', 'education': [' primary school', 'junior middle school']} 242 | 243 | ``` 244 | 245 | 246 | 247 | 用列表作为 Key 在这里是不被允许的,因为列表是一个动态变化的数据结构,字典当中的 key 要求是不可变的,原因也很好理解. 248 | 249 | key 首先是不重复的,如果 Key 是可以变化的话,那么随着 Key 的变化,这里就有可能就会有重复的 Key,那么这就和字典的定义相违背;如果把这里的列表换成之前我们讲过的元组是可以的,因为元组不可变。 250 | -------------------------------------------------------------------------------- /11-20/14、深入Python条件和循坏.md: -------------------------------------------------------------------------------- 1 | @Author:By Runsen 2 | 3 | 4 | 5 | @[TOC] 6 | # 条件控制 7 | 8 | 简单来说:当判断的条件为真时,执行某种代码逻辑,这就是条件控制。 9 | 10 | 11 | 那么在讲条件控制之前,可以给大家讲一个程序员当中流传的比较真实的一个例子 12 | 13 | 说有一天一个程序员,他的媳妇让他去出去买两个包子,那出去之前,他媳妇这么跟他说的,说老公你出去给我买两个包子 14 | ,如果看见卖西瓜的就买一个回来。 15 | 16 | 结果这个程序员回来了,买一个包子。结果媳妇给他一顿揍。 17 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS8zZmYzYThiNy1mMzU1LTQ5YTgtYWRhZi1mNTkzZjc3YWI5ZGQucG5n?x-oss-process=image/format,png) 18 | 19 | 20 | 然后问他为啥,你为啥就买一个包子回来?,他回答他媳妇说我看见了卖西瓜的,所以买了一个包子。 21 | 22 | 其实这个就是条件控制一个典型的,一个生活化的一个说明场景 23 | 24 | 25 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS85YTdjMWVhZS1lNmU0LTQyODUtOWZjMS05ZTFjYjBlZThmYmQucG5n?x-oss-process=image/format,png) 26 | 27 | 28 | 29 | 30 | 31 | 32 | # 条件语句 33 | 34 | 35 | 条件控制就是我们常见的的if else 36 | 37 | 38 | 39 | ```python 40 | # y = |x| 41 | if x < 0: 42 | y = -x 43 | else: 44 | y = x 45 | 46 | ``` 47 | 在条件语句后面加上 冒号: 48 | 49 | python不支持switch语句,但是支持elif 50 | 51 | ```python 52 | if condition_1: 53 | statement_1 54 | elif condition_2: 55 | statement_2 56 | ... 57 | elif condition_i: 58 | statement_i 59 | else: 60 | statement_n 61 | 62 | ``` 63 | 不少人喜欢省略半段的条件,就像这样 64 | 65 | ```python 66 | if s: # s is a string 67 | ... 68 | if l: # l is a list 69 | ... 70 | if i: # i is an int 71 | ... 72 | ... 73 | 74 | ``` 75 | 76 | ![](https://img-blog.csdnimg.cn/2019052409161133.png) 77 | 78 | 79 | # 循环语句 80 | 81 | 82 | 一般通过for循环和while循环实现 83 | 84 | ```python 85 | l = [1, 2, 3, 4] 86 | for item in l: 87 | print(item) 88 | 1 89 | 2 90 | 3 91 | 4 92 | 93 | ``` 94 | 95 | 96 | 在python数据结构只要时可迭代对象,如列表,集合,等等,就可以遍历 97 | ```python 98 | for item in : 99 | ... 100 | 101 | ``` 102 | 103 | 但是字典本身只有键时课迭代的,如何要遍历字典的值和键值对,要通过内置的函数values() 和items() 实现 104 | 105 | ```python 106 | d = {'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'} 107 | for k in d: # 遍历字典的键 108 | print(k) 109 | name 110 | dob 111 | gender 112 | 113 | for v in d.values(): # 遍历字典的值 114 | print(v) 115 | jason 116 | 2000-01-01 117 | male 118 | 119 | for k, v in d.items(): # 遍历字典的键值对 120 | print('key: {}, value: {}'.format(k, v)) 121 | key: name, value: jason 122 | key: dob, value: 2000-01-01 123 | key: gender, value: male 124 | 125 | ``` 126 | 127 | 当然可以通过索引来遍历元素 128 | 129 | ```python 130 | l = [1, 2, 3, 4, 5, 6, 7] 131 | for index in range(0, len(l)): 132 | if index < 5: 133 | print(l[index]) 134 | 135 | 1 136 | 2 137 | 3 138 | 4 139 | 5 140 | 141 | ``` 142 | 别忘了还有一个更重要的enumerate() 函数 143 | 144 | ```python 145 | l = [1, 2, 3, 4, 5, 6, 7] 146 | for index, item in enumerate(l): 147 | if index < 5: 148 | print(item) 149 | 150 | 1 151 | 2 152 | 3 153 | 4 154 | 5 155 | 156 | ``` 157 | 在循环语句中,要通过continue 或break 一起使用 158 | 159 | 160 | continue,就是让程序跳过当前这层循环,继续执行下面的循环 161 | 162 | 163 | 164 | break 则是指完全跳出所在的整个循环体 165 | 166 | 167 | 现在找出价格小于1000,颜色不是红色的产品名称和颜色组合,如果不用continue 168 | 169 | ```python 170 | # name_price: 产品名称 (str) 到价格 (int) 的映射字典 171 | # name_color: 产品名字 (str) 到颜色 (list of str) 的映射字典 172 | for name, price in name_price.items(): 173 | if price < 1000: 174 | if name in name_color: 175 | for color in name_color[name]: 176 | if color != 'red': 177 | print('name: {}, color: {}'.format(name, color)) 178 | else: 179 | print('name: {}, color: {}'.format(name, 'None')) 180 | 181 | ``` 182 | 共用了5层for 或if 的嵌套 183 | 184 | 加上了continue,只有3层 185 | ```python 186 | # name_price: 产品名称 (str) 到价格 (int) 的映射字典 187 | # name_color: 产品名字 (str) 到颜色 (list of str) 的映射字典 188 | for name, price in name_price.items(): 189 | if price >= 1000: 190 | continue 191 | if name not in name_color: 192 | print('name: {}, color: {}'.format(name, 'None')) 193 | for color in name_color[name]: 194 | if color == 'red': 195 | continue 196 | print('name: {}, color: {}'.format(name, color)) 197 | 198 | ``` 199 | 200 | 201 | while 202 | 203 | ```python 204 | l = [1, 2, 3, 4] 205 | index = 0 206 | while index < len(l): 207 | print(l[index]) 208 | index += 1 209 | 210 | ``` 211 | 212 | 213 | 那么在什么场合使用for和continue 214 | 215 | 如果只是遍历已知的集合,找出满足条件的元素,使用for更加的简洁 216 | 217 | 如果需要在满足某个条件前,要不停的重复操作,并且没有特定的集合来遍历 218 | 219 | 220 | 例如 221 | ```python 222 | while True: 223 | try: 224 | text = input('Please enter your questions, enter "q" to exit') 225 | if text == 'q': 226 | print('Exit system') 227 | break 228 | ... 229 | ... 230 | print(response) 231 | except as err: 232 | print('Encountered error: {}'.format(err)) 233 | break 234 | 235 | ``` 236 | 237 | 238 | for 循环和while循环的效率问题 239 | 240 | ```python 241 | i = 0 242 | while i < 1000000 243 | i += 1 244 | 245 | for i in range(0, 1000000): 246 | pass 247 | 248 | 249 | ``` 250 | range()函数直接时C语言写的,调用的速度非常快,for循环的效率更高 251 | 252 | 253 | 254 | 对于有些大神直接写成一行操作 255 | 256 | ```python 257 | expression1 if condition else expression2 for item in iterable 258 | 259 | ``` 260 | 分解成 261 | ```python 262 | for item in iterable: 263 | if condition: 264 | expression1 265 | else: 266 | expression2 267 | 268 | ``` 269 | 270 | 271 | 如何没有else 272 | 273 | ```python 274 | expression for item in iterable if condition 275 | 276 | ``` 277 | 278 | 279 | 现在绘制 y = 2*|x| + 5 的函数图像 280 | 281 | 282 | 只需一行 283 | ```python 284 | y = [value * 2 + 5 if x > 0 else -value * 2 + 5 for value in x] 285 | 286 | ``` 287 | 288 | 在处理字符串时,将文件逐行读取,按照逗号分隔单词,去掉首位空字符,过滤小于3的单词,最后返回单词组成的列表 289 | 290 | ```python 291 | text = ' Today, is, Sunday' 292 | text_list = [s.strip() for s in text.split(',') if len(s.strip()) > 3] 293 | print(text_list) 294 | ['Today', 'Sunday'] 295 | 296 | ``` 297 | 给定两个列表 x、y,要求返回 x、y 中所有元素对组成的元组 298 | 299 | ```python 300 | [(xx, yy) for xx in x for yy in y if x != y] 301 | 302 | ``` 303 | 304 | 305 | ```python 306 | l = [] 307 | for xx in x: 308 | for yy in y: 309 | if x != y: 310 | l.append((x, y)) 311 | 312 | ``` 313 | 314 | -------------------------------------------------------------------------------- /11-20/15、深入Python输入和输出.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | 在很多时候,你会想要让你的程序与用户(可能是你自己)交互。你会从用户那里得到输入,然后打印一些结果。我们可以使用iinput和print语句来完成这些功能。 4 | 5 | 6 | @[TOC] 7 | 8 | 9 | 10 | 11 | # input 12 | 13 | ```python 14 | name = input('your name:') 15 | gender = input('you are a boy?(y/n)') 16 | 17 | ###### 输入 ###### 18 | your name:Jack 19 | you are a boy? 20 | 21 | welcome_str = 'Welcome to the matrix {prefix} {name}.' 22 | welcome_dic = { 23 | 'prefix': 'Mr.' if gender == 'y' else 'Mrs', 24 | 'name': name 25 | } 26 | 27 | print('authorizing...') 28 | print(welcome_str.format(**welcome_dic)) 29 | 30 | ########## 输出 ########## 31 | authorizing... 32 | Welcome to the matrix Mr. Jack. 33 | 34 | ``` 35 | input函数暂停运行,等待键盘输入,直到按下回车,输入的类型永远时字符串 36 | 37 | 38 | 39 | ```python 40 | a = input() 41 | 1 42 | b = input() 43 | 2 44 | 45 | print('a + b = {}'.format(a + b)) 46 | ########## 输出 ############## 47 | a + b = 12 48 | print('type of a is {}, type of b is {}'.format(type(a), type(b))) 49 | ########## 输出 ############## 50 | type of a is , type of b is 51 | print('a + b = {}'.format(int(a) + int(b))) 52 | ########## 输出 ############## 53 | a + b = 3 54 | 55 | ``` 56 | 57 | 58 | # 文件输入和输出 59 | 生产级别的 Python 代码,大部分 I/O 则来自于文件 60 | 61 | 这里有个in.text 62 | 63 | ```python 64 | Mr. Johnson had never been up in an aerophane before and he had read a lot about air accidents, so one day when a friend offered to take him for a ride in his own small phane, Mr. Johnson was very worried about accepting. Finally, however, his friend persuaded him that it was very safe, and Mr. Johnson boarded the plane. 65 | 66 | His friend started the engine and began to taxi onto the runway of the airport. Mr. Johnson had heard that the most dangerous part of a flight were the take-off and the landing, so he was extremely frightened and closed his eyes. 67 | 68 | After a minute or two he opened them again, looked out of the window of the plane, and said to his friend。 69 | 70 | "Look at those people down there. They look as small as ants, don't they?" 71 | 72 | "Those are ants," answered his friend. "We're still on the ground." 73 | ``` 74 | 现在 75 | - 读取文件 76 | - 去掉所有标点和换行符,将大写变为小写 77 | - 合并相同的词,统计每个词出现的频率,将词频从大到小排序 78 | - 将结果按行输出文件out.txt 79 | 80 | ```python 81 | import re 82 | 83 | # 你不用太关心这个函数 84 | def parse(text): 85 | # 使用正则表达式去除标点符号和换行符 86 | text = re.sub(r'[^\w ]', '', text) 87 | 88 | # 转为小写 89 | text = text.lower() 90 | 91 | # 生成所有单词的列表 92 | word_list = text.split(' ') 93 | 94 | # 去除空白单词 95 | word_list = filter(None, word_list) 96 | 97 | # 生成单词和词频的字典 98 | word_cnt = {} 99 | for word in word_list: 100 | if word not in word_cnt: 101 | word_cnt[word] = 0 102 | word_cnt[word] += 1 103 | 104 | # 按照词频排序 105 | sorted_word_cnt = sorted(word_cnt.items(), key=lambda kv: kv[1], reverse=True) 106 | 107 | return sorted_word_cnt 108 | 109 | with open('in.txt', 'r') as fin: 110 | text = fin.read() 111 | 112 | word_and_freq = parse(text) 113 | 114 | with open('out.txt', 'w') as fout: 115 | for word, freq in word_and_freq: 116 | fout.write('{} {}\n'.format(word, freq)) 117 | 118 | ########## 输出 (省略较长的中间结果) ########## 119 | 120 | 121 | 122 | ``` 123 | ![](https://img-blog.csdnimg.cn/20190523215923502.png) 124 | 125 | 126 | 127 | 但是有个问题,如果文件非常的大容易造成内存奔溃 128 | 129 | 这个时候给 read 指定参数 size,还可以通过 readline() 函数,每次读取一行, 130 | 131 | # json文件读取 132 | 133 | 134 | ```python 135 | import json 136 | 137 | params = { 138 | 'symbol': '123456', 139 | 'type': 'limit', 140 | 'price': 123.4, 141 | 'amount': 23 142 | } 143 | 144 | params_str = json.dumps(params) 145 | 146 | print('after json serialization') 147 | print('type of params_str = {}, params_str = {}'.format(type(params_str), params)) 148 | 149 | original_params = json.loads(params_str) 150 | 151 | print('after json deserialization') 152 | print('type of original_params = {}, original_params = {}'.format(type(original_params), original_params)) 153 | 154 | ########## 输出 ########## 155 | 156 | after json serialization 157 | type of params_str = , params_str = {'symbol': '123456', 'type': 'limit', 'price': 123.4, 'amount': 23} 158 | after json deserialization 159 | type of original_params = , original_params = {'symbol': '123456', 'type': 'limit', 'price': 123.4, 'amount': 23} 160 | 161 | ``` 162 | json.dumps() 这个函数,接受 Python 的基本数据类型 字典,然后转化string (json的字符串) 163 | 164 | json.loads() 这个函数,接受一个合法字符串(json),然后 转化为字典 165 | 166 | 167 | **json 的读入** 168 | ```python 169 | import json 170 | 171 | params = { 172 | 'symbol': '123456', 173 | 'type': 'limit', 174 | 'price': 123.4, 175 | 'amount': 23 176 | } 177 | 178 | with open('params.json', 'w') as fout: 179 | params_str = json.dump(params, fout) 180 | 181 | with open('params.json', 'r') as fin: 182 | original_params = json.load(fin) 183 | 184 | print('after json deserialization') 185 | print('type of original_params = {}, original_params = {}'.format(type(original_params), original_params)) 186 | 187 | ########## 输出 ########## 188 | 189 | after json deserialization 190 | type of original_params = , original_params = {'symbol': '123456', 'type': 'limit', 'price': 123.4, 'amount': 23} 191 | 192 | ``` 193 | 194 | -------------------------------------------------------------------------------- /11-20/16、深入Python字符串.md: -------------------------------------------------------------------------------- 1 |  2 | @Author :Runsen 3 | 4 | Python字符串总结 5 | 6 | 7 | @[TOC] 8 | 9 | # 什么字符串 10 | 字符串是由独立字符组成的一个序列,通常包含在单引号(‘ ’),双引号(”“) 11 | 12 | 三引号(''' ''') 13 | 14 | 15 | ```python 16 | s1 = 'hello' 17 | s2 = "hello" 18 | s3 = """hello""" 19 | s1 == s2 == s3 20 | True 21 | 22 | ``` 23 | 三引号字符串常用于函数的注释 24 | 25 | ```python 26 | def calculate_similarity(item1, item2): 27 | """ 28 | Calculate similarity between two items 29 | Args: 30 | item1: 1st item 31 | item2: 2nd item 32 | Returns: 33 | similarity score between item1 and item2 34 | """ 35 | 36 | ``` 37 | 38 | # 转义字符 39 | 40 | 用 \ 开头的字符串,来表示一些特定意义的字符 41 | 42 | ```python 43 | s = 'a\nb\tc' 44 | print(s) 45 | a 46 | b c 47 | 48 | len(s) 49 | 5 50 | ``` 51 | 52 | 代码中的'\n',表示一个字符——换行符;'\t'也表示一个字符,四个空格 53 | 54 | 55 | 字符 a,换行,字符 b,然后制表符,最后打印字符 c 56 | 最后打印的输出横跨了两行,但是整个字符串 s 仍然只有 5 57 | 58 | 59 | # 常用操作 60 | 61 | ```python 62 | name = 'jason' 63 | name[0] 64 | 'j' 65 | name[1:3] 66 | 'as' 67 | 68 | 69 | for char in name: 70 | print(char) 71 | j 72 | a 73 | s 74 | o 75 | n 76 | 77 | 78 | ``` 79 | 注意python的字符串是不可变的 80 | 81 | 82 | ```python 83 | s = 'hello' 84 | s[0] = 'H' 85 | Traceback (most recent call last): 86 | File "", line 1, in 87 | TypeError: 'str' object does not support item assignment 88 | 89 | ``` 90 | 91 | 只能通过船创建新的字符串 92 | ```python 93 | s = 'H' + s[1:] 94 | s = s.replace('h', 'H') 95 | 96 | ``` 97 | 98 | 99 | 在java 中有可变的字符串,StringBuilder ,每次改变字符串,无需创建新的字符串,时间复杂度为O(1) 100 | 101 | 但是在python中如果想要改变字符串,往往需要O(n)的时间复杂度,n是新字符串的长度 102 | 103 | 104 | # 拼接字符串 105 | 106 | ```python 107 | str1 += str2 # 表示 str1 = str1 + str2 108 | 109 | # 这个时间复杂度是多少 110 | s = '' 111 | for n in range(0, 100000): 112 | s += str(n) 113 | 114 | ``` 115 | 在python2中总的时间复杂度就为 O(1) + O(2) + … + O(n) = O(n^2) 116 | 117 | 但是在python3中 str1 += str2 首先会检测str1 是否有其他的引用 118 | 119 | 所以在python3中时间复杂度是O(n) 120 | 121 | 122 | 123 | 124 | 125 | ```python 126 | l = [] 127 | for n in range(0, 100000): 128 | l.append(str(n)) 129 | l = ' '.join(l) 130 | 131 | ``` 132 | 由于列表的 append 操作是 O(1) 复杂度,时间复杂度为 n*O(1)=O(n)。 133 | 134 | 135 | 136 | # split分割 137 | ```python 138 | def query_data(namespace, table): 139 | """ 140 | given namespace and table, query database to get corresponding 141 | data 142 | """ 143 | 144 | path = 'hive://ads/training_table' 145 | namespace = path.split('//')[1].split('/')[0] # 返回'ads' 146 | table = path.split('//')[1].split('/')[1] # 返回 'training_table' 147 | data = query_data(namespace, table) 148 | 149 | ``` 150 | - string.strip(str),表示去掉首尾的 str 151 | - tring.lstrip(str),表示只去掉开头的 str 152 | - string.rstrip(str),表示只去掉尾部的 str 153 | 154 | 155 | 在读入文件时候,如果开头和结尾都含有空字符,就采用strip函数 156 | ```python 157 | s = ' my name is jason ' 158 | s.strip() 159 | 'my name is jason' 160 | 161 | ``` 162 | # 格式化 163 | 164 | 165 | format 166 | ```python 167 | print('no data available for person with id: {}, name: {}'.format(id, name)) 168 | ``` 169 | 170 | 171 | 172 | ```python 173 | print('no data available for person with id: %s, name: %s' % (id, name)) 174 | 175 | ``` 176 | **%s 表示字符串型,%d 表示整型** 177 | 178 | 179 | 180 | 181 | **两种字符串拼接操作,哪个更好** 182 | ```python 183 | s = '' 184 | for n in range(0, 100000): 185 | s += str(n) 186 | 187 | ``` 188 | 189 | ```python 190 | l = [] 191 | for n in range(0, 100000): 192 | l.append(str(n)) 193 | 194 | s = ' '.join(l) 195 | 196 | ``` 197 | 对于上面的两种拼接操作,计算运行时间 198 | 199 | 200 | 201 | ```python 202 | # 第一个 += 203 | import time 204 | start_time =time.perf_counter() 205 | s = '' 206 | for n in range(0,1000000): 207 | s += str(n) 208 | end_time = time.perf_counter() 209 | # 5.7604558070000005 210 | print(end_time - start_time) 211 | # 第二个 join 212 | import time 213 | start_time =time.perf_counter() 214 | s = [] 215 | for n in range(0,1000000): 216 | s.append(str(n)) 217 | ''.join(s) 218 | end_time = time.perf_counter() 219 | # 0.622547053 220 | print(end_time - start_time) 221 | 222 | 223 | 224 | # 第三个 map 225 | import time 226 | start_time = time.perf_counter() 227 | s = ''.join(map(str, range(0, 1000000))) 228 | end_time = time.perf_counter() 229 | # 0.403433529 230 | print(end_time - start_time) 231 | 232 | ``` 233 | 234 | 235 | 结果: 236 | - 对于数据量大的map好过join,join好过 += 237 | 238 | 239 | - 对于数据量小的map 好过 += 好过join 240 | 241 | 242 | ![](https://img-blog.csdnimg.cn/2019052315133017.png) 243 | -------------------------------------------------------------------------------- /11-20/17、深入Python异常处理.md: -------------------------------------------------------------------------------- 1 | @Author:BY Runsen 2 | 3 | 4 | 5 | 6 | @[toc] 7 | 8 | # 异常处理 9 | 在Python 中的错误和异常是什么? 10 | 11 | 通常来说,程序中的错误至少包括两种,一种是语法错误,另一种则是异常。所谓语法错误,你应该很清楚,也就是你写的代码不符合编程规范,无法被识别与执行,比如下面这个例子的语法错误 12 | 13 | 下面的代码无法被识别和执行 14 | ```python 15 | if name is not None 16 | print(name) 17 | ``` 18 | If 语句漏掉了冒号,不符合 Python 的语法规范,所以程序就会报错invalid syntax。 19 | 20 | 21 | 异常则是指程序的语法正确,也可以被执行,但在执行过程中遇到了错误,抛出了异常 22 | ```python 23 | 10 / 0 24 | Traceback (most recent call last): 25 | File "", line 1, in 26 | ZeroDivisionError: integer division or modulo by zero 27 | 28 | order * 2 29 | Traceback (most recent call last): 30 | File "", line 1, in 31 | NameError: name 'order' is not defined 32 | 33 | 1 + [1, 2] 34 | Traceback (most recent call last): 35 | File "", line 1, in 36 | TypeError: unsupported operand type(s) for +: 'int' and 'list' 37 | 38 | ``` 39 | 40 | 常见的报错是ZeroDIvision NameError 和 typeError 41 | 42 | 还有很多其他异常的类型如keyError 字典的键找不到和FileNotFoundError 文件不存在 43 | 44 | 45 | 46 | 如何处理异常,通常是用try except来解决 47 | ```python 48 | try: 49 | s = input('please enter two numbers separated by comma: ') 50 | num1 = int(s.split(',')[0].strip()) 51 | num2 = int(s.split(',')[1].strip()) 52 | ... 53 | except ValueError as err: 54 | print('Value Error: {}'.format(err)) 55 | 56 | print('continue') 57 | 58 | ``` 59 | 60 | 如果我们输入a,b,程序便会抛出异常invalid literal for int() with base 10:'a' 61 | 62 | ```python 63 | please enter two numbers separated by comma: a,b 64 | Value Error: invalid literal for int() with base 10: 'a' 65 | continue 66 | ``` 67 | 68 | 大型社交网站的后台,需要针对用户发送的请求返回相应记录。用户记录往往储存在 key-value 结构的数据库中,每次有请求过来后,我们拿到用户的 ID,并用 ID 查询数据库中此人的记录,就能返回相应的结果。而数据库返回的原始数据,往往是 json string 的形式,这就需要我们首先对 json string 进行 decode(解码),你可能很容易想到下面的方法: 69 | 70 | 71 | 72 | ```python 73 | import json 74 | raw_data = queryDB(uid) # 根据用户的 id,返回相应的信息 75 | data = json.loads(raw_data) 76 | 77 | ``` 78 | 上面的代码是不是就足够呢? 79 | 80 | json.loads()函数中,如果输入的字符串不符合规范,那么就无法解码,就会抛出异常 81 | 82 | 83 | 因此写之前就应该考虑如何处理异常 84 | 85 | ```python 86 | try: 87 | data = json.loads(raw_data) 88 | .... 89 | except JSONDecodeError as err: 90 | print('JSONDecodeError: {}'.format(err)) 91 | 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /11-20/18、深入Python函数.md: -------------------------------------------------------------------------------- 1 | @Author :By Runsen 2 | 3 | 4 | @[TOC] 5 | # 函数 6 | 7 | 在Python中的函数就是为了实现某一段功能的代码段,可以重复利用。 8 | 9 | 就是以后不要重复造轮子,遇到那个场景就用那个函数,就是函数式编程 10 | 11 | 12 | 下面,我定义一个 my_func,传入一个Hello World,再打印一个Hello World 13 | ```python 14 | def my_func(message): 15 | print('Got a message: {}'.format(message)) 16 | 17 | # 调用函数 my_func() 18 | my_func('Hello World') 19 | # 输出 20 | Got a message: Hello World 21 | ``` 22 | 23 | 简单的知识点 24 | 25 | 26 | - def是函数的声明 27 | - my_func是函数的名称 28 | - message 是函数的参数 29 | - print 是函数的主体部分 30 | - 在函数的最后 可以返回调用结果(return 或yield ),也可以不返回 31 | 32 | 33 | 34 | 35 | 定义在前,调用在后 36 | 37 | 38 | ```python 39 | def my_sum(a, b): 40 | return a + b 41 | 42 | result = my_sum(3, 5) 43 | print(result) 44 | 45 | # 输出 46 | 8 47 | 48 | ``` 49 | 50 | 51 | 52 | 对于函数的参数可以设定默认值 53 | 54 | ```python 55 | def func(param = 0): 56 | ... 57 | 58 | ``` 59 | 如果param没有传入,那么参数默认是0,如果传入了参数,就覆盖默认值 60 | 61 | # 多态 62 | 63 | 64 | 传入的参数可以接受任何数据类型 65 | 66 | 67 | 比如,列表 68 | ```python 69 | print(my_sum([1, 2], [3, 4])) 70 | 71 | # 输出 72 | [1, 2, 3, 4] 73 | 74 | ``` 75 | 再比如,字符串 76 | ```python 77 | print(my_sum('hello ', 'world')) 78 | 79 | # 输出 80 | hello world 81 | 82 | ``` 83 | 当然,如果参数数据类型不同,而两者无法相加 84 | 85 | ``` 86 | print(my_sum([1, 2], 'hello')) 87 | TypeError: can only concatenate list (not "str") to list 88 | 89 | ``` 90 | 91 | 同一个函数可以应用到整数,列表,字符串等等的操作称为`多态`。这可不是变态。 92 | 93 | 94 | 95 | 96 | 97 | # 函数嵌套 98 | 99 | 函数嵌套就是函数中有函数,就叫嵌套函数了。 100 | 101 | 102 | ```python 103 | def f1(): 104 | print('hello') 105 | def f2(): 106 | print('world') 107 | f2() 108 | f1() 109 | 110 | # 输出 111 | hello 112 | world 113 | 114 | ``` 115 | 116 | 117 | 函数的嵌套保证了内部函数的调用,内部函数只能被外部函数所调用,不会作用于全局域中。 118 | 119 | 120 | 121 | 122 | 合理使用函数嵌套,提高运算速度 123 | 124 | 比如计算5的阶乘。 125 | 126 | ```python 127 | def factorial(input): 128 | 129 | if not isinstance(input, int): 130 | raise Exception('input must be an integer.') 131 | if input < 0: 132 | raise Exception('input must be greater or equal to 0' ) 133 | 134 | def inner_factorial(input): 135 | if input <= 1: 136 | return 1 137 | return input * inner_factorial(input-1) 138 | return inner_factorial(input) 139 | 140 | 141 | print(factorial(5)) 142 | 143 | 120 144 | 145 | ``` 146 | # 函数变量作用域 147 | 148 | 149 | 如果变量是izai函数内部定义的,称为局部变量,只在函数内部有效,当函数执行完毕,局部变量就会被回收。 150 | 151 | 152 | 全局变量就是写在函数外面的。 153 | 154 | ```python 155 | MIN_VALUE = 1 156 | MAX_VALUE = 10 157 | def validation_check(value): 158 | if value < MIN_VALUE or value > MAX_VALUE: 159 | raise Exception('validation check fails') 160 | 161 | ``` 162 | 这里的MIN_VELUE 和MAX_VALUE就是全局变量,但是我们不能在函数的内部随意改变全局变量的值 163 | 164 | ```python 165 | MIN_VALUE = 1 166 | MAX_VALUE = 10 167 | def validation_check(value): 168 | ... 169 | MIN_VALUE += 1 170 | ... 171 | validation_check(5) 172 | UnboundLocalError: local variable 'MIN_VALUE' referenced before assignment 173 | 174 | ``` 175 | 176 | 177 | 要想改变 必须加上global这个声明 178 | 179 | 180 | ```python 181 | MIN_VALUE = 1 182 | MAX_VALUE = 10 183 | def validation_check(value): 184 | global MIN_VALUE 185 | ... 186 | MIN_VALUE += 1 187 | ... 188 | validation_check(5) 189 | 190 | ``` 191 | global告诉python解析器,函数内部的变量MIN_VALUE就是定义的全局变量,这里输入的是2,这样修改的全局变量的值 192 | 193 | ```python 194 | MIN_VALUE = 1 195 | MAX_VALUE = 10 196 | def validation_check(value): 197 | MIN_VALUE = 3 198 | ... 199 | 200 | ``` 201 | 202 | 203 | ```python 204 | MIN_VALUE = 1 205 | MAX_VALUE = 10 206 | def validation_check(): 207 | MIN_VALUE = 3 208 | print(MIN_VALUE) 209 | validation_check() 210 | print(MIN_VALUE) 211 | 212 | 213 | # 3 214 | # 1 215 | ``` 216 | 217 | 对于嵌套函数来说,内部函数无法修改外部函数定义的变量,可以访问,想要修改就要加上 nonolocal 218 | 219 | ```python 220 | def outer(): 221 | x = "local" 222 | def inner(): 223 | nonlocal x # nonlocal 关键字表示这里的 x 就是外部函数 outer 定义的变量 x 224 | x = 'nonlocal' 225 | print("inner:", x) 226 | inner() 227 | print("outer:", x) 228 | outer() 229 | # 输出 230 | inner: nonlocal 231 | outer: nonlocal 232 | 233 | ``` 234 | 235 | 不加就不会覆盖 236 | ```python 237 | def outer(): 238 | x = "local" 239 | def inner(): 240 | x = 'nonlocal' # 这里的 x 是 inner 这个函数的局部变量 241 | print("inner:", x) 242 | inner() 243 | print("outer:", x) 244 | outer() 245 | # 输出 246 | inner: nonlocal 247 | outer: local 248 | 249 | ``` 250 | # 闭包 251 | 252 | 253 | 闭包就是在函数里面调用函数,一般用return来执行,return出内部调用的函数名。 254 | 255 | 计算一个数的n次幂 256 | ```python 257 | def nth_power(exponent): 258 | def exponent_of(base): 259 | return base ** exponent 260 | return exponent_of # 返回值是 exponent_of 函数 261 | 262 | square = nth_power(2) # 计算一个数的平方 263 | cube = nth_power(3) # 计算一个数的立方 264 | square 265 | # 输出 266 | .exponent(base)> 267 | 268 | cube 269 | # 输出 270 | .exponent(base)> 271 | 272 | print(square(2)) # 计算 2 的平方 273 | print(cube(2)) # 计算 2 的立方 274 | # 输出 275 | 4 # 2^2 276 | 8 # 2^3 277 | 278 | ``` 279 | 280 | -------------------------------------------------------------------------------- /11-20/19、深入Python匿名函数.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | @Author:By Runsen 4 | 5 | @Date:2019年07月13日 6 | 7 | 8 | 9 | 10 | 之前写的,最近决定把之前的回顾,写详细。 11 | 12 | 13 | @[toc] 14 | # 1、匿名函数 15 | 16 | 匿名函数不需要显示地定义函数名,使用【lambda + 参数 +表达式】的方式 17 | 18 | ## 1.1 lambda 函数 19 | lambda 函数的形式 20 | 21 | 22 | 23 | 24 | ```python 25 | lambda argument1, argument2,... argumentN : expression 26 | 27 | ``` 28 | 29 | 套入函数,使用lambda 30 | 31 | ```python 32 | square = lambda x: x**2 33 | square(3) 34 | 35 | 9 36 | 37 | ``` 38 | lambda 返回的一个函数对象 39 | 40 | 41 | 42 | 注意:lambda 和def 的区别 43 | 44 | lambda 是一个表达式,def 是一个语句 45 | 46 | 47 | ```python 48 | [(lambda x: x*x)(x) for x in range(10)] 49 | # 输出 50 | [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 51 | 52 | ``` 53 | lambda 可以用作函数的参数,def 不能 54 | ```python 55 | l = [(1, 20), (3, 0), (9, 10), (2, -1)] 56 | l.sort(key=lambda x: x[1]) # 按列表中元祖的第二个元素排序 57 | print(l) 58 | # 输出 59 | [(2, -1), (3, 0), (9, 10), (1, 20)] 60 | 61 | ``` 62 | 63 | 64 | lambda 是只有一行的简单表达式 65 | 66 | ```python 67 | squared = map(lambda x: x**2, [1, 2, 3, 4, 5]) 68 | 69 | ``` 70 | 如果不用lambda ,你用def就需要多写好多行 71 | ```python 72 | def square(x): 73 | return x**2 74 | 75 | squared = map(square, [1, 2, 3, 4, 5]) 76 | 77 | ``` 78 | 79 | 在tkinter 中实现的简单功能 80 | 81 | ```python 82 | from tkinter import Button, mainloop 83 | button = Button( 84 | text='This is a button', 85 | command=lambda: print('being pressed')) # 点击时调用 lambda 函数 86 | button.pack() 87 | mainloop() 88 | 89 | ``` 90 | ![](https://img-blog.csdnimg.cn/20190602104359313.png) 91 | 92 | 主要你按压就出现being pressed 93 | 94 | 95 | 你用def就是下面的样子 96 | 97 | ```python 98 | from tkinter import Button, mainloop 99 | 100 | def print_message(): 101 | print('being pressed') 102 | 103 | button = Button( 104 | text='This is a button', 105 | command=print_message) # 点击时调用 lambda 函数 106 | button.pack() 107 | mainloop() 108 | 109 | ``` 110 | 使用def 要写好多行,多定义一个函数 111 | 112 | 113 | 114 | 115 | ## 1.2 函数式编程 116 | 117 | 函数式编程是指代码每一块都是不可变的,都是由纯函数的组成 118 | 119 | 120 | 这里的纯函数 值函数本身相互独立,对于相同的输入都有相同的输出 121 | 122 | 123 | 传入一个列表将列表的元素变为原来的2倍 124 | ```python 125 | def multiply_2(l): 126 | for index in range(0, len(l)): 127 | l[index] *= 2 128 | return l 129 | 130 | ``` 131 | 这段代码不是纯函数的形式,因为我多次调用,每次得到的结果不一样 132 | 133 | ```python 134 | def multiply_2_pure(l): 135 | new_list = [] 136 | for item in l: 137 | new_list.append(item * 2) 138 | return new_list 139 | 140 | ``` 141 | 纯函数的形式,应该在函数里面定义一个新的列表 142 | 143 | 144 | 145 | 146 | # 2、其他函数 147 | 148 | 149 | 对于纯函数python 提供了几个函数 150 | 151 | 152 | 153 | ## 2.1 map 154 | 155 | 156 | map 函数的形式 157 | 158 | ```python 159 | ( function ,iterable ) 160 | ``` 161 | 第一个参数是函数的对象,第二个是一个可迭代对象 162 | 163 | 164 | 165 | 166 | 167 | 168 | ```python 169 | l = [1, 2, 3, 4, 5] 170 | new_list = map(lambda x: x * 2, l) 171 | list(new_list) 172 | # [2, 4, 6, 8, 10] 173 | ``` 174 | 175 | ## 2.2 filter 176 | 177 | 178 | filter通常对一个集合做g过滤的操作 179 | 180 | ```python 181 | l = [1, 2, 3, 4, 5] 182 | new_list = filter(lambda x: x % 2 == 0, l) 183 | list(new_list) 184 | # [2, 4] 185 | ``` 186 | 187 | ## 2.3 reduce 188 | 189 | reduce通常对一个集合做累积的操作 190 | 191 | ```python 192 | import functools 193 | 194 | l = [1, 2, 3, 4, 5] 195 | product = functools.reduce(lambda x, y: x * y, l) 196 | product 197 | # 1*2*3*4*5 = 120 198 | ``` 199 | 200 | 201 | # 3、思考题 202 | 203 | 204 | 205 | ## 3.1 如何根据值来排序 206 | ```python 207 | d = {'mike': 10, 'lucy': 2, 'ben': 30} 208 | 209 | 210 | sorted(d.items(),key=lambda x:x[1],reverse=True) 211 | ``` 212 | 213 | 注意 reduce在3中已经放进functools模块中了 214 | ```python 215 | >>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) 216 | 217 | >>> filter(lambda x: x % 2 ==0, [1,2,3,4,5]) 218 | 219 | >>> reduce(lambda x,y: x*y,[1,2,3,4,5]) 220 | Traceback (most recent call last): 221 | File "", line 1, in 222 | NameError: name 'reduce' is not defined 223 | >>> from functools import reduce 224 | >>> reduce(lambda x,y: x*y,[1,2,3,4,5]) 225 | 120 226 | map,filter返回的只是一个对象,reduce在3中已经放进fucntools模块中了 227 | ``` 228 | 229 | -------------------------------------------------------------------------------- /21-30/22、上篇 _ Python的进程和线程.md: -------------------------------------------------------------------------------- 1 |  2 | @Author: Runsen 3 | 4 | 5 | 以前的文章 6 | 7 | @[TOC] 8 | 9 | 10 | # 进程和线程 11 | 12 | 我们打开我们的计算机就会看到进程和线程 13 | 14 | 15 | ![](https://img-blog.csdnimg.cn/20190409220332456.png) 16 | 17 | 18 | 那什么是进程什么是线程 19 | 20 | 我的理解是进程是指在系统中正在运行的一个应用程序;程序一旦运行就是进程,或者更专业化来说:进程是指程序执行时的一个实例。 21 | 22 | 线程是进程的一个实体。 23 | 24 | 进程——资源分配的最小单位,线程——程序执行的最小单位。 25 | 26 | 27 | 28 | 我举个例子,**比如打开qq,就是一个线程,有很多个qq上号就是进程** 29 | 30 | 31 | # python线程和进程的使用 32 | 33 | 现在讲python线程和进程的使用 34 | 35 | 36 | ![](https://img-blog.csdnimg.cn/20190409220401431.png) 37 | 38 | 39 | 在Python中线程和进程的使用就是通过Thread这个类。这个类在我们的_thread和threading模块中。 40 | 41 | ![](https://img-blog.csdnimg.cn/201904092204568.png) 42 | 43 | 44 | 我们看一个标准的多线程的例子。 45 | 46 | 47 | ![](https://img-blog.csdnimg.cn/2019040922060320.png) 48 | 49 | 50 | 51 | # 练习 52 | 53 | 下面我们来练习下, 加深hreading模块的使用。 54 | 55 | 56 | 我写了下面的代码 57 | 58 | ```python 59 | # -*- coding:utf-8 -*- 60 | # time :2019/4/9 21:52 61 | # author: Runsen 62 | import threading 63 | import time 64 | def fun1(): 65 | print('hello') 66 | time.sleep(2) 67 | print('Bye') 68 | def fun2(): 69 | print('hi') 70 | time.sleep(2) 71 | print('OUT') 72 | t1 = threading.Thread(target=fun1) 73 | t2 = threading.Thread(target=fun2) 74 | t1.start() 75 | t2.start() 76 | # t1.join() 77 | # t2.join() 78 | print('主线程完毕') 79 | ``` 80 | 81 | 我们先不加join()来阻塞,t1和t2两个线程同时执行,由于位置先打印hello,再打印hi,这个时候都sleep2秒钟,但是他sleep2秒钟,主程序还是在执行,所以下面打印print('主线程完毕'),最后才打印Bye和OUT 82 | 83 | ``` 84 | hello 85 | hi 86 | 主线程完毕 87 | Bye 88 | OUT 89 | ``` 90 | 91 | 92 | # 线程间变量的共享 93 | 94 | ![](https://img-blog.csdnimg.cn/20190409221959273.png) 95 | 96 | 97 | 98 | 99 | 100 | ![](https://img-blog.csdnimg.cn/20190409222051749.png) 101 | 102 | 103 | 代码如上图所示,打印的a是1还是2, 104 | 105 | 答案是 :2。因为出现了global,线程间变量的共享,在func中的a是全局变量。 106 | 107 | 108 | 109 | 下面,我们提高一点点难度,代码如下图所示,还是猜一猜a是啥东西。注意:这里出现了join来阻塞来增加了加和减的操作。 110 | 111 | 112 | 113 | 114 | 115 | ![](https://img-blog.csdnimg.cn/20190409222525518.png) 116 | 117 | 118 | 相信很多人都认为是0,其实这个a的值是变化的,可能这次是0 ,下次是1,还有可能是1000000,a就是在[-1000000,1000000]中的一个随机数。 119 | 120 | 121 | 122 | 为什么呢?这是因为虽然他们是同时运行的,但是同时在修改我们的a,那就乱了。这是导致a,for i in range(1000000),就是遍历了1000000,incr和decr的方法都加上一起了,在这1000000次遍历中,不知道有多少加,多少减,比如,我1000000都是加,没有减,a就是1000000。 123 | 124 | 125 | 126 | 127 | 128 | 129 | 如果你就是想出现0,其实加一个互斥锁就可以了。这样你加多少次,我就减多少次,加减的次数不会叠加。因此来了lock的用法。 130 | 131 | 132 | 133 | ![](https://img-blog.csdnimg.cn/20190409222743790.png) 134 | 135 | 这个a怎么运行都是 0。因为我们把这个a锁上了,这样就加1000000次,减1000000次,怎么出来都是我们的0。 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /21-30/23、下篇 _ Python线程和进程.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | @Author:Runsen 4 | 5 | @[TOC] 6 | 7 | # 队列 8 | 9 | 上文锁能解决问题,但是不常见 10 | 11 | ![](https://img-blog.csdnimg.cn/20190409223407931.png) 12 | 13 | 导入: 14 | 15 | `from queue import Queue` 16 | 17 | 18 | ``` 19 | from queue import Queue 20 | from threading import Thread 21 | from random import randint 22 | my_queue = Queue(3) 23 | def f1(my_queus): 24 | for i in range(3): 25 | num = randint(0,10) 26 | print(num) 27 | my_queue.put(num) 28 | def f2(my_queus): 29 | for i in range(3): 30 | num = my_queue.get() 31 | print(num) 32 | t1 = Thread(target=f1,args=(my_queue,)) 33 | t2 = Thread(target=f2,args=(my_queue,)) 34 | t1.start() 35 | t2.start() 36 | t1.join() 37 | t2.join() 38 | ``` 39 | 40 | 41 | 42 | 0 43 | 5 44 | 10 45 | 0 46 | 5 47 | 10、 48 | 49 | 50 | ![](https://img-blog.csdnimg.cn/20190409224419329.png) 51 | 52 | 53 | # 线程池 54 | 55 | ![](https://img-blog.csdnimg.cn/20190409224540227.png) 56 | 57 | ``` 58 | from multiprocessing.pool import ThreadPool 59 | import time 60 | def hello(name): 61 | print('hello,{}'.format(name)) 62 | time.sleep(2) 63 | print('Bye') 64 | t = ThreadPool(3) 65 | for i in range(3): 66 | t.apply_async(hello,args=(i,)) 67 | t.close() 68 | t.join() 69 | ``` 70 | OUT: 71 | 几乎一起完成 72 | hello,0 73 | hello,1 74 | hello,2 75 | 几乎一起完成 76 | Bye 77 | Bye 78 | Bye 79 | ![](https://img-blog.csdnimg.cn/2019040922534897.png) 80 | 81 | 对于进程和线程,可以提高爬虫速度 82 | 83 | 84 | # 多线程典型例子 85 | 86 | 87 | 88 | ```python 89 | # -*- coding:utf-8 -*- 90 | # time :2019/4/23 10:13 91 | # author: 毛利 92 | 93 | import threading 94 | import time 95 | import random 96 | MONEY = 0 97 | gLock = threading.Lock() 98 | 99 | def Procuder(): 100 | while True: 101 | global MONEY 102 | random_money = random.randint(10,100) 103 | gLock.acquire() 104 | MONEY += random_money 105 | gLock.release() 106 | print ('生产者%s-生产了%d' % (threading.current_thread,random_money)) 107 | time.sleep(0.5) 108 | 109 | def Customer(): 110 | while True: 111 | global MONEY 112 | random_money = random.randint(10,100) 113 | if MONEY > random_money: 114 | print ('消费者%s-消费了:%d' % (threading.current_thread,random_money)) 115 | gLock.acquire() 116 | MONEY -= random_money 117 | gLock.release() 118 | else: 119 | print ('需要消费的钱为:%d,余额为:%d,' % (random_money,MONEY)) 120 | time.sleep(0.5) 121 | 122 | def p_c_test(): 123 | # 执行3个线程,来当作生产者 124 | for x in range(3): 125 | th = threading.Thread(target=Procuder) 126 | th.start() 127 | # 执行3个线程,来当作消费者 128 | for x in range(3): 129 | th = threading.Thread(target=Customer) 130 | th.start() 131 | 132 | if __name__ == "__main__": 133 | p_c_test() 134 | ``` 135 | ![](https://img-blog.csdnimg.cn/20190424214132327.png) 136 | -------------------------------------------------------------------------------- /21-30/26、Python中的Time和os模块.md: -------------------------------------------------------------------------------- 1 | @Author: Runsen 2 | @[TOC] 3 | 4 | # 日期与时间管理的库 5 | datetime 与time 6 | 7 | 8 | 9 | ```python 10 | import datetime 11 | t = datetime.time(1, 20, 1) 12 | # Lets show the different compoenets # datetime.time(hour,minute,second,microsecond) 13 | print(t) 14 | print('hour :', t.hour) 15 | print('minute:', t.minute) 16 | print('second:', t.second) 17 | print('microsecond:', t.microsecond) 18 | print('tzinfo:', t.tzinfo) 19 | ``` 20 | 21 | 01:20:01 22 | hour : 1 23 | minute: 20 24 | second: 1 25 | microsecond: 0 26 | tzinfo: None 27 | 28 | 29 | 30 | ```python 31 | import time 32 | time.time() #10位 33 | ``` 34 | 35 | 36 | 37 | 38 | 1557212908.1839943 39 | 40 | 41 | 42 | 43 | ```python 44 | print('Earliest :', datetime.time.min) 45 | print('Latest :', datetime.time.max) 46 | print('Resolution:', datetime.time.resolution) 47 | ``` 48 | 49 | Earliest : 00:00:00 50 | Latest : 23:59:59.999999 51 | Resolution: 0:00:00.000001 52 | 53 | 54 | 55 | ```python 56 | today = datetime.date.today() 57 | print(today) 58 | print('ctime:', today.ctime()) 59 | print('tuple:', today.timetuple()) 60 | print('ordinal:', today.toordinal()) 61 | print('Year:', today.year) 62 | print('Mon :', today.month) 63 | print('Day :', today.day) 64 | ``` 65 | 66 | 2019-05-07 67 | ctime: Tue May 7 00:00:00 2019 68 | tuple: time.struct_time(tm_year=2019, tm_mon=5, tm_mday=7, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=127, tm_isdst=-1) 69 | ordinal: 737186 70 | Year: 2019 71 | Mon : 5 72 | Day : 7 73 | 74 | 75 | 76 | ```python 77 | print('Earliest :', datetime.date.min) 78 | print('Latest :', datetime.date.max) 79 | print('Resolution:', datetime.date.resolution) 80 | ``` 81 | 82 | Earliest : 0001-01-01 83 | Latest : 9999-12-31 84 | Resolution: 1 day, 0:00:00 85 | 86 | 87 | 88 | ```python 89 | d1 = datetime.date(2019, 5, 7) 90 | print('d1:', d1) 91 | d2 = d1.replace(year=1990) 92 | print('d2:', d2) 93 | ``` 94 | 95 | d1: 2019-05-07 96 | d2: 1990-05-07 97 | 98 | 99 | # os 操作模块 100 | OS模块简单的来说它是一个Python的系统编程的操作模块,可以处理文件和目录这些我们日常手动需要做的 操作。 可以查看OS模块的帮助文档: 101 | 102 | import os #导入os模块 103 | help(os) #查看os模块帮助文档,里面详细的模块相关函数和使用方法 104 | 105 | 106 | 107 | # OS模块重要函数和变量: 108 | - os.sep 更改操作系统中的路径分隔符。 109 | - os.getcwd()获取当前路径,这个在Python代码中比较 常用。 110 | - os.listdir() 列出当前目录下的所有文件和文件夹。 111 | - os.remove() 方法可以删除指定 的文件。 112 | - os.system() 方法用来运行shell命令。 113 | - os.chdir() 改变当前目录,到指定目录 中。 114 | 115 | # OS模块函数作用详解 116 | - os.system函数可以运行shello命令,Linux系统中就是终端模拟器中的命令。 也有一些函数可以执行外部 程序,包括execv,它会退出Python解释器,并且将控制权交给被执行的程序。 117 | - os.sep变量主要用于系统路 径中的分隔符。 Windows系统通过是“\”,Linux类系统如Ubuntu的分隔符是“/”,而苹果Mac OS系统中 是“:”。 118 | 119 | - os.sep 可以取代操作系统特定的路径分割符。 120 | - os.name字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它 是'posix'。 121 | - os.getcwd()函数得到当前工作目录,即当前Python脚本工作的目录路径。 122 | - os.getenv()和os.putenv()函数分别用来读取和设置环境变量。 123 | - os.listdir()返回指定目录下的所有文件和目录名。 124 | - os.remove()函数用来删除一个文件。 125 | - os.system()函数用来运行shell命令。 126 | - os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用'\n'而Mac使 用'\r'。 127 | - os.path.split()函数返回一个路径的目录名和文件名。 128 | - os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。 129 | - os.path.existe()函数用来检验给出的路径是否真地存在 130 | 131 | - os.listdir(dirname):列出dirname下的目录和文件 132 | - os.getcwd():获得当前工作目录 133 | - os.curdir:返回但前目录('.') 134 | - os.chdir(dirname):改变工作目录到dirname 135 | # os.path模块 136 | - os.path.isdir(name):判断name是不是一个目录,name不是目录就返回false 137 | - os.path.isfile(name):判断name是不是一个文件,不存在name也返回false 138 | - os.path.exists(name):判断是否存在文件或目录name 139 | - os.path.getsize(name):获得文件大小,如果name是目录返回0L 140 | - os.path.abspath(name):获得绝对路径 141 | - os.path.normpath(path):规范path字符串形式 142 | - os.path.split(name):分割文件名与目录(事实上,如果你完全使用目录,它也会将最后一个目录作为文件 名而分离,同时它不会判断文件或目录是否存在) 143 | - os.path.splitext():分离文件名与扩展名 144 | - os.path.join(path,name):连接目录与文件名或目录 145 | - os.path.basename(path):返回文件名 146 | - os.path.dirname(path):返回文件路径 147 | 148 | 以上就是总结的Python os模块的一些比较重要的内容。 149 | 150 | -------------------------------------------------------------------------------- /21-30/27、Python序列化pickle标准库.md: -------------------------------------------------------------------------------- 1 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS8wZTgyODU5My0zZTk2LTQ3ODctYjE0Yy0xNmRhNzFhYzAwMDUucG5n?x-oss-process=image/format,png) 2 | 3 | 4 | 5 | 6 | @[toc] 7 | 8 | 听过Python序列化pickle标准库吗? 9 | 10 | # 序列化 11 | 12 | 13 | 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。就是将数据结构转化成你看不懂的东西 14 | 15 | 16 | pickle提供四个功能:dumps,dump,loads,load 和json 一样 17 | 18 | 19 | 从小demo入手 20 | 21 | ```python 22 | import pickle 23 | data = [{'a': 'A', 'b': 2, 'c': 2.22}] 24 | # 使用 pickle.dumps() 可以将一个对象转换为二进制字符串(dump string): 25 | data_string = pickle.dumps(data) 26 | print("DATA:") 27 | print(data) 28 | print("PICKLE:") 29 | print(data_string) 30 | ``` 31 | 32 | --- 33 | 34 | 35 | 36 | ```python 37 | DATA: 38 | [{'a': 'A', 'b': 2, 'c': 2.22}] 39 | PICKLE: 40 | b'\x80\x03]q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\x00bq\x04K\x02X\x01\x00\x00\x00cq\x05G@\x01\xc2\x8f\\(\xf5\xc3ua.' 41 | ``` 42 | 43 | 44 | 现在给你这个data_string 你能知道这是啥吗? 45 | 46 | 47 | 虽然 pickle 编码的字符串并不一定可读,但是我们可以用 pickle.loads() 来从这个字符串中恢复原对象中的内容(load string): 48 | 49 | ```python 50 | # pickle.loads() 来从这个字符串中恢复原对象中的内容(load string): 51 | data_from_string = pickle.loads(data_string) 52 | print(data_from_string) 53 | ``` 54 | 55 | 56 | dumps 和loads 相反的作用 57 | 58 | ```python 59 | [{'a': 'A', 'b': 2, 'c': 2.22}] 60 | ``` 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | dumps 可以接受一个可省略的 protocol 参数(默认为 0) 69 | 70 | 71 | 72 | 73 | ```python 74 | data_string_0 = pickle.dumps(data, 0) 75 | print("Pickle 0:", data_string_0) 76 | data_string_1 = pickle.dumps(data, 1) 77 | print("Pickle 1:", data_string_1) 78 | data_string_2 = pickle.dumps(data, 2) 79 | print("Pickle 2:", data_string_2) 80 | # 如果 protocol 参数指定为负数,那么将调用当前的最高级的编码协议进行编码: 81 | print("Pickle -1:", pickle.dumps(data, -1)) 82 | ``` 83 | 84 | 85 | 输出如下 86 | 87 | 88 | ```python 89 | Pickle 0: b'(lp0\n(dp1\nVa\np2\nVA\np3\nsVb\np4\nL2L\nsVc\np5\nL3L\nsa.' 90 | Pickle 1: b']q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\x00bq\x04K\x02X\x01\x00\x00\x00cq\x05K\x03ua.' 91 | Pickle 2: b'\x80\x02]q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\x00bq\x04K\x02X\x01\x00\x00\x00cq\x05K\x03ua.' 92 | Pickle -1: b'\x80\x04\x95\x1c\x00\x00\x00\x00\x00\x00\x00]\x94}\x94(\x8c\x01a\x94\x8c\x01A\x94\x8c\x01b\x94K\x02\x8c\x01c\x94K\x03ua.' 93 | ``` 94 | 95 | 96 | 97 | 从这些格式中恢复对象时,不需要指定所用的协议,pickle.load() 会自动识别: 98 | 99 | ```python 100 | print("Load 1:", pickle.loads(data_string_1)) 101 | print("Load 2:", pickle.loads(data_string_2)) 102 | 103 | OUT: 104 | Load 1: [{'a': 'A', 'b': 2, 'c': 3}] 105 | Load 2: [{'a': 'A', 'b': 2, 'c': 3}] 106 | ``` 107 | 108 | 109 | 110 | 存储和读取 pickle 文件 111 | 112 | 113 | 114 | 115 | ```python 116 | # 存储和读取 pickle 文件 117 | with open('data.pkl', 'wb') as f: 118 | pickle.dump(data, f) 119 | 120 | with open('data.pkl',"rb") as f: 121 | data_from_file = pickle.load(f) 122 | 123 | print(data_from_file) 124 | 125 | # 清理生成的文件: 126 | os.remove('data.pkl') 127 | 128 | OUT: 129 | [{'a': 'A', 'b': 2, 'c': 3}] 130 | ``` 131 | 132 | -------------------------------------------------------------------------------- /21-30/28、Python中的日志处理logging模块.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | 3 | 4 | @[toc] 5 | # 日志 6 | 7 | 日志是一种可以追踪某些软件运行时所发生事件的方法。软件开发人员可以向他们的代码中调用日志记录相关的方法来表明发生了某些事情。一个事件可以用一个可包含可选变量数据的消息来描述。此外,事件也有重要性的概念,这个重要性也可以被称为严重性级(level)。 8 | 9 | ![](https://img-blog.csdnimg.cn/20190418234643545.png) 10 | 11 | 12 | 13 | 14 | 15 | Logging 中几种级别:DEBUG < INFO < WARNING < ERROR < CRITICAL 16 | 17 | 18 | 19 | 20 | ![](https://img-blog.csdnimg.cn/20190418234723863.png) 21 | 22 | 23 | ![](https://img-blog.csdnimg.cn/20190418234754723.png) 24 | 25 | 26 | logging模块是python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件和回滚等; 27 | 可以说,logging模块主要由4部分组成: 28 | 29 | 30 | 31 | - Logger 记录器,提供了应用程序代码能直接使用的接口 32 | - Handler 处理器,将记录器产生的日志记录发送至合适的目的地,或者说将Logger产生的日志传到指定位置 33 | - Filters 过滤器,对输出的日志进行过滤,它可以决定输出哪些日志记录 34 | - Formatter 格式化器,控制日志输出的格式,指明了最终输出中日志记录的布局 35 | 36 | 37 | 38 | 39 | 40 | ![](https://img-blog.csdnimg.cn/20190418234825414.png) 41 | 42 | 43 | # 模块化组件使用 44 | - 创建一个logger(日志处理器)对象 45 | - 定义handler(日志处理器),决定把日志发到哪里 46 | 47 | 48 | ![](https://img-blog.csdnimg.cn/20190418235053974.png) 49 | 50 | 51 | 52 | 53 | - 设置日志级别(level)和输出格式Formatters(日志格式器) 54 | - 把handler添加到对应的logger中去 55 | 56 | 57 | 58 | ![](https://img-blog.csdnimg.cn/20190418235206590.png) 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /21-30/30、Python中的Json解析模块.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | @Author:Runsen 5 | @[toc] 6 | 7 | 8 | # 什么是json 9 | 10 | 11 | JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。 12 | 13 | 14 | 它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。 15 | 16 | # JS对象 17 | ```python 18 | var teacher_1 = { 19 | name: ‘Runsen’, 20 | age: 18, 21 | feature : [‘高’, ‘富’, ‘帅’] 22 | } 23 | ``` 24 | 25 | # JSON字符串 26 | ```python 27 | { 28 | “name”: “Runsen”, 29 | “age”: 18, 30 | “ feature “ : [‘高’, ‘富’, ‘帅’] 31 | } 32 | ``` 33 | # Python字典 34 | ```python 35 | { 36 | ‘name’: ‘Runsen’, 37 | ‘age’: 18 38 | ‘feature’ : [‘高’, ‘富’, ‘帅’] 39 | } 40 | ``` 41 | 注意点: 42 | - 字符串必须用双引号(即:””)来包括 43 | - 值可以是字符串、数字、true、false、null、列表,或字典。 44 | 45 | 46 | 47 | 48 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS8wYjY2OTcxNC02ZDg3LTQyOTItYjBiZC02OWQ4MGVhZTQxNmEucG5n?x-oss-process=image/format,png) 49 | 50 | # Json模块API 51 | 52 | 常用json就知道,json模块提供了四个常用的方法:dumps、dump、loads、load,用于字符串 和 python数据类型间进行转换。 53 | 54 | 55 | - json.dumps(obj) --> 将python数据转化为json 56 | 57 | Indent实现缩进,ensure_ascii 是否用ascii解析 58 | 59 | - json.loads(s) -->将json数据转换为python的数据 60 | 61 | - json.dump(obj, fp) -->转换为json并保存到文件中 62 | 63 | - json.load(fp) --> 从文件中读取json,并转化为python数据 64 | 65 | # Json模块使用 66 | 67 | 68 | ```python 69 | import json 70 | my_dict = {'a':'1','b':'2','c':'3','d':'4'} 71 | print(type(my_dict)) 72 | a = json.dumps(my_dict) 73 | print(a) 74 | print(type(a)) 75 | b=json.loads(a) 76 | print(b) 77 | print(type(b)) 78 | OUT: 79 | 80 | {"a": "1", "b": "2", "c": "3", "d": "4"} 81 | #json的字符串 82 | {'a': '1', 'b': '2', 'c': '3', 'd': '4'} 83 | 84 | —————————— 85 | >>> import json 86 | >>> print (json.dumps('中国')) 87 | "\u4e2d\u56fd" 88 | >>> print(json.dumps('中国', ensure_ascii=False)) 89 | "中国" 90 | —————————— 91 | #json.dump() 和 json.load() 来编码和解码JSON数据,用于处理文件。 92 | 93 | import json 94 | my_dict = {'a':'1','b':'2','c':'3','d':'4'} 95 | json.dump(my_dict,open('a.txt','w')) 96 | print(json.load(open('a.txt','r'))) 97 | OUT: 98 | 会生成一个“a.txt"文件 99 | {'a': '1', 'b': '2', 'c': '3', 'd': '4'} 100 | ``` 101 | 102 | 103 | -------------------------------------------------------------------------------- /31-40/31、Python读写docx文件.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | @Author:Runsen 4 | 5 | 6 | @[toc] 7 | 8 | 9 | # Python读写docx文件 10 | 11 | 12 | Python读写word文档有现成的库可以处理 13 | 14 | `pip install python-docx`安装一下。 15 | https://python-docx.readthedocs.io/en/latest/ 16 | 17 | 学习官网: http://python-docx.readthedocs.org/en/latest/ 18 | 19 | 20 | 21 | ```python 22 | import docx 23 | # 新建,打开,保存文件。 24 | 25 | import docx 26 | #新建文档 27 | doc_new = docx.Document() 28 | # 保存文档 29 | doc_new.save('demo.docx') 30 | #读取文档 31 | doc = docx.Document('demo.docx') 32 | ``` 33 | 34 | **python-docx包含了word文档的相关对象** 35 | - doc.paragraphs #段落 36 | - doc.tables #表格 37 | - doc.sections #节 38 | - doc.styles #样式 39 | - doc.inline_shapes #内置图形 40 | 41 | 42 | ```python 43 | # 插入段落。 44 | 45 | doc.add_paragraph('第一段',style=None) #插入一个段落,文本为“第一段” 46 | #默认是不应用样式,这里也可以不写style参数,或者指定一个段落样式 47 | 48 | doc.add_paragraph('第二段',style='Heading 2') 49 | #这些样式都是word默认带有的样式,可以直接罗列出来有哪些段落样式 50 | print ([s.name for s in doc.styles if s.type==1]) 51 | 52 | ``` 53 | 54 | ['Normal', 'Header', 'Footer', 'Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6', 'Heading 7', 'Heading 8', 'Heading 9', 'No Spacing', 'Title', 'Subtitle', 'List Paragraph', 'Body Text', 'Body Text 2', 'Body Text 3', 'List', 'List 2', 'List 3', 'List Bullet', 'List Bullet 2', 'List Bullet 3', 'List Number', 'List Number 2', 'List Number 3', 'List Continue', 'List Continue 2', 'List Continue 3', 'macro', 'Quote', 'Caption', 'Intense Quote', 'TOC Heading'] 55 | 56 | 57 | 58 | ```python 59 | # 新增样式 60 | from docx.shared import RGBColor #这个是docx的颜色类 61 | #新建文档 62 | #新增样式(第一个参数是样式名称,第二个参数是样式类型:1代表段落;2代表字符;3代表表格) 63 | style = doc.styles.add_style('style name 1', 2) 64 | #设置具体样式(修改样式字体为蓝色,当然还可以修改其他的) 65 | style.font.color.rgb = RGBColor(0x0, 0x0, 0xff) 66 | ``` 67 | 68 | 69 | ```python 70 | # 字符样式 71 | # 插入一个空白段落 72 | p = doc.add_paragraph('') 73 | # 写入 74 | p.add_run('毛利1', style="Heading 1 Char") 75 | p.add_run('毛利2') 76 | p.add_run('毛利3', style="Heading 2 Char") 77 | #这样一个段落就应用了两个字符样式,中间“毛利”就没应用样式 78 | print(p.text) #输出结果是u'123456789' 也还是连续的 79 | 80 | ``` 81 | 82 | 毛利1毛利2毛利3 83 | 84 | 85 | 86 | ```python 87 | # 设置字体 88 | r = p.add_run('毛利4') 89 | r.font.bold = True #加粗 90 | r.font.italic = True #倾斜 91 | ``` 92 | 93 | 94 | ```python 95 | # 表格操作 96 | 97 | #新建一个2x3的表格,style可以不写 98 | table=doc.add_table(rows=2,cols=3,style=None) 99 | #可以用table 的rows和columns得到这个表格的行数和列数 100 | print (len(table.rows)) 101 | print (len(table.columns)) 102 | #遍历表格rows 103 | for index,row in enumerate(table.rows): 104 | row.cells[0].text = '毛利{}'.format(index) 105 | print(row.cells[0].text) 106 | 107 | #新增行或列 108 | table.add_row() 109 | table.add_column(width=1) 110 | ``` 111 | 112 | 2 113 | 3 114 | 毛利0 115 | 毛利1 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | ```python 124 | # 官方例子 125 | from docx import Document 126 | from docx.shared import Inches 127 | 128 | document = Document() 129 | 130 | document.add_heading('Document Title', 0) 131 | # 段落 132 | p = document.add_paragraph('A plain paragraph having some ') 133 | p.add_run('bold').bold = True 134 | p.add_run(' and some ') 135 | p.add_run('italic.').italic = True 136 | # 137 | document.add_heading('Heading, level 1', level=1) 138 | document.add_paragraph('Intense quote', style='Intense Quote') 139 | 140 | document.add_paragraph( 141 | 'first item in unordered list', style='List Bullet' 142 | ) 143 | document.add_paragraph( 144 | 'first item in ordered list', style='List Number' 145 | ) 146 | 147 | # document.add_picture('monty-truth.png', width=Inches(1.25)) 148 | 149 | records = ( 150 | (3, '101', 'Spam'), 151 | (7, '422', 'Eggs'), 152 | (4, '631', 'Spam, spam, eggs, and spam') 153 | ) 154 | 155 | table = document.add_table(rows=1, cols=3) 156 | hdr_cells = table.rows[0].cells 157 | hdr_cells[0].text = 'Qty' 158 | hdr_cells[1].text = 'Id' 159 | hdr_cells[2].text = 'Desc' 160 | for qty, id, desc in records: 161 | row_cells = table.add_row().cells 162 | row_cells[0].text = str(qty) 163 | row_cells[1].text = id 164 | row_cells[2].text = desc 165 | 166 | document.add_page_break() 167 | 168 | document.save('demo1.docx') 169 | ``` 170 | 171 | 172 | 173 | 174 | ![](https://img-blog.csdnimg.cn/20190505223424346.png) 175 | 176 | 177 | 178 | 179 | ![](https://img-blog.csdnimg.cn/20190505223505857.png) 180 | 参考: http://python-docx.readthedocs.org/en/latest/ 181 | 182 | -------------------------------------------------------------------------------- /31-40/32、教你Python制作简单的二维码.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @[toc] 3 | 4 | 5 | 6 | # 安装MyQR 7 | 8 | cmd 窗口中用 pip 命令安装 9 | ``` 10 | pip install MyQR 11 | ``` 12 | 13 | 14 | 这个库提供了两种使用方法,一种是直接使用命令行的方式,另外一种使用import引入 15 | 16 | 先在最原始的IDE上 17 | ``` 18 | from MyQR import myqr 19 | myqr.run('1234567') 20 | ``` 21 | 22 | ![](https://img-blog.csdnimg.cn/20190425123522141.png) 23 | 24 | 在看下源码 25 | ![](https://img-blog.csdnimg.cn/20190425123316449.png) 26 | 27 | 位置参数 28 | 单词:STR 29 | 30 | 可选参数 31 | 版本:int,从1到40 32 | 33 | 级别:str,仅限其中一个(l'、'm'、'q'、'h') 34 | 35 | picutre:str,图像的文件名 36 | 37 | 着色:布尔 38 | 39 | constrast:浮动 40 | 41 | 亮度:浮动 42 | 43 | 保存“name:str”,输出文件名如“example.png” 44 | 45 | save_dir:str,输出目录 46 | 47 | ![](https://img-blog.csdnimg.cn/20190425131139766.png0) 48 | 49 | 50 | ``` 51 | from MyQR import myqr 52 | myqr.run(words='123456',picture='1.jpg',save_name='demo.png',colorized=True) 53 | ``` 54 | 55 | ![](https://img-blog.csdnimg.cn/20190425124718125.png) 56 | 57 | 58 | 59 | # 动图 60 | 61 | ``` 62 | from MyQR import myqr 63 | myqr.run(words='https://www.baidu.com',picture='1.gif',save_name='demo1.gif',colorized=True) 64 | ``` 65 | ![](https://img-blog.csdnimg.cn/20190425125335676.gif) 66 | 67 | 68 | 第二种cmd下的方法 69 | 70 | 参数 71 | ```shell 72 | ''' 73 | myqr Words 74 | [-v {1,2,3,...,40}] 75 | [-l {L,M,Q,H}] 76 | [-n output-filename] 77 | [-d output-directory] 78 | [-p picture_file] 79 | [-c] 80 | [-con contrast] 81 | [-bri brightness] 82 | ''' 83 | ``` 84 | 85 | 86 | -v 参数是控制二维码边长的,范围 1至40,数字越大边长越大; 87 | 88 | -l 控制纠错水平,范围是L、M、Q、H,从左到右依次升高。默认纠错等级是最高级的H。 89 | 90 | -n 控制文件名,格式可以是 .jpg, .png ,.bmp ,.gif ; 91 | 92 | -d 控制位置,控制二维码图片的保存位置。 93 | 94 | -p 参数可以把原二维码和同目录下另一张图片结合形成新的黑白艺术二维码。 95 | 96 | -con 用以调节图片的对比度,1.0 表示原始图片,更小的值表示更低对比度,更大反之。默认为1.0。 97 | 98 | -bri 用来调节图片的亮度,其余用法和取值与 -con 相同。 99 | 100 | 101 | ![](https://img-blog.csdnimg.cn/20190425125634355.png) 102 | 103 | ![](https://img-blog.csdnimg.cn/2019042512570917.png) 104 | 105 | 106 | 107 | ![](https://img-blog.csdnimg.cn/20190425125721429.png) 108 | 109 | 110 | ![](https://img-blog.csdnimg.cn/20190425130043254.png) 111 | 112 | 113 | ![](https://img-blog.csdnimg.cn/2019042513010215.gif) 114 | 115 | ![](https://img-blog.csdnimg.cn/20190425130513425.png) 116 | 117 | 118 | ![](https://img-blog.csdnimg.cn/20190425130523197.png) 119 | 120 | 121 | # 搜索范冰冰 122 | 123 | 124 | ```python 125 | from MyQR import myqr 126 | myqr.run(words='https://www.baidu.com/s?wd=%E8%8C%83%E5%86%B0%E5%86%B0&rsv_spt=1&rsv_iqid=0xa48f245a0000d799&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=12&rsv_sug1=10&rsv_sug7=100&rsv_t=b7 127 | a30UsfuYzvKe8JVKCYqvrCF%2FVdbjT%2B0viM0p7fh8j%2BUKcUaEJF%2FTojpsWfmTDc%2FL5s&rsv_sug2 128 | =0&inputT=3459&rsv_sug4=3459&rsv_sug=1',picture='2.png',save_name='demo1.png',colorized=True) 129 | ``` 130 | 131 | 132 | 133 | ![](https://img-blog.csdnimg.cn/20190425132652811.png) 134 | 135 | 136 | 出现的问题:cannot write mode RGBA as JPEG 137 | 138 | 139 | 原因:RGBA意思是红色,绿色,蓝色,Alpha的色彩空间,Alpha指透明度。而JPG不支持透明度,所以要么丢弃Alpha,要么保存为.png文件 140 | 141 | 142 | ```python 143 | from PIL import Image 144 | image = Image.open('2.jpg') 145 | # image = image.convert("RGB") 146 | image.save("2.png") 147 | ``` 148 | -------------------------------------------------------------------------------- /31-40/33、自从我会了Python中的PIL,发现了其实超级简单.md: -------------------------------------------------------------------------------- 1 | PIL全称是Python Image Library,顾名思义,是用来做图像处理的。 2 | 3 | 4 | @[TOC] 5 | # 了解PIL 6 | 7 | `PIL` (Python Image Library) 已经算是 `Python` 处理图片的标准库了,兼具强大的功能和简洁的` API.` 8 | 但是`PIL`库的更新非常缓慢, 并且它只支持到`python2.7`,不支持`python3` 9 | 10 | 由于PIL库更新太慢了,于是于是一群志愿者在PIL库的基础上创建了一个新的分支版本,命名为`Pillow`. 11 | 12 | `Pillow`目前最新支持到`python3.6`,它的维护和开发十分活跃,兼容PIL库的绝大多数语法,并且增加了许多新的特性,推荐直接使用`Pillow` 13 | 14 | # 概念了解 15 | 16 | 17 | PIL中所涉及的基本概念有如下几个: 18 | - 通道(bands) 19 | - 尺寸(size) 20 | - 坐标系统(coordinate system) 21 | 22 | 23 | 24 | 25 | 通道: 26 | 27 | 每张图片都是由一个或者多个数据通道构成,如果这些通道具有相同的维数和深度,PIL允许将这些通道进行叠加 28 | 29 | 以RGB图像为例,每张图片都是由三个数据通道叠加构成,分别为R 、G 、B。 30 | 31 | 对于灰度图像(没有色彩的图片, RGB色彩分量全部相等),只有一个通道。 32 | 33 | 灰度指的是黑白图像中点的颜色深度,范围一般是0到255, 白色为255,黑色为0 34 | 35 | 图片尺寸(size): 36 | 指的是图片的宽度和高度 37 | 38 | 通过size属性可以获取图片的尺寸,它的返回值是一个元祖,元祖里面有两个值,分别是水平和垂直方向上的像素个数 39 | 40 | 坐标系统: 41 | 42 | PIL使用笛卡尔像素坐标系统,图像的左上角为左边的原点(0,0),这就意味着,x轴的数值是从左到右增长的,y轴的数值是从上到下增长的。 43 | 44 | 在我们处理图像的时候,常常需要去表示一个矩形的图像区域。Pillow中很多方法都需要传入一个表示矩形区域的元祖 45 | 46 | 这个元祖包含四个值,分别表示矩形四条边距离x轴或者y轴的距离。顺序是(左,顶,右,底) 47 | 例如,一个800x600的像素图像表示为(0, 0, 800, 600) 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 我们可以用PIL干嘛呢? 56 | 57 | 第一,可以将两张图片合并在一起 58 | 59 | 60 | # Image.blend(image1,image2,alpha) 61 | 62 | 63 | 64 | 65 | 合成公式为:out=image1(1.0- alpha)+image2alpha 66 | 67 | ```python 68 | from PIL import Image 69 | im1 = Image.open("1.jpg") 70 | im2 = Image.open("2.jpg") 71 | print(im1.mode,im1.size) # RGB (500, 300) 72 | print(im2.mode,im2.size) # RGB (500, 300) 73 | im = Image.blend(im1, im2, 0.5) 74 | im.save('3.jpg') 75 | ``` 76 | 77 | 这是1.jpg 78 | ![](https://img-blog.csdnimg.cn/20190502220733889.jpg) 79 | 这是2.jpg 80 | ![](https://img-blog.csdnimg.cn/20190502220739252.jpg) 81 | 82 | 83 | 这是3.jpg 84 | 85 | 86 | 87 | ![合成后的图片](https://img-blog.csdnimg.cn/2019050222074462.jpg) 88 | 89 | # Composite 90 | 91 | 92 | 当然除了上面的方法还可以使用Composite类 93 | Image.composite(image1,image2, mask) ⇒ image 94 | 复合类使用给定的两张图像及mask图像作为透明度,插值出一张新的图像。变量mask图像的模式可以为“1”,“L”或者“RGBA”。所有图像必须有相同的尺寸。 95 | 96 | 97 | 看一波源码,如下图所示 98 | 99 | 100 | ![](https://img-blog.csdnimg.cn/20190502221303486.png) 101 | 102 | 103 | 一波代码开干 104 | 105 | 106 | ```python 107 | from PIL import Image 108 | im1 = Image.open("1.jpg") 109 | im2 = Image.open("2.jpg") 110 | r,g,b = im1.split() 111 | print(b.mode) 112 | print(im1.mode,im1.size) 113 | print(im2.mode,im2.size) 114 | im = Image.composite(im1,im2,mask=b) 115 | im.save('4.jpg') 116 | ``` 117 | 这是4.jpg 118 | 119 | 120 | 121 | 122 | ![](https://img-blog.csdnimg.cn/20190502222239658.jpg) 123 | 124 | # Filter类 125 | im.filter(filter) ⇒ image 126 | 127 | 128 | 返回一个使用给定滤波器处理过的图像的拷贝。在该模块中,预先定义了很多增强滤波器,可以通过filter()函数使用,预定义滤波器包括: 129 | 130 | - BLUR 131 | - CONTOUR 132 | - DETAIL 133 | - EDGE_ENHANCE 134 | - EDGE_ENHANCE_MORE 135 | - EMBOSS 136 | - FIND_EDGES 137 | - SMOOTH 138 | 139 | 140 | 再看一波源码,如下图所示 141 | 142 | 143 | 144 | ![](https://img-blog.csdnimg.cn/20190502223542859.png) 145 | 146 | 147 | 一波代码开干 148 | 149 | 150 | ```python 151 | from PIL import Image 152 | from PIL import ImageFilter ## 调取ImageFilter 153 | img = Image.open("1.jpg") 154 | blu = img.filter(ImageFilter.BLUR) ##均值滤波 155 | con = img.filter(ImageFilter.CONTOUR) ##找轮廓 156 | edge = img.filter(ImageFilter.FIND_EDGES) ##边缘检测 157 | blu.save('均值滤波.jpg') 158 | con.save('找轮廓.jpg') 159 | edge.save('边缘检测.jpg') 160 | ``` 161 | 162 | 这是均值滤波.jpg 163 | 164 | 165 | 166 | ![](https://img-blog.csdnimg.cn/20190502223351590.jpg) 167 | 168 | 这是找轮廓.jpg 169 | 170 | 171 | 172 | ![](https://img-blog.csdnimg.cn/20190502223356699.jpg) 173 | 174 | 这是边缘检测.jpg 175 | 176 | 177 | 178 | ![](https://img-blog.csdnimg.cn/20190502223400421.jpg) 179 | # PIL所有操作 180 | 181 | 182 | 基本操作 183 | 184 | 原图 185 | ![1.jpg](https://img-blog.csdnimg.cn/20190328222744357.jpg) 186 | 187 | ```python 188 | # 导入模块 189 | from PIL import Image 190 | # 打开图片 191 | image = Image.open('1.jpg') 192 | image.show() 193 | # 新建图片 194 | newImage= Image.new('RGB', (100, 100), 'red') 195 | newImage.save('new.jpg') 196 | # 获得图像尺寸: 197 | w, h = image.size 198 | print('原本图像大小: %sx%s' % (w, h)) 199 | # 缩放到50%: 200 | image.thumbnail((w//2, h//2)) 201 | print('缩放后图片的大小: %sx%s' % (w//2, h//2)) 202 | # 把缩放后的图像用jpeg格式保存: 203 | image.save('2.jpg', 'jpeg') 204 | # 复制图片 205 | image2 = image.copy() 206 | image2.save("3.jpg") 207 | ``` 208 | 剪切 粘贴,合并图像 209 | ```python 210 | # 剪切图片 211 | # 设置要拷贝的区域 212 | box = (0, 0, 100, 100) 213 | image3 = image.crop(box) 214 | image3.save("4.jpg") 215 | # 这个region可以用来后续的操作(region其实就是一个Image对象) 216 | region = image.crop(box) 217 | # 处理复制的矩形选区并粘贴到原图 218 | region = region.transpose(Image.ROTATE_180) 219 | image.paste(region, box) 220 | image.save('5.jpg') 221 | ``` 222 | 223 | 旋转和翻转图像 224 | ```python 225 | # 保持原图像不变。逆时针旋转。 226 | image.rotate(90).save('6.jpg') 227 | # 水平翻转, 228 | image.transpose(Image.FLIP_LEFT_RIGHT).save('7.jpg') 229 | # 垂直翻转 230 | image.transpose(Image.FLIP_TOP_BOTTOM).save('8.jpg') 231 | ``` 232 | 过滤操作 233 | ```python 234 | from PIL import Image, ImageFilter 235 | im = Image.open('1.jpg') 236 | # 高斯模糊 237 | im.filter(ImageFilter.GaussianBlur).save(r'高斯模糊.jpg') 238 | # 普通模糊 239 | im.filter(ImageFilter.BLUR).save(r'普通模糊.jpg') 240 | # 边缘增强 241 | im.filter(ImageFilter.EDGE_ENHANCE).save(r'边缘增强.jpg') 242 | # 找到边缘 243 | im.filter(ImageFilter.FIND_EDGES).save(r'找到边缘.jpg') 244 | # 浮雕 245 | im.filter(ImageFilter.EMBOSS).save(r'浮雕.jpg') 246 | # 轮廓 247 | im.filter(ImageFilter.CONTOUR).save(r'轮廓.jpg') 248 | # 锐化 249 | im.filter(ImageFilter.SHARPEN).save(r'锐化.jpg') 250 | # 平滑 251 | im.filter(ImageFilter.SMOOTH).save(r'平滑.jpg') 252 | # 细节 253 | im.filter(ImageFilter.DETAIL).save(r'细节.jpg') 254 | ``` 255 | 256 | ![](https://img-blog.csdnimg.cn/20190328223500732.jpg) 257 | -------------------------------------------------------------------------------- /31-40/34、使用pytesser3 和pillow完成图形验证码的识别.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | @Author: Runsen 4 | 5 | 6 | @[TOC] 7 | 8 | 9 | 10 | # 灰度化 11 | 12 | 13 | 像素点是最小的图片单元,一张图片由很多像素点构成,一个像素点的颜色是由RGB三个值来表现的,所以一个像素点对应三个颜色向量矩阵,我们对图像的处理就是对这个像素点的操作。 14 | 15 | 图片的灰度化,就是让像素点矩阵中的每一个像素点满足 R=G=B,此时这个值叫做灰度值,白色为0,黑色为255 16 | 灰度转化一般公式为: 17 | 18 | 19 | `R=G=B = 处理前的 RX0.3 + GX0.59 + B*0.11` 20 | 21 | 22 | ``` 23 | from PIL import Image 24 | image = Image.open('code.jpg') 25 | im = image.convert('L') 26 | ``` 27 | 28 | 29 | # 二值化 30 | 31 | 32 | 图像的二值化,就是将图像的像素点矩阵中的每个像素点的灰度值设置为0(黑色)或255(白色),从而实现二值化,将整个图像呈现出明显的只有黑和白的视觉效果。 33 | 34 | 二值化原理是利用设定的一个阈值来判断图像像素是0还是255, 一般小于阈值的像素点变为0, 大于的变成255 35 | 36 | 这个临界灰度值就被称为阈值,阈值的设置很重要,阈值过大或过小都会对图片造成损坏 37 | 38 | 选择阈值的原则是:既要尽可能保存图片信息,又要尽可能减少背景和噪声的干扰 39 | 40 | 41 | 常用阈值选择的方法是: 42 | 43 | 44 | - 灰度平局值法: 取127 (0~255的中数, (0+255)/2 = 127) 45 | 46 | - 平均值法: 47 | 48 | 计算像素点矩阵中的所有像素点的灰度值的平均值avg 49 | 50 | - 迭代法: 51 | 52 | 选择一个近似阈值作为估计值的初始值,然后进行分割图像,根据产生的子图像的特征来选取新的阈值,在利用新的阈值分割图像,经过多次循环,使得错误分割的图像像素点降到最小。 53 | 54 | 55 | # 降噪 56 | 经过了二值化处理,整个图片像素就被分为了两个值0和255. 57 | 58 | 如果一个像素点是图片或者干扰因素的一部分,那么她的灰度值一定是0(黑色),如果一个点是背景,其灰度值应该是255,白色 59 | 60 | 所以对于孤立的噪点,他的周围应该都是白色,或者大多数点都是白色的,所以在判断的时候条件应该放宽,一个点是黑色并且相邻的点为白色的点的个数大于一个固定的值,那么这个点就是噪点。 61 | 62 | 我们根据一个点A的RGB值,与周围的8个点的RBG值比较,设定一个值N(0 170: 104 | pixdata[j,i] = 255 105 | else: 106 | pixdata[j, i] = 0 107 | return image 108 | 109 | def depoint(image): 110 | ''' 111 | 对图片进行降噪 112 | :param image: 113 | :return: 114 | ''' 115 | pixdata = image.load() 116 | w,h = image.size 117 | for y in range(1,h-1): 118 | for x in range(1,w-1): 119 | count = 0 120 | if pixdata[x,y-1] >245: 121 | count =count +1 122 | if pixdata[x,y+1] >245: 123 | count =count +1 124 | if pixdata[x-1,y] >245: 125 | count =count +1 126 | if pixdata[x+1,y] >245: 127 | count =count +1 128 | if pixdata[x-1, y - 1] > 245: 129 | count = count + 1 130 | if pixdata[x+1, y + 1] > 245: 131 | count = count + 1 132 | if pixdata[x - 1, y+1] > 245: 133 | count = count + 1 134 | if pixdata[x + 1, y-1] > 245: 135 | count = count + 1 136 | if count>4: 137 | pixdata[x,y] =255 138 | return image 139 | 140 | if __name__ == '__main__': 141 | image = Image.open('111.jpg') 142 | image = binazing(image) 143 | image = depoint(image) 144 | image.show() 145 | print(image_to_string(image)) 146 | 147 | ####输出结果##### 148 | TBQL 149 | ``` 150 | 151 | 152 | 153 | 154 | 这是111.jpg 155 | 156 | 157 | ![](https://imgconvert.csdnimg.cn/aHR0cDovL3B3ZmdtOWZqby5ia3QuY2xvdWRkbi5jb20vRmotSXZrRE9oTWJkcm9GRy1oT1RET2dCRG1zWg?x-oss-process=image/format,png) 158 | -------------------------------------------------------------------------------- /31-40/35、Python在window平台打包工具pyinstaller.md: -------------------------------------------------------------------------------- 1 | Java 一次编译到处运行,Python没有这么好本事,但是也有一个pyinstaller可以打包exe,在window平台下运行 2 | 3 | 4 | 5 | @[TOC] 6 | 7 | 8 | 9 | # pyinstaller 10 | 11 | 安装`pip install pyinstaller` 12 | 13 | # 参数 14 | 15 | 16 | |参数 |含 义 | 17 | |--|--| 18 | | -F | 只生成一个exe文件 | 19 | | –distpath| 指定生成的exe存放的目录 | 20 | | –workpath | 指定编译中临时文件存放的目录 | 21 | |-i | 创建一个目录包含:exe文件、依赖文件| 22 | | -F | 指定exe图标 | 23 | |-p |指定exe依赖的包、模块 24 | |-d |编译为debug模式,获取运行中的日志信息 25 | |-clean| 清理编译时临时文件 26 | |-c |使用控制台 27 | |-w |使用窗口 28 | |-version-file |添加exe版本信息 29 | 30 | # 计算机小助手例子 31 | 32 | 33 | 在我桌面有demo8.py文件,psutil这个标准库是计算计算机的性能的。 34 | 35 | 36 | ```python 37 | # -*- coding:utf-8 -*- 38 | # time :2019/3/28 22:44 39 | # author: Runsen 40 | print('欢迎您,我是您的计算机小助手') 41 | import psutil as ps 42 | import time 43 | print('本机开机的时间是:{}'.format(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(ps.boot_time())))) 44 | print("-------------------------") 45 | print("CPU部分") 46 | print("-------------------------") 47 | print('本机物理CPU个数:{}个'.format(ps.cpu_count())) 48 | print('本机逻辑CPU个数:{}个'.format(ps.cpu_count(logical=False))) 49 | print("-------------------------") 50 | print('内容部分') 51 | print("-------------------------") 52 | print('本机内存大小为:{}个字节'.format(ps.virtual_memory().total)) 53 | print('本机已用内存大小为:{}个字节'.format(ps.virtual_memory().used)) 54 | print('本机已用内存大小占比为:{}%'.format(ps.virtual_memory().percent)) 55 | input() 56 | ``` 57 | 58 | # 注意点: 59 | 60 | 61 | 一定要在代码最后面加上`input()`,这样打开exe不会一散而过, 62 | 63 | 64 | 65 | ![](https://img-blog.csdnimg.cn/20190328231100468.png) 66 | 67 | 68 | 69 | cd 到代码的目录执行 `pyinstaller -F demo8.py` 70 | 71 | 这样就会生成日记等文件 72 | 73 | ![](https://img-blog.csdnimg.cn/20190328231232777.jpg) 74 | 75 | 76 | 我们找到exe 77 | 78 | ![](https://img-blog.csdnimg.cn/20190328231312320.jpg) 79 | 80 | 双击打开它,这样就显示出电脑的内存占用,说明下电脑的内存和你下载的东西无关,就是看你打开了多少网页和程序。 81 | 82 | 83 | ![](https://img-blog.csdnimg.cn/20190328231336607.jpg) 84 | 85 | 和jar包比起来就是给人家完爆的感觉。 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /31-40/37、下篇 _ tkinter实现一个翻译软件.md: -------------------------------------------------------------------------------- 1 |  2 | @Author : Runsen 3 | 4 | 5 | 下面使用 tkinter实现一个翻译软件,我们用的有道云翻译 6 | 7 | 8 | 我先试下把访问的url搞出来 9 | ![](https://img-blog.csdnimg.cn/2020051618303574.png) 10 | 11 | 12 | ![](https://img-blog.csdnimg.cn/20200516183545919.png) 13 | 你可以查看这些参数,都是请求的参数,这需要进一步找的,不是我不会,是我写过,看下面的文章 14 | 15 | 16 | [JS逆向有道云翻译](https://maoli.blog.csdn.net/article/details/103609133) 17 | 18 | 19 | 20 | 21 | 有道翻译的网址原本不是代码中所展现的,但是这个是有道最原始的`url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'` 22 | 23 | 24 | 25 | 现在的url估计是担心别人爬的多,所以就加了一些不必要的参数。因为是零基础专栏,就用最原始的url。 26 | 27 | 28 | 给出代码吧 29 | 30 | 31 | ```python 32 | # -*- coding:utf-8 -*- 33 | # time :2019/5/2 23:44 34 | # author: 毛利 35 | import requests 36 | from tkinter import * 37 | from tkinter import messagebox 38 | import time 39 | def translation(): 40 | 41 | # 接受用户的信息 42 | content = entry.get() 43 | if content =='': 44 | messagebox.showinfo('提示','请输入要翻译的内容') 45 | else: 46 | # url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule' 47 | url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule' 48 | data ={ 49 | 'i':content, 50 | 'from': 'AUTO', 51 | 'to': 'AUTO', 52 | 'smartresult': 'dict', 53 | 'client': 'fanyideskweb', 54 | # 时间戳 14位 55 | # 'salt': '15568459610827', 56 | # 'sign': '9494fda01d62399b1a3476280a82c990', 57 | # 时间戳13位 58 | # 'ts': '1556845961082', 59 | # 'bv': 'd6c3cd962e29b66abe48fcb8f4dd7f7d', 60 | 'doctype': 'json', 61 | 'version': '2.1', 62 | 'keyfrom': 'fanyi.web', 63 | 'action': 'FY_BY_REALTlME', 64 | } 65 | 66 | result = requests.post(url,data) 67 | tarn = result.json()['translateResult'][0][0]['tgt'] 68 | res.set(tarn) 69 | print(tarn) 70 | 71 | 72 | 73 | # 创建窗口 74 | root = Tk() 75 | 76 | # 窗口标题 77 | 78 | root.title('翻译软件') 79 | 80 | # 窗口大小 小写的x 不是370*100 81 | root.geometry('370x100') 82 | # 窗口位置 83 | root.geometry('+500+300') 84 | # root.geometry('300x100+500+300') 85 | 86 | # 标签控件 font = ('微软雅黑',12) 87 | label = Label(root,text ='输入要翻译的文字') 88 | 89 | # 定位 pack 包 place 位置 90 | label.grid(row=0,column =0) 91 | # fg = 'red' 字体颜色 92 | label1 = Label(root,text ='翻译之后的结果:') 93 | label1.grid(row =1,column= 0) 94 | # 输入控件 95 | entry = Entry(root,font =('微软雅黑',15)) 96 | entry.grid(row=0,column = 1) 97 | # 翻译之后的结果 98 | 99 | res = StringVar() 100 | entry1 = Entry(root,font =('微软雅黑',15),textvariable=res) 101 | entry1.grid(row=1,column = 1) 102 | 103 | # 点击按钮 104 | 105 | button = Button(root,text="翻译",width=10,command = translation) 106 | # sticky 对齐方式 N S E W 107 | button.grid(row=2,column=0,sticky=W) 108 | 109 | button1 = Button(root,text ='退出',width=10,command = root.quit) 110 | button1.grid(row=2,column = 1,sticky=E ) 111 | # 消息循环 112 | root.mainloop() 113 | 114 | ``` 115 | 116 | 117 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/2019050310370113.png) 118 | 119 | 打包 ptyinstaller -F demo.py 120 | -------------------------------------------------------------------------------- /31-40/38、练习、Python判断一个信用卡号是否合理.md: -------------------------------------------------------------------------------- 1 | @Author: Runsen 2 | 3 | 这个一个编程题 4 | 5 | 一个信用卡号必须是13到16位的整数 6 | 7 | 8 | 9 | 1954年,IBM的Hans Luhn提出一种算法,用于验证信用卡号的有效性。 10 | 11 | 这个算法在确定输入的卡号是否正确,或者这张信用卡是否被扫描仪正确扫描方面是非常有用的。 12 | 13 | 14 | 15 | 16 | - **4,指Visa信用卡** 17 | - **5,指Master万事达卡** 18 | - **37,指American Express 国际信用卡** 19 | - **6,指Discover 信用卡** 20 | 21 | 22 | 23 | 遵循这个合法性检测可以生成所有的信用卡号,通常称之为Luhn检测或者Mod 10检测,可以如下描述(为了方便解释,假设卡号4388576018402626: 24 | 25 | 1.从右到左对偶数位数字翻倍。如果对某个数字翻倍之后的结果是一个两位数,那么就将这两位加在一起得到一位数。 26 | 27 | 28 | ![](https://img-blog.csdnimg.cn/20200330100745345.png) 29 | 30 | 2.现在将第一步得到的所有一位数相加。 31 | 32 | 33 | 34 | ![](https://img-blog.csdnimg.cn/20200330100753832.png) 35 | 36 | 3.将卡号里从右到左奇数位上的所有数字相加。 37 | 38 | 39 | ![](https://img-blog.csdnimg.cn/20200330100806932.png) 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 4.将第二步和第三步得到的结果相加。 48 | 49 | 50 | 51 | 52 | ![](https://img-blog.csdnimg.cn/20200330100818162.png) 53 | 54 | 55 | 56 | 57 | 5.如果第四步得到的结果能被10整除,那么卡号是合法的;否则,卡号是不合法的。 58 | 59 | ![](https://img-blog.csdnimg.cn/20200330100831819.png) 60 | 61 | 例如,号码4388576018402626是不合法的,但是号码4388576018410707是合法的。 62 | 编写程序,提示用户输入一个long型整数的信用卡号码,显示这个数字是合法的还是非法的 63 | 64 | 65 | ![](https://img-blog.csdnimg.cn/20200330100841306.png) 66 | 67 | 68 | ## 代码 69 | 70 | ```python 71 | def isValid(number): 72 | # 判断是不是合法,就是计算出第四步的结果,如果整除就是合法,我们取模就可以了 73 | if sumOf0ddPlace(number) % 10 == 0: 74 | print("信用卡号的合法") 75 | else: 76 | print("信用卡号的不合法") 77 | 78 | def sumOfDoubleEvenPlace(number): 79 | # 现在将第一步得到的所有一位数相加。这里的number传入的是int类型 80 | sum = 0 81 | for i in str(number)[::2]: 82 | if int(i)*2 <10: 83 | sum = sum + int(i)*2 84 | else: 85 | for j in str(int(i)*2): 86 | sum = sum + int(j) 87 | return sum 88 | 89 | def getDigit(number): 90 | return sum([int(i) for i in str(number)[1::2]]) 91 | 92 | def sumOf0ddPlace(number): 93 | return sumOfDoubleEvenPlace(number) + getDigit(number) 94 | 95 | 96 | 97 | number = input("用户输入一个的信用卡号码,必须是13到16位的整数") 98 | isValid(number) 99 | 100 | # 验证 101 | 用户输入一个的信用卡号码,必须是13到16位的整数4388576018402626 102 | 信用卡号的不合法 103 | 用户输入一个的信用卡号码,必须是13到16位的整数4388576018410707 104 | 信用卡号的合法 105 | ``` 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | # 补充 114 | 115 | 添加 prefixMatched,判断卡号的前缀是否合法。 116 | 117 | 118 | 4,指visa卡 119 | 5,指master卡 120 | 37,指American Express卡 121 | 6,指Discovery卡 122 | 123 | 124 | 125 | ```css 126 | def prefixMatched(number): 127 | if number[0] == '4' or number[0] == '5' or number[0] == '37': 128 | print("信用卡前缀的合法") 129 | elif number[:2] == '37': 130 | print("信用卡前缀的合法") 131 | else: 132 | print("信用卡前缀的不合法") 133 | ``` 134 | 135 | 136 | 137 | 138 | 139 | 函数6:def getSize(d): 获得信用卡号的长度并将结果返回 140 | 141 | ```css 142 | def getSize(d): 143 | return number[:d] 144 | ``` 145 | 146 | 147 | 148 | 函数7:def getPrefix(number, k): 获得信用卡号的第k位''' 149 | 150 | 151 | ```css 152 | def getPrefix(number, k): 153 | return number[k] 154 | ``` 155 | 156 | -------------------------------------------------------------------------------- /31-40/39、Python对象的深浅拷贝,练习冒泡排序.md: -------------------------------------------------------------------------------- 1 |  2 | @Author:By Runsen 3 | 4 | 5 | 6 | @[toc] 7 | 8 | 9 | # 对象的深浅拷贝 10 | 11 | 在Python有个重要的东西,就是对象的深浅拷贝。 12 | 13 | 我们就称为:'==' vs 'is' 14 | 15 | 16 | 17 | 18 | 19 | 20 | - == 比较对象之间的值是否相等 21 | - is 比较的是对象身份是否相等,它们是否同一个对象 22 | 23 | 24 | 我们一般通过id来是否相等来判断是否同一个对象 25 | 26 | ```python 27 | a = 10 28 | b = 10 29 | 30 | a == b 31 | True 32 | 33 | id(a) 34 | 4427562448 35 | 36 | id(b) 37 | 4427562448 38 | 39 | a is b 40 | True 41 | 42 | ``` 43 | 44 | 45 | 注意a is b == True 只适合和用于-5 到256之间,这个不知道你是否知道,我觉得面试官肯定不知道。 46 | 47 | ```python 48 | a = 257 49 | b = 257 50 | 51 | a == b 52 | True 53 | 54 | id(a) 55 | 4473417552 56 | 57 | id(b) 58 | 4473417584 59 | 60 | a is b 61 | False 62 | 63 | ``` 64 | 65 | 下面我们说下,浅拷贝和深拷贝 66 | 67 | 68 | ```python 69 | l1 = [1, 2, 3] 70 | l2 = list(l1) 71 | 72 | l2 73 | [1, 2, 3] 74 | 75 | l1 == l2 76 | True 77 | 78 | l1 is l2 79 | False 80 | 81 | s1 = set([1, 2, 3]) 82 | s2 = set(s1) 83 | 84 | s2 85 | {1, 2, 3} 86 | 87 | s1 == s2 88 | True 89 | 90 | s1 is s2 91 | False 92 | 93 | ``` 94 | 浅拷贝指重新分配一块内存,l2 就是l1的浅拷贝,但是只要是序列的浅拷贝,他们的id就是不一样的。 95 | 96 | 97 | 98 | 99 | 对于深拷贝,在python中提供了对应的函数copy.copy() 100 | 101 | ```python 102 | import copy 103 | l1 = [1, 2, 3] 104 | l2 = copy.copy(l1) 105 | 106 | t1 = (1, 2, 3) 107 | t2 = tuple(t1) 108 | 109 | t1 == t2 110 | True 111 | 112 | t1 is t2 113 | True 114 | 115 | ``` 116 | 元组(1,2,3)只被创建一次,t1和t2同时指向这个元组,反正你看到copy.copy()就是两个True 117 | 118 | 119 | 120 | 121 | 这里有一个天天来骗小孩的东西,就是l1变了,l2变不变的问题 122 | 123 | 124 | 我这里在使用的嵌套列表 125 | 126 | 127 | ```python 128 | l1 = [[1, 2], (30, 40)] 129 | l2 = list(l1) 130 | 131 | l2 132 | [[1, 2], (30, 40)] 133 | 134 | l1.append(100) 135 | l1[0].append(3) 136 | 137 | l1 138 | [[1, 2, 3], (30, 40), 100] 139 | 140 | l2 141 | [[1, 2, 3], (30, 40)] 142 | ``` 143 | 144 | 145 | l2竟然变了,这是为什么。首先初始化一个列表l1,里面的元素是一个列表和元组,然后对l1执行浅拷贝,赋予了l2 146 | ,但是l2中的元素和l1指向同一个列表和元组对象,只有列表对象变,你浅拷贝就要跟着我变。 147 | 148 | 如果你添加一个序列来,我浅拷贝没有指向你新来的对象。我干嘛跟着你变。 149 | 150 | l1.append(100)l1的列表新增元素100,不会对l2产生影响,l1和l2是两个不同的对象 151 | 152 | 153 | 154 | **如果我在元组加呢???** 155 | ```python 156 | 157 | l1[1] += (50, 60) 158 | 159 | l1 160 | [[1, 2, 3], (30, 40, 50, 60), 100] 161 | 162 | l2 163 | [[1, 2, 3], (30, 40)] 164 | 165 | ``` 166 | 167 | 竟然不会变,说白了只有列表对象变,难道元组不可变你不知道? 168 | 169 | 170 | 171 | 172 | 173 | 174 | 深度拷贝,就是你爱怎么变,就去哪里变,我就不变了。 175 | 176 | 177 | 178 | ```python 179 | import copy 180 | l1 = [[1, 2], (30, 40)] 181 | l2 = copy.deepcopy(l1) 182 | l1.append(100) 183 | l1[0].append(3) 184 | 185 | l1 186 | [[1, 2, 3], (30, 40), 100] 187 | 188 | l2 189 | [[1, 2], (30, 40)] 190 | 191 | ``` 192 | 193 | 因为此时l1和l2完全独立了,没有任何影响 194 | 195 | 总结起来其实就是两句话 196 | 197 | - 浅拷贝,不可变的不可变,可变的依旧可变 198 | - 深拷贝,都不可变 199 | 200 | 201 | 202 | 203 | 下面我们练习下冒泡排序 204 | # 冒泡排序 205 | 要学习冒泡排序必须知道它的原理: 206 | 207 | 所谓冒泡,就是将元素两两之间进行比较,谁大就往后移动,直到将最大的元素排到最后面,接着再循环一趟,从头开始进行两两比较,而上一趟已经排好的那个元素就不用进行比较了。(图中排好序的元素标记为黄色柱子) 208 | 209 | 说得不清楚,我们看看下面的动图就应该明白了 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 下面,我们就进入代码环节。 218 | 219 | ![](https://img-blog.csdnimg.cn/20200710225406469.png) 220 | 221 | Python实现冒泡排序 222 | 现在,我给你一个nums = [3,1,25,6,8,10,15],要求你用Python将nums实现冒泡排序。 223 | 224 | 看上去很难入手,其实很简单,我先给出代码 225 | 226 | ```csharp 227 | nums = [3,1,25,6,8,10,15] 228 | for i in range(len(nums)-1): 229 | for j in range(len(nums) - i -1): 230 | if nums[j] > nums[j+1]: 231 | nums[j],nums[j+1] = nums[j+1],nums[j] 232 | print("第"+str(j)+"次内循环"+str(nums)) 233 | print("第"+str(i)+"次外循环"+str(nums)) 234 | print("最后的结果"+str(nums)) 235 | ``` 236 | 237 | 我们先遍历nums,这不就是我们的range(len(nums)-1),至于为什么是range(len(nums)-1),其实就是我们的下标从0开始的,len(nums)返回是7,range是左开右闭,但是冒泡排序,我们只需要取到nums[5] = 10 就足够了,所以这里range(len(nums)-1),取到[3,1,25,6,8,10]。 238 | 239 | 然后,我们在遍历之后的nums,比如i = 0,我们将j取值范围到len(nums) - i -1,用nums[j] > nums[j+1]判断两两的大小, 每次内循环将最大的移到最右边。 240 | 241 | 每一次内循环的目的就是将当中最大的移到最右边,而每一次外循环的目的就是当最大的移到最右边后,缩小范围,再寻找最大的数,再把它移到最右边。 242 | 243 | 我们执行上面的代码的结果如下: 244 | ```python 245 | 第0次内循环[1, 3, 25, 6, 8, 10, 15] 246 | 第1次内循环[1, 3, 25, 6, 8, 10, 15] 247 | 第2次内循环[1, 3, 6, 25, 8, 10, 15] 248 | 第3次内循环[1, 3, 6, 8, 25, 10, 15] 249 | 第4次内循环[1, 3, 6, 8, 10, 25, 15] 250 | 第5次内循环[1, 3, 6, 8, 10, 15, 25] 251 | 第0次外循环[1, 3, 6, 8, 10, 15, 25] 252 | 第0次内循环[1, 3, 6, 8, 10, 15, 25] 253 | 第1次内循环[1, 3, 6, 8, 10, 15, 25] 254 | 第2次内循环[1, 3, 6, 8, 10, 15, 25] 255 | 第3次内循环[1, 3, 6, 8, 10, 15, 25] 256 | 第4次内循环[1, 3, 6, 8, 10, 15, 25] 257 | 第1次外循环[1, 3, 6, 8, 10, 15, 25] 258 | 第0次内循环[1, 3, 6, 8, 10, 15, 25] 259 | 第1次内循环[1, 3, 6, 8, 10, 15, 25] 260 | 第2次内循环[1, 3, 6, 8, 10, 15, 25] 261 | 第3次内循环[1, 3, 6, 8, 10, 15, 25] 262 | 第2次外循环[1, 3, 6, 8, 10, 15, 25] 263 | 第0次内循环[1, 3, 6, 8, 10, 15, 25] 264 | 第1次内循环[1, 3, 6, 8, 10, 15, 25] 265 | 第2次内循环[1, 3, 6, 8, 10, 15, 25] 266 | 第3次外循环[1, 3, 6, 8, 10, 15, 25] 267 | 第0次内循环[1, 3, 6, 8, 10, 15, 25] 268 | 第1次内循环[1, 3, 6, 8, 10, 15, 25] 269 | 第4次外循环[1, 3, 6, 8, 10, 15, 25] 270 | 第0次内循环[1, 3, 6, 8, 10, 15, 25] 271 | 第5次外循环[1, 3, 6, 8, 10, 15, 25] 272 | 最后的结果[1, 3, 6, 8, 10, 15, 25] 273 | ``` 274 | 我们可以看到,第0次外循环,已经将25放在了最右边,第1次外循环确定把15放到最右边,这样从右往左,从大到小,这就是完整的冒泡排序。 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | -------------------------------------------------------------------------------- /31-40/40、练习、Python的八皇后.md: -------------------------------------------------------------------------------- 1 |  2 | @Author:By Runsen 3 | # 什么是八皇后 4 | 5 | **八皇后问题**是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后。 6 | 7 | 来自百度百科,皇后的走法是可以横竖斜着走任意格。 8 | 9 | 10 | 11 | 12 | 13 | 14 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS80NzBjMGE4NC04NTM4LTQyMzAtYjg2Ny03ZTg2NTk4Y2Q2NzIucG5n?x-oss-process=image/format,png) 15 | 16 | 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子。皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子。在一个棋盘上如果要放八个皇后,使得她们互相之间不能攻击(即任意两两之间都不同行不同列不同斜线),求出一种所有布局方式。 17 | 18 | 好了我们来解决这个八皇后的问题,最常用的就是回溯法 19 | 20 | # 回溯法 21 | 22 | 回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件]的某个[状态的点称为“回溯点”。(来自百度百科) 23 | 24 | 说到底,就是一个一个的试错,在第一行第一个列放皇后,然后在第二行放皇后,一直将整个棋盘放满。如果发现放不了,就回到上一行放皇后的地方,选择其他位置放皇后。 25 | 26 | 27 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS9kNmVhODUzOC0wYjQ2LTRiMzMtYmJmOS02YWRlZjkwZjUyNmQucG5n?x-oss-process=image/format,png) 28 | 29 | 30 | 31 | 回溯法就是不断的试错,有错了就回到上一行放皇后,直到整个棋盘放满。 32 | 33 | # 代码 34 | 35 | 下图是八皇后问题的一个解: 36 | 37 | 38 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS8xNGQ2ZGM2Yi01ZTk2LTQxNjMtYjAzMS1mMTAwM2NhNmRkODIucG5n?x-oss-process=image/format,png) 39 | 40 | 首先定义一个冲突函数,如下,ps是positions 的缩写,表示之前摆放的皇后位置,是一个list,每个元素代表第几列放的,比如上图所有的皇后可以表示为 41 | 42 | ``` 43 | [0,4,7,5,2,6,1,3] 44 | ``` 45 | 46 | 47 | 48 | 49 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS9mMDY3OWI2NC1iNmEyLTQ0ODItODc0NC03YzdiZWI3NzU2MzUucG5n?x-oss-process=image/format,png) 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | state 这里理解元组,就是之前放回皇后的位置,nextX表示新皇后要放的横坐标,conflict函数就是检测新皇后放的位置和之前的皇后在位置上是否有冲突,有的话返回True。 58 | 59 | ```python 60 | def conflict(state, nextX): 61 | nextY = len(state) 62 | # 新皇后要放的纵坐标 63 | # print(state) #不知道可以下面打印下 64 | for i in range(nextY): 65 | #在同一行或者在对角线上 nextY-i=1 就是对角线 66 | if abs(state[i]-nextX) in (0, nextY-i): 67 | return True 68 | return False 69 | ``` 70 | 71 | 再定义一个queens函数, 这里我们用Python的生成器来存储我们的结果 72 | 73 | ```python 74 | def queens(num,state=()): 75 | for pos in range(num): 76 | # 没有冲突 77 | if not conflict(state,pos): 78 | # 最后一个pos,就是放到了最后一行,就yield储存在queens队列中 79 | if len(state) ==num-1: 80 | yield(pos,) 81 | # 还没有到最后一行,就放皇后 82 | else: 83 | # 遍历之前的queens队列中储存的结果,(pos,) 就是当前放皇后,我们不知道是否最后一行,所以不断地递归,直到放到了最后一行 84 | for result in queens(num, state + (pos,)): 85 | yield (pos, ) + result 86 | 87 | print(len(list(queens(8)))) 88 | # 92 89 | 90 | 一共有92中方法 91 | ``` 92 | 93 | 94 | 95 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS80MDg3YTU5OC05MTI3LTQyNmQtOGVmMS02Y2RhNjg1OTBkYjAucG5n?x-oss-process=image/format,png) 96 | 97 | 98 | 99 | 100 | 101 | `list(queens(8))`就是我们的结果,下面我们定义一个`preetyprint`打印美观先 102 | 103 | 104 | 105 | ```python 106 | import random 107 | 108 | def preetyprint(solution): # pilish 输出 109 | def line(pos, length=len(solution)): 110 | return'| '*(pos)+'|X'+'| '*(length-pos) 111 | for pos in solution: 112 | print (line(pos)) 113 | 114 | preetyprint(random.choice(list(queens(8)))) 115 | 116 | | | | | | | |X| | 117 | | | | |X| | | | | 118 | | |X| | | | | | | 119 | | | | | | | | |X| 120 | | | | | | |X| | | 121 | |X| | | | | | | | 122 | | | |X| | | | | | 123 | | | | | |X| | | | 124 | ``` 125 | 126 | # 完整代码 127 | 128 | ```python 129 | import random 130 | 131 | def conflict(state, nextX): 132 | nextY = len(state) 133 | # 新皇后要放的纵坐标 134 | # print(state) #不知道可以下面打印下 135 | for i in range(nextY): 136 | #在同一行或者在对角线上 nextY-i=1 就是对角线 137 | if abs(state[i]-nextX) in (0, nextY-i): 138 | return True 139 | return False 140 | 141 | def queens(num,state=()): 142 | for pos in range(num): 143 | # 没有冲突 144 | if not conflict(state,pos): 145 | # 最后一个pos,就是放到了最后一行,就yield储存在queens队列中 146 | if len(state) ==num-1: 147 | yield(pos,) 148 | # 还没有到最后一行,就放皇后 149 | else: 150 | # 遍历之前的queens队列中储存的结果,(pos,) 就是当前放皇后,我们不知道是否最后一行,所以不断地递归,直到放到了最后一行 151 | for result in queens(num, state + (pos,)): 152 | yield (pos, ) + result 153 | 154 | 155 | def preetyprint(solution): 156 | def line(pos, length=len(solution)): 157 | return'| '*(pos)+'|X'+'| '*(length-pos) 158 | for pos in solution: 159 | print (line(pos)) 160 | 161 | print(len(list(queens(8)))) 162 | 163 | preetyprint(random.choice(list(queens(8)))) 164 | 165 | 166 | 167 | for i in list(queens(8)): 168 | print(i) 169 | ``` 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /41-50/41、Python统计模块statistics.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | 3 | 4 | 5 | @[TOC] 6 | 7 | 8 | 官网: https://docs.python.org/3/library/statistics.html 9 | # Python统计模块statistics 10 | statistics 模块实现了许多常用的统计公式,以便使用 Python 的各种数值类型(int,float,Decimal 和 Fraction)进行高效的计算。 11 | 12 | 13 | 14 | 15 | 16 | 17 | ```python 18 | # 计算平均数 19 | import statistics 20 | 21 | 22 | data = [1,2,3,4,5.6] 23 | 24 | print(statistics.mean(data))# 3.12 25 | # 等同于 26 | 27 | print(sum(data)/len(data)) 28 | ``` 29 | 30 | 3.12 31 | 3.12 32 | 33 | 34 | 35 | ```python 36 | # mode 众数 37 | data = [1,2,3,4,5,1] 38 | statistics.mode(data) 39 | ``` 40 | 41 | 42 | 43 | 44 | 1 45 | 46 | 47 | 48 | # median-中位数 49 | - median-low()-中位数(如果项数是偶数,返回小值) 50 | - median-high()-中位数(如果项数是偶数,返回大值) 51 | - median-grouped() - j将数字排序好再选择中位数 52 | 53 | 54 | 55 | ```python 56 | print(statistics.median([1, 3, 5, 7])) 57 | print(statistics.median_low([1, 3, 5, 7])) 58 | print(statistics.median_high([1, 3, 5, 7])) 59 | print(statistics.median_grouped([5, 3, 7])) 60 | ``` 61 | 62 | 4.0 63 | 3 64 | 5 65 | 5.0 66 | 67 | # 方差 68 | 69 | **计算样本方差(sample variance)和样本标准差(sample standard deviation,the square root of the sample variance,也叫均方差)。** 70 | 71 | 72 | ```python 73 | # variance()-方差 74 | data = [1, 2, 3, 3, 4] 75 | statistics.variance(data) # 1.3 76 | # stdev-标准差 77 | statistics.stdev(data) # 1.140175425099138 78 | ``` 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | ```python 89 | # pvariance()-总体方差 90 | statistics.pvariance([1.5, 2.5, 2.5, 2.75, 3.25, 4.75]) 91 | ``` 92 | 93 | 94 | 95 | 96 | 0.9739583333333334 97 | 98 | 99 | 100 | 101 | ```python 102 | ### pstdev() -- 返回总体标准差()。 103 | ### pvariance() --返回总体方差()。 104 | 105 | statistics.pstdev(data) # 1.019803902718557 106 | statistics.pvariance(data)# 1.04 107 | ``` 108 | 109 | 110 | https://docs.python.org/3/library/statistics.html 111 | 112 | -------------------------------------------------------------------------------- /41-50/42、MOOC课程 _ Python中的Scipy模块.md: -------------------------------------------------------------------------------- 1 |  2 | 这是MOOC课上的Scipy基础 3 | 4 | 5 | @[toc] 6 | # SciPy的介绍 7 | 在Numpy库的基础上增加了众多的数学、科学以及工程计算中常用 的库函数 8 | 9 | 10 | - 线性代数 11 | - 常微分方程数值求解 12 | - 信号处理 13 | - 图像处理 14 | - 稀疏矩阵 15 | 16 | # SciPy的常数 17 | SciPy的constants模块包含了众多的物理常数: 18 | 19 | 20 | ```python 21 | from scipy import constants 22 | print(constants.c) # 真空中的光速 23 | 299792458.0 24 | print(constants.h) # 普朗克常数 25 | 6.62607004e-34 26 | ``` 27 | 28 | 29 | 在字典physical_constants中,以物理常量名为键,对应的值是一个含有三 个元素的元组,查看电子质量的例子: 30 | ```python 31 | print(constants.physical_constants['electron mass']) 32 | 33 | (9.10938356e-31, 'kg', 1.1e-38) 34 | 常数值 单位 误差 35 | ``` 36 | 37 | 38 | 39 | ![](https://img-blog.csdnimg.cn/20190507230820928.png) 40 | 41 | ```python 42 | # 1英里等于多少米, 1英寸等于多少米, 1克等于多少千克, 1磅等于多少千克 43 | print(C.mile, C.inch,C.gram,C.pound) 44 | 45 | 1609.3439999999998 0.0254 0.001 0.45359236999999997 46 | ``` 47 | # optimize模块 48 | optimize模块提供了许多数值优化算法,可以实现 49 | - 非线性方程组求解 50 | - 数据拟合 51 | - 函数最小值 52 | ![](https://img-blog.csdnimg.cn/20190507230952638.png) 53 | 54 | ![](https://img-blog.csdnimg.cn/20190507231011629.png) 55 | 56 | ```python 57 | import numpy as np 58 | from scipy.optimize import leastsq 59 | X = np.array([8.19, 2.72, 6.39, 8.71, 4.7, 2.66, 3.78]) 60 | Y = np.array([7.01, 2.78, 6.47, 6.71, 4.1, 4.23, 4.05]) 61 | #计算以p为参数的直线和原始数据之间的误差 62 | def f(p): 63 | k, b = p 64 | return(Y-(k*X+b)) 65 | #leastsq使得f的输出数组的平方和最小,参数初始值为[1,0] 66 | r = leastsq(f, [1,0]) 67 | k, b = r[0] 68 | print("k=",k,"b=",b) 69 | 70 | k= 0.6134953491930442 b= 1.794092543259387 71 | ``` 72 | 73 | ![](https://img-blog.csdnimg.cn/20190507231137418.png) 74 | 75 | ![](https://img-blog.csdnimg.cn/20190507231154670.png) 76 | 77 | 78 | ```python 79 | from scipy.optimize import fsolve 80 | from math import sin 81 | #f计算方程组的误差,x是一组可能的解 82 | def f(x): 83 | #转换为标准的浮点数列表 84 | x0, x1, x2 = x.tolist() 85 | return[5*x1+3, 86 | 4*x0*x0 - 2*sin(x1*x2), 87 | x1*x2-1.5] 88 | #[1,1,1]是未知数的初始值 89 | result = fsolve(f, [1,1,1]) 90 | #输出方程组的解 91 | print(result) 92 | #输出误差 93 | print(f(result)) 94 | 95 | [-0.70622057 -0.6 -2.5 ] 96 | [0.0, -9.126033262418787e-14, 5.329070518200751e-15] 97 | ``` 98 | # 插值-interpolate 99 | 100 | # 插值 V.S. 拟合 101 | 102 | 103 | - 插值:通过已知的离散数据来求解未知数据的方法,要求 104 | 曲线通过所有的已知数据。 105 | - 拟合:要求曲线函数与已知数据集的误差最小,不要求曲 106 | 线通过所有的已知数据。 107 | 108 | 109 | **intepolate模块提供了许多对数据进行插值运算的函数:** 110 | - B样条曲线插值 111 | - 外推 112 | - Spline拟合(UnivariateSpline插值运算) 113 | - 二维插值运算等 114 | 115 | 116 | 117 | ![](https://img-blog.csdnimg.cn/20190507231542972.png) 118 | ![](https://img-blog.csdnimg.cn/20190507231551681.png) 119 | 120 | ```python 121 | # 创建数据点集: 122 | import numpy as np 123 | x = np.linspace(0, 10, 11) 124 | y = np.sin(x) 125 | import pylab as pl 126 | pl.plot(x,y,'ro') 127 | pl.show() 128 | ``` 129 | ![](https://img-blog.csdnimg.cn/20190507231833418.png) 130 | **B样条曲线插值-举例** 131 | ![](https://img-blog.csdnimg.cn/20190507232206654.png) 132 | ![](https://img-blog.csdnimg.cn/20190507232229935.png) 133 | ```python 134 | import numpy as np 135 | from scipy import interpolate 136 | import pylab as pl 137 | #创建数据点集并绘制 138 | x = np.linspace(0, 10, 11) 139 | y = np.sin(x) 140 | pl.plot(x,y,'ro') 141 | #建立插值数据点 142 | xnew = np.linspace(0, 10, 101) 143 | for kind in ['nearest', 'zero','linear','quadratic']: 144 | #根据kind创建插值对象interp1d 145 | f = interpolate.interp1d(x, y, kind = kind) 146 | ynew = f(xnew)#计算插值结果 147 | pl.plot(xnew, ynew, label = str(kind)) 148 | pl.legend(loc = 'lower right') 149 | pl.show() 150 | ``` 151 | ![](https://img-blog.csdnimg.cn/20190507232107790.pn) 152 | 153 | 154 | ![](https://img-blog.csdnimg.cn/2019050723464798.Jpeg) 155 | ![](https://img-blog.csdnimg.cn/20190507234650759.Jpeg) 156 | ![](https://img-blog.csdnimg.cn/20190507234654748.Jpeg) 157 | ![](https://img-blog.csdnimg.cn/2019050723465825.Jpeg) 158 | ![](https://img-blog.csdnimg.cn/20190507234701218.Jpeg) 159 | ![](https://img-blog.csdnimg.cn/20190507234704658.Jpeg) 160 | ![](https://img-blog.csdnimg.cn/20190507234708104.Jpeg) 161 | ![](https://img-blog.csdnimg.cn/20190507234711667.Jpeg) 162 | ![](https://img-blog.csdnimg.cn/2019050723471532.Jpeg) 163 | 164 | ![](https://img-blog.csdnimg.cn/20190507234727542.Jpeg) 165 | ![](https://img-blog.csdnimg.cn/20190507234738729.Jpeg) 166 | ![](https://img-blog.csdnimg.cn/20190507234742401.Jpeg) 167 | ![](https://img-blog.csdnimg.cn/20190507234745727.Jpeg) 168 | ![](https://img-blog.csdnimg.cn/20190507234808467.Jpeg) 169 | ![](https://img-blog.csdnimg.cn/20190507234812407.Jpeg) 170 | ![](https://img-blog.csdnimg.cn/20190507234820974.Jpeg) 171 | ![](https://img-blog.csdnimg.cn/20190507234827194.Jpeg) 172 | ![](https://img-blog.csdnimg.cn/2019050723483554.Jpeg) 173 | ![](https://img-blog.csdnimg.cn/20190507234838989.Jpeg) 174 | ![](https://img-blog.csdnimg.cn/20190507234842351.Jpeg) 175 | ![](https://img-blog.csdnimg.cn/20190507234853398.Jpeg) 176 | ![](https://img-blog.csdnimg.cn/20190507234917869.Jpeg) 177 | ![](https://img-blog.csdnimg.cn/20190507234922406.Jpeg) 178 | ![](https://img-blog.csdnimg.cn/20190507234934928.Jpeg) 179 | ![](https://img-blog.csdnimg.cn/20190507235034101.Jpeg) 180 | ![](https://img-blog.csdnimg.cn/20190507234946502.Jpeg) 181 | ![](https://img-blog.csdnimg.cn/20190507235113899.Jpeg) 182 | ![](https://img-blog.csdnimg.cn/20190507235140760.Jpeg) 183 | ![](https://img-blog.csdnimg.cn/2019050723514621.Jpeg) 184 | ![](https://img-blog.csdnimg.cn/20190507235226486.Jpeg) 185 | ![](https://img-blog.csdnimg.cn/20190507235212116.Jpeg) 186 | ![](https://img-blog.csdnimg.cn/20190507235235835.Jpeg) 187 | ![](https://img-blog.csdnimg.cn/20190507235239996.Jpeg) 188 | ![](https://img-blog.csdnimg.cn/20190507235334260.Jpeg) 189 | ![](https://img-blog.csdnimg.cn/20190507235342238.Jpeg) 190 | 191 | ![](https://img-blog.csdnimg.cn/20190507235349850.Jpeg) 192 | ![](https://img-blog.csdnimg.cn/20190507235354452.Jpeg) 193 | ![](https://img-blog.csdnimg.cn/20190507235358306.Jpeg) 194 | -------------------------------------------------------------------------------- /41-50/46、和我一起看看,国外的Python考试到底是怎么样(下篇).md: -------------------------------------------------------------------------------- 1 | [四十五、国外的Python考试(上篇)](https://blog.csdn.net/weixin_44510615/article/details/106228702) 2 | 3 | 4 | @Author: Runsen 5 | @Date:2020/5/21 6 | 7 | 8 | 上次,我看了Python考试,前面就是送分玩意,70先拿了50,这还是不及格,虽然我天天挂科,但是有尊严的。跟着我学Python,Java就对了。 9 | 10 | @[TOC] 11 | 12 | 13 | 14 | 15 | # 第五题 16 | 17 | 18 | 看题,看Runsen怎么解决国外Python考试。 19 | ![](https://img-blog.csdnimg.cn/202005212231099.png) 20 | 21 | 22 | 第一题,就是代入法,送分 23 | 24 | 25 | len一开始是5,然后m等于2,取整除,这样就是 c+ab+de 26 | 27 | 然后再将ab,de运行一次 28 | 29 | 30 | ab:2整除是1,得到b,a , 31 | 32 | 33 | de:2整除是1,得到e,d , 34 | 35 | 答案就是cbaed 36 | 37 | 38 | 我不信,就写代码测试一下 39 | 40 | ```css 41 | ''' 42 | @Author: Runsen 43 | @微信公众号: 润森笔记 44 | @博客: https://blog.csdn.net/weixin_44510615 45 | @Date: 2020/5/21 46 | ''' 47 | def fn(a): 48 | if len(a) <2: 49 | return a 50 | m = len(a) //2 51 | print(a[m],a[:m],a[m+1:]) 52 | return a[m] + fn(a[:m]) + fn(a[m+1:]) 53 | 54 | if __name__ == '__main__': 55 | print(fn('abcde')) 56 | 57 | c ab de 58 | b a 59 | e d 60 | cbaed 61 | ``` 62 | 63 | 和想得一样,简单 64 | 65 | ![](https://img-blog.csdnimg.cn/20200521223123412.png) 66 | 67 | 继续代入,其中lo =0,hi=4,m=2.,num[2] = 15,这样就是[1, 2, 15, 4, 5] 68 | 69 | 70 | 71 | 72 | fn([1,2,15,4,5],0,1) ,继续代入m=0,s=3,num[0] =3,就是[3, 2, 15, 4, 5] 73 | 74 | 75 | 76 | ```css 77 | # 错误的想法 78 | 这是这是把本身的fn运行,在fn还有两个fn。继续代入,fn([3,2,15,4,5],0,0),其中m=2.,num[0] = 3,无变化。fn([3,2,15,4,5],1,5),其中m=3,num[0] = 3 79 | 80 | 81 | 82 | 这样就是[1, 2, 15, 4, 5] 83 | 84 | 85 | ``` 86 | 87 | 88 | 89 | 90 | 91 | **我终于知道了,这里考的是函数的嵌套** 92 | 93 | 94 | 这题,我真的不会,一个函数再调用两次,直接打印看看,结果是[3, 2, 15, 9, 5],此题不会, 95 | 96 | 97 | 98 | ```css 99 | ''' 100 | @Author: Runsen 101 | @微信公众号: 润森笔记 102 | @博客: https://blog.csdn.net/weixin_44510615 103 | @Date: 2020/5/21 104 | ''' 105 | 106 | def fn(nums,lo,hi): 107 | if hi < lo: 108 | return 109 | m = (lo +hi )//2 110 | s = 0 111 | for i in range(lo,hi+1): 112 | s += nums[i] 113 | nums[m] = s 114 | print(nums,lo,m) 115 | fn(nums,lo , m-1) 116 | print(nums) 117 | fn(nums,m+1 , hi) 118 | 119 | if __name__ == '__main__': 120 | test = [1, 2, 3, 4, 5] 121 | fn(test, 0, len(test)-1) 122 | print(test) 123 | 124 | 125 | 126 | 127 | [1, 2, 15, 4, 5] 0 2 128 | [3 129 | 130 | , 2, 15, 4, 5] 0 0 131 | [3, 2, 15, 4, 5] 132 | [3, 2, 15, 4, 5] 1 1 133 | [3, 2, 15, 4, 5] 134 | [3, 2, 15, 4, 5] 135 | [3, 2, 15, 9, 5] 3 3 136 | [3, 2, 15, 9, 5] 137 | [3, 2, 15, 9, 5] 4 4 138 | [3, 2, 15, 9, 5] 139 | [3, 2, 15, 9, 5] 140 | 141 | ``` 142 | 143 | 144 | 145 | ![](https://img-blog.csdnimg.cn/20200521223141986.png) 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | ![](https://img-blog.csdnimg.cn/20200521223200423.png) 155 | 156 | runsen一开始看这题就是蒙的,然后发现了规律$a[n+1]=a[n]+3^n$ 157 | 158 | 159 | 这里还要求递归计算,不能超过四行代码,简单搞定 160 | 161 | 162 | 163 | ```css 164 | ''' 165 | @Author: Runsen 166 | @微信公众号: 润森笔记 167 | @博客: https://blog.csdn.net/weixin_44510615 168 | @Date: 2020/5/22 169 | ''' 170 | 171 | def tulip(n): 172 | if n == 0: 173 | return 1 174 | else: 175 | return tulip(n-1) + 3**n 176 | 177 | def main(): 178 | n = int(input('Enter a value for n:')) 179 | for i in range(n+1): 180 | print(tulip(i)) 181 | main() 182 | 183 | Enter a value for n:5 184 | 1 185 | 4 186 | 13 187 | 40 188 | 121 189 | 364 190 | ``` 191 | 192 | # 第六题 193 | 194 | 195 | 196 | 第一题 197 | ![](https://img-blog.csdnimg.cn/20200522162910746.png) 198 | 199 | 200 | 第一题。问当代码在上面显示的链表上执行时,会打印什么? 201 | 202 | 203 | 204 | 205 | 小白先看这个 206 | ![](https://img-blog.csdnimg.cn/20200522163538501.png) 207 | 208 | count=0,ptr 20 209 | count=1,ptr 30 210 | 211 | 然后2跳出循环,答案到30,也是就10,20,30],送分 212 | 213 | 214 | 215 | 216 | 217 | 218 | ![](https://img-blog.csdnimg.cn/20200522163746415.png) 219 | 220 | 221 | 第二题,这就是傻逼做的,答案[14,18,12,13]。解答没有 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | ![](https://img-blog.csdnimg.cn/20200522164021974.png) 230 | 231 | 232 | 第三题,我的结果是[5,4,9,4] 233 | 234 | ![](https://img-blog.csdnimg.cn/20200522164348195.png) 235 | 236 | 237 | 考链表的时间复杂度,链表中的元素都会两个属性,一个是元素的值,另一个是指针,此指针标记了下一个元素的地址,每一个数据都会保存下一个数据的内存的地址,通过此地址可以找到下一个数据,任意位置插入元素和删除元素效率较高,时间复杂度为O(1)。随机访问效率低,时间复杂度为0(N) 238 | 239 | 240 | 241 | ![](https://img-blog.csdnimg.cn/20200522165427407.png) 242 | 我的答案 243 | 244 | 245 | 246 | 第一个尾节点加入节点的时间复杂度$O(1)$ 247 | 248 | 249 | 第二个确定链表长度的时间复杂度$O(n)$ 250 | 251 | 252 | 第三个将链表中的前10个值相加的时间复杂度为$O(1)$ 253 | 254 | 第四个对于已排序的链接列表,搜索不在列表中的值的时间复杂性为$O(n)$ 255 | 256 | 257 | # 第七题 258 | 259 | 260 | 261 | 262 | ![](https://img-blog.csdnimg.cn/20200522165627577.png) 263 | 264 | 第一题显示列表值在下面的树中的位置,以形成二叉搜索树。假设节点是按照在原始列表中的出现顺序插入的,从44开始,然后是60,然后是62,依此类推。 265 | 266 | 取中间作根节点,下图就我的答案 267 | 268 | 269 | 270 | 271 | 272 | 273 | ![](https://img-blog.csdnimg.cn/20200522170413407.png) 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | ![](https://img-blog.csdnimg.cn/20200522170727592.png) 283 | 284 | 第二题。指出树是否表示二叉搜索树(BST),如果树不是二叉搜索树,为什么 285 | 286 | 287 | 二叉搜索树:任意节点的键值一定大于其左子树中的每一个节点的键值,并小于其右子树中的每一个节点的键值。 288 | 289 | 290 | 291 | 看我的二叉树 292 | 293 | [二叉树(上)](https://maoli.blog.csdn.net/article/details/90648081) 294 | 295 | 296 | 第一个不是,这里错了 297 | 298 | ![](https://img-blog.csdnimg.cn/20200522171407902.png) 299 | 300 | 301 | 第二个是 302 | 303 | 304 | 第三个不是,因为不是二叉树 305 | 306 | 307 | 至此,这份70分的考卷结束了。我还要一份,继续。 308 | -------------------------------------------------------------------------------- /41-50/47、第二份国外的Python考试(上篇).md: -------------------------------------------------------------------------------- 1 |  2 | @Author:Runsen 3 | @Date:2020/5/26 4 | 5 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 6 | 7 | 8 | 之前撸了一份国外的Python考试题目,那个留学生还有一份,我接着继续撸。走,看看国外的Python考试题到底是什么东西? 9 | 10 | 11 | @[toc] 12 | 13 | ![](https://img-blog.csdnimg.cn/20200524163744996.png) 14 | 15 | 满分55分,之前的是70,不知道什么回事,撸就对了。 16 | 17 | 18 | 19 | # 第一题 20 | 21 | 22 | ![](https://img-blog.csdnimg.cn/20200526182922726.png) 23 | 24 | 25 | 第一题很明显就是一个时间复杂度的题目,一个快速排序,一个链表查找,一个冒泡排序,一个链表插入,一个二叉搜索,一个访问Python列表中的单个元素。 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ![](https://img-blog.csdnimg.cn/20200527094912912.png) 34 | 35 | 快速排序$Onlogn)$,链表查找$On)$,冒泡排序$On^2)$,链表插入$O(1)$,二叉搜索$O(Logn)$ 36 | 访问Python列表中的单个元素$O(1)$。 37 | 38 | 39 | 40 | Python列表做元素的遍历、删除、插入等操作,对应的时间复杂度为O(n);访问某个索引的元素、尾部添加元素或删除元素这些操作比较适合做,对应的时间复杂度为O(1)。 41 | 42 | 43 | 44 | 45 | ![](https://img-blog.csdnimg.cn/20200527100100585.png) 46 | 47 | 答案我不知道,没有标准答案。 48 | 49 | 50 | 51 | 52 | 53 | ![](https://img-blog.csdnimg.cn/20200527100151854.png) 54 | 55 | 第二题是指出函数的时间复杂性 56 | 57 | 58 | 三个循环,但是结尾是一个n//4,应该是$O(nlogn)$,因为`for i in range(10)`这个是$O(1)$ 59 | 60 | 61 | 62 | ![](https://img-blog.csdnimg.cn/20200527101032924.png) 63 | 64 | 65 | 二个循环,应该是$O(n^2)$ 66 | 67 | 68 | # 第二题 69 | 70 | 71 | ![](https://img-blog.csdnimg.cn/20200527101155993.png) 72 | 73 | 打印出什么,2*fizbin(6,10),然后就是4*fizbin(3,5),答案就是4。 74 | 75 | 76 | 77 | ![](https://img-blog.csdnimg.cn/20200527101439234.png) 78 | 79 | 一开始mid等于2,left = mysteryFun([1,0]) = mysteryFun([1]) +mysteryFun([0]) = 1 80 | 81 | 82 | right = mysteryFun([2,3]) = mysteryFun([2]) +mysteryFun([3]) = 4+9=13 83 | 84 | 答案14。 85 | 86 | 87 | 如果mysteryFun([0,1]),运行3次。 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | ![](https://img-blog.csdnimg.cn/20200527102542313.png) 98 | 99 | 100 | 写一个函数应该返回一个由列表中所有字符串组成的字符串,这些字符串以一个空格分隔的给定字符开头,用字符决定排序的列表。 101 | 102 | 103 | 难度一般, 104 | 105 | 106 | ```css 107 | def alliterationMaker(alist,char): 108 | # 对alist的开头不是char的去除 109 | for i in alist: 110 | if i[0] != char: 111 | alist.pop(alist.index(i)) 112 | alist.sort() 113 | return alist 114 | 115 | if __name__ == '__main__': 116 | print(alliterationMaker(["big","cow","bug","bit","table","black","bear"],"b")) 117 | 118 | ['bear', 'big', 'bit', 'black', 'bug'] 119 | ``` 120 | # 第三题 121 | 122 | ![](https://img-blog.csdnimg.cn/20200527104040275.png) 123 | 124 | 125 | 就是把从大到小,6,5,4,2,2,然后再全部加一,7,6,5,3,3.再反转,3,3,5,6,7 126 | 127 | 128 | ![](https://img-blog.csdnimg.cn/2020052710452826.png) 129 | 130 | 131 | 答案8,7,6,25 132 | 133 | 134 | # 第四题 135 | ![](https://img-blog.csdnimg.cn/20200527105249730.png) 136 | 137 | 二叉树的遍历是指从二叉树的根结点出发,按照某种次序依次访问二叉树中的所有结点,使得每个结点被访问一次,且仅被访问一次,分别有前序遍历,中序遍历,后序遍历 138 | 139 | 140 | 前序遍历通俗的说就是从二叉树的根结点出发,当第一次到达结点时就输出结点数据,按照先向左在向右的方向访问。 141 | 142 | 中序遍历就是从二叉树的根结点出发,当第二次到达结点时就输出结点数据,按照先向左在向右的方向访问。 143 | 144 | 后序遍历就是从二叉树的根结点出发,当第三次到达结点时就输出结点数据,按照先向左在向右的方向访问。 145 | 146 | ![](https://img-blog.csdnimg.cn/20190528215926380.png) 147 | 148 | 选项A就是后序遍历 正确 149 | 选项B就是前序遍历 但是错误 150 | 选项C就是前序遍历 正确 151 | 选项D什么遍历都不是,错误 152 | 选项E什么遍历都不是,错误 153 | ![](https://img-blog.csdnimg.cn/20200527110144387.png) 154 | 155 | 当输入是上面显示的树时,显示以下代码打印的内容。 156 | 157 | 158 | 这个真的不知道写什么,就是不断地分解子树,打印出来 159 | -------------------------------------------------------------------------------- /41-50/48、第二份国外的Python考试(下篇).md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/5/26 3 | 4 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 5 | 6 | 7 | 8 | 9 | @[TOC] 10 | 11 | # 第五题 12 | 13 | 14 | ![](https://img-blog.csdnimg.cn/20200527111432148.png) 15 | 16 | 归并排序和快速排序在最佳情况下都具有$O(n logn)$时间复杂性。然而,其中一个算法的最坏情况复杂度为$O(n^2)$。说明哪些算法的时间复杂度为$O(n^2)$,并简要解释为什么 17 | 18 | 19 | 答案是快速排序 20 | ![](https://img-blog.csdnimg.cn/20200527111040603.png) 21 | 22 | 23 | 快速排序具有最好的平均性能(average behavior),但最坏性能(worst case behavior)和插入排序 24 | 25 | 相同,也是$O(n^2)$。比如一个序列5,4,3,2,1,要排为1,2,3,4,5。按照快速排序方法,每次只会有一个数据进入正确顺序,不能把数据分成大小相当的两份,很明显,]时间复杂度就成了O(n^2)。 26 | 27 | 28 | 29 | 30 | 31 | 32 | 第二题 33 | 34 | ![](https://img-blog.csdnimg.cn/20200527111409799.png) 35 | 36 | 37 | 在对冒泡排序、选择排序和插入排序的外部循环进行三次迭代之后,下面使用哪种排序 38 | 39 | 40 | 第一个很明显选择排序,选择排序在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。 41 | 42 | 43 | 44 | 第三个很明显冒泡排序, 45 | 46 | 47 | 那么第二个很明显插入排序 48 | 49 | 50 | 51 | 52 | ![](https://img-blog.csdnimg.cn/20200527112109255.png) 53 | 54 | 第三题,其实就是一个二分查找,只不过变成了查找对应的字符串,变汤不变药,问题就是当count等于2时候,那么对应的mid,higth,low。 55 | 56 | 57 | 58 | 第一,len(collection) = 10,一开始mid等于4,然后不对,直接low等于5,count等于1,接着mid等于7,不对,直接low等于8,count等于2, 59 | 60 | 因此答案是mid等于7,higth等于9,low等于8。 61 | 62 | 63 | 64 | 65 | # 最后一题 66 | 67 | ![](https://img-blog.csdnimg.cn/20200527122433768.png) 68 | 69 | 70 | (20分)你被委托写一个简单的游戏卡游戏称为考试扑克。这场比赛是用一套标准的扑克牌进行的。在您的游戏中,卡片将被表示为(等级,套装)元组的列表。注意数字11-13代表杰克、王后、国王,而我代表王牌。西装(黑桃钻石、红桃和梅花)用一个字母表示。我们将把这些卡片存储在一个叫做deck的全局抖动结构中。您可以假设在您的程序中定义了以下内容 71 | 72 | 73 | SCDH就是扑克牌的四种类别,一共有52张扑克牌 74 | 75 | 76 | 77 | 78 | 79 | 玩家最初获得5张牌。然后,他们还有三个(可选)回合,目标是实现以下其中一个 80 | 81 | 82 | 83 | 其中通俗的来说,就是现在你有五张牌,打牌的时候,怎么可以出五张牌,顺子可以打出去,三带二可以打出去,还有就是锄大地的同一种花色可以打出去。最后,通过五张牌的总和作为得分。你可以换牌。 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | ![](https://img-blog.csdnimg.cn/20200527122502815.png) 92 | 93 | ![](https://img-blog.csdnimg.cn/20200527123008596.png) 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | ![](https://img-blog.csdnimg.cn/20200527123654834.png) 102 | 103 | 104 | 这个代码写了我快一个小时,真的很多细节注意 105 | ```css 106 | ''' 107 | @Author: Runsen 108 | @微信公众号: 润森笔记 109 | @博客: https://blog.csdn.net/weixin_44510615 110 | @Date: 2020/5/21 111 | ''' 112 | import random 113 | # 定义一副未洗的牌[0, 1....51] 114 | porks = [i for i in range(52)] 115 | # 定义花色 116 | # 方片D(Diamonds) 梅花C(Clubs) 红桃H(heart) 黑桃S(spade) 117 | suits = ['D', 'C', 'H', 'S'] 118 | # 定义编号 119 | ranks = ['1', '2', '3', '4', '5', '6', '7', '8', 120 | '9', '10', '11', '12', '13'] 121 | s = 0 122 | def get_porks(mylist): 123 | # 随机生成一牌,但是要求不能在之前的出现 124 | pork = random.choice(ranks) + random.choice(suits) 125 | if pork in mylist: 126 | # 出现重新生成一牌 127 | return get_porks(mylist) 128 | else: 129 | return pork 130 | 131 | def get_five_porks(): 132 | mylist = [] 133 | for i in range(52): 134 | # 随机得到0-51整数随机数 135 | randomIndex = random.randint(0, 51) 136 | # 交换 137 | porks[i], porks[randomIndex] = porks[randomIndex], porks[i] 138 | for i in range(5): 139 | suit = suits[porks[i] // 13] 140 | rank = ranks[porks[i] % 13] 141 | mylist.append(str(rank + suit)) 142 | return mylist 143 | 144 | def change_porks(mylist): 145 | # 需不需要换牌 146 | 147 | global s 148 | print(mylist,s) 149 | Change = input("Change some cards:y or n: ") 150 | if Change == "y": 151 | keep = input("Indicate which cards you wish to keep :") 152 | for index,i in enumerate(keep): 153 | if i == '0': 154 | # 换牌 155 | pork = get_porks(mylist) 156 | print(pork) 157 | mylist.insert(index, pork) 158 | # 在删除之后的下一个 159 | mylist.pop(index+1) 160 | print("You now have:"+ str(mylist)) 161 | change_porks(mylist) 162 | else: 163 | # 计算分数 164 | for i in mylist: 165 | print(i) 166 | s += int(i[:-1]) 167 | print("Your total score is now:" +str(s)) 168 | return s 169 | 170 | 171 | def teststraightchecker(): 172 | global s 173 | mylist = get_five_porks() 174 | print("Here is your first hand:" + str(mylist)) 175 | change_porks(mylist) 176 | choice = input("Would you like to play again (y or n) :") 177 | if choice == 'y': 178 | teststraightchecker() 179 | else: 180 | print("Thank you for playing") 181 | 182 | if __name__ == '__main__': 183 | teststraightchecker() 184 | ``` 185 | 186 | 187 | ![](https://img-blog.csdnimg.cn/20200527214817516.png) 188 | 189 | ```css 190 | Here is your first hand:['11D', '13H', '3H', '6C', '12C'] 191 | Change some cards:y or n: y 192 | Indicate which cards you wish to keep :11001 193 | You now have:['11D', '13H', '3S', '7D', '12C'] 194 | Change some cards:y or n: y 195 | Indicate which cards you wish to keep :11001 196 | You now have:['11D', '13H', '11H', '8S', '12C'] 197 | Change some cards:y or n: y 198 | Indicate which cards you wish to keep :11101 199 | You now have:['11D', '13H', '11H', '6H', '12C'] 200 | Change some cards:y or n: y 201 | Indicate which cards you wish to keep :11100 202 | You now have:['11D', '13H', '11H', '13C', '6C'] 203 | Change some cards:y or n: y 204 | Indicate which cards you wish to keep :11110 205 | You now have:['11D', '13H', '11H', '13C', '13S'] 206 | Change some cards:y or n: n 207 | Your total score is now:61 208 | Would you like to play again (y or n) :n 209 | Thank you for playing 210 | ``` 211 | 212 | -------------------------------------------------------------------------------- /41-50/50、Redis数据库学习.md: -------------------------------------------------------------------------------- 1 |  2 | @Author:Runsen 3 | @Date:2019/03/19 4 | 5 | 6 | 7 | 8 | @[TOC] 9 | 10 | # 什么是redis 11 | Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。 12 | 13 | Redis特性 14 | - Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。 15 | - Redis不仅仅支持简单的key-value类型的数据,同时还把value分为list,set,zset,hash等数据结构存储。 16 | - 因为Redis交换数据快,所以在服务器中常用来存储一些需要频繁调取的数据,提高效率。 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | # redis安装 25 | 26 | 27 | 28 | 29 | 检查是否安装gcc环境 30 | 31 | ```css 32 | [root@VM_0_16_centos ~]# rpm -qa|grep gcc* 33 | //无则安装。 34 | [root@VM_0_16_centos ~]# yum install gcc-c++ 35 | ``` 36 | 37 | 创建目录,下载源码(通过华为镜像),解压源码 38 | 39 | ```css 40 | [root@VM_0_16_centos redis]# mkdir /usr/lib/redis 41 | [root@VM_0_16_centos redis]# cd /usr/lib/redis/ 42 | [root@VM_0_16_centos redis]# wget https://mirrors.huaweicloud.com/redis/redis-5.0.5.tar.gz 43 | [root@VM_0_16_centos redis]# tar -zxvf redis-5.0.5.tar.gz 44 | ``` 45 | 46 | 进入文件夹,编译 47 | 48 | ```css 49 | [root@VM_0_16_centos redis]# cd ./redis-5.0.5/ 50 | [root@VM_0_16_centos redis-5.0.5]# make 51 | ``` 52 | 53 | 编译成功 54 | 55 | 56 | 安装,并检查是否安装了服务 57 | 58 | 59 | ```css 60 | [root@VM_0_16_centos redis-5.0.5]# make PREFIX=/usr/local/redis install 61 | //查看是否有此服务 62 | [root@VM_0_16_centos bin]# ls /usr/local/redis/bin 63 | redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server 64 | 把解压目录下配置文件复制到安装路径下 65 | 66 | [root@VM_0_16_centos usr]# cp /usr/lib/redis/redis-5.0.5/redis.conf /usr/local/redis/ 67 | 由于前端启动模式启动后不可以随意关闭(进程断开),所以需要配置后端模式启动 68 | 69 | ``` 70 | 71 | 修改后端启动(即守护进程开启),取消ip绑定 72 | 73 | 74 | ```css 75 | [root@VM_0_16_centos ~]# vim /usr/local/redis/redis.conf 76 | 注释掉bind 127.0.0.1 77 | #bind 127.0.0.1 78 | 更改protected-mode yes为 79 | protected-mode no 80 | 81 | 更改daemonize no为 82 | daemonize yes 83 | ``` 84 | 85 | 设置密码 86 | requirepass 要很长的密码 87 | 88 | 启动,并指定配置文件 89 | 90 | ```css 91 | 92 | [root@VM_0_16_centos ~]# cd /usr/local/redis/ 93 | 94 | [root@VM_0_16_centos redis]# ./bin/redis-server ./redis.conf 95 | 96 | 1675:C 15 Sep 2019 22:50:52.157 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 97 | 98 | 1675:C 15 Sep 2019 22:50:52.157 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=1675, just started 99 | 1675:C 15 Sep 2019 22:50:52.157 # Configuration loaded 100 | 通过端口(6379)查看服务是否启动 101 | [root@VM_0_16_centos redis]# ps -ef|grep redis 102 | root 1676 1 0 22:50 ? 00:00:00 ./bin/redis-server *:6379 103 | root 1900 1219 0 22:52 pts/6 00:00:00 grep –color=auto redis 104 | 本地客户端连接和redis服务关闭 105 | [root@VM_0_16_centos redis]# ./bin/redis-cli 106 | 127.0.0.1:6379> eixt 107 | [root@VM_0_16_centos redis]# ./bin/redis-cli shutdown 108 | 通过外部(ip)连接,(需要开放云服务器相应端口) 109 | [root@VM_0_16_centos redis]# ./bin/redis-cli -h 49.ip.ip.2 -p 6379 -a 密码 110 | Warning: Using a password with ‘-a’ or ‘-u’ option on the command line interface may not be safe. 111 | 49.ip.ip.2:6379> 112 | ``` 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | # Redis数据模型 122 | 123 | 124 | Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。 125 | 126 | 1. String ------> 字符串 127 | 2. Hash ------> 哈希 128 | 3. List ------> 列表 129 | 4. set ------> 集合 130 | 5. Zset ------> 有序集合 131 | 132 | 133 | ![](https://img-blog.csdnimg.cn/20190319160041710.png) 134 | 135 | 136 | 137 | 138 | ## Redis基本使用 139 | 140 | ![](https://img-blog.csdnimg.cn/20190319160059375.png) 141 | - 连接redis:`redis-cli` 142 | 143 | - 退出:`exit` 144 | - 操作服务端:`service redis start/stop/restart` 145 | - 切换数据库:select n 146 | 147 | ![](https://img-blog.csdnimg.cn/2019031916011549.png) 148 | 149 | # Redis五大数据类型使用 150 | ## 全局key操作 151 | 对5 个数据类型都使用的命令 152 | ```shell 153 | 查看所有的key:keys * 154 | 删除键值对:del key 155 | 改名:rename key new_key 156 | 设置过期时间:expire key seconds 157 | ``` 158 | 159 | ## String类型 160 | 161 | strings是redis最基本的数据类型,一个key对应一个value 162 | ```shell 163 | 设置数据:set key value 164 | 查看数据:get key 165 | 追加数据:append key value 166 | 删除数据:del key; 167 | ``` 168 | 169 | ## List类型 170 | 171 | ```shell 172 | 添加数据:rpush key value [value…] 173 | lpush key value [value…] 头部添加数据 174 | 175 | 查看数据:lrange key start stop 176 | lindex key index 查看某个数据 177 | 178 | 修改数据:lset key index value 179 | 删除数据:rpop key 180 | lpop key 头部删除数据 181 | ``` 182 | ## Hash类型 183 | ```shell 184 | 添加数据:hset key field value 185 | 查看域值:hget key field 186 | hgetall key 查看所有的field和value 187 | 查看所有的value:hvals key 188 | 查看所有的field:hkeys key 189 | ``` 190 | ## Set类型 191 | 192 | ```shell 193 | 添加数据:sadd key member [member …] 194 | 查看数据:smembers key 195 | 随机删除:spop key 196 | 指定删除:srem key member [member …] 197 | ``` 198 | 199 | ## Sorted Set类型 200 | 201 | ```shell 202 | 添加数据: zadd key score member [score2 member2 …] 203 | 查看数据: zrange key start stop 204 | zrangebyscore key min max 通过scores值查看 205 | 删除数据:zrem key member [member …] 206 | 通过索引删除多个数据:zremrangebyrank key min max 207 | zremrangebyscore key min max -- 通过scores值删除 208 | ``` 209 | 210 | 211 | 212 | **flushall 删除所有数据** 213 | 214 | 215 | -------------------------------------------------------------------------------- /51-60/51、学会MongoDB数据库.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2019/03/19 3 | 4 | 5 | ![](https://img-blog.csdnimg.cn/20200527114711364.png) 6 | 7 | 8 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 9 | 10 | 11 | 12 | @[TOC] 13 | 14 | 15 | # MongoDB简介 16 | 安装 17 | 18 | ```csharp 19 | sudo apt-get install mongodb 20 | ``` 21 | 22 | `MongoDB`是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似`json`的`bson`格式,因此可以存储比较复杂的数据类型。`Mongo`最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。 23 | 24 | 将数据存储为一个文档,文档类似与Json格式, 25 | ``` 26 | { 27 | name:"毛利", 28 | age:18, 29 | address: {city:"东莞", country:"china"} 30 | } 31 | ``` 32 | 33 | # MongoDB数据模型 34 | 35 | ![](https://img-blog.csdnimg.cn/20190319104459695.png) 36 | **如何进入和退出mongo** 37 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190319104516430.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDUxMDYxNQ==,size_16,color_FFFFFF,t_70) 38 | ## 库级操作语句 39 | 40 | 41 | 42 | - 显示所有库: `show dbs` 43 | - 切换/创建数据库:` use 数据库名称 ` 44 | - 查看所在库: `db` 45 | - 删除库:`db.dropDatabase() ` 46 | 47 | 48 | ## 集合操作语句 49 | 50 | - 显示当前数据库的集合:` show collections` 51 | - 创建集合: `db.createCollection(name)` 52 | 53 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190319104539962.png) 54 | - 删除集合:` db.集合名称.drop()` 55 | 56 | 57 | ## 文档操作 58 | 59 | ### 添加文档(数据) 60 | 61 | `db.集合名称.insert(document)` 62 | 63 | 每一条数据,就是一个`document`,就是一条`json` 64 | 65 | 例:` db.student.insert({name:'毛利', age:18})` 66 | 67 | > 注意点: 68 | 69 | 添加文档时,如果不指定_id参数 70 | MongoDB会为文档分配一个唯一的ObjectId 71 | 72 | 给定 `_id` 73 | 例: `db.student.insert({'_id':1, name:'毛利', age:18})` 74 | 75 | - 添加多条文档 76 | ``` 77 | db.student.insert([ 78 | {name:'毛利, sex:'男', age:18}, 79 | {name:’毛利的爸爸', sex:'男', age:47}, 80 | {name:’毛利的姐姐', sex:'女', age:23}, 81 | {name:’毛利的妈妈‘, sex:’女', age:44}, 82 | ]) 83 | ``` 84 | 85 | 86 | ### 查询文档(数据) 87 | 88 | `db.集合名称.find([conditions])` 89 | 90 | 查看集合中全部数据: `db.student.find()` 91 | 92 | 格式化显示: `db.student.find().pretty() ` 93 | 94 | 查看满足条件的数据: `db.student.find({name:'毛利'})` 95 | 96 | 97 | ### 条件 98 | 99 | 100 | - and条件 `{$and:[{expression1}, {expression1}, ...] }` 101 | 102 | 103 | - or条件 `{$or:[{expression1}, {expression1}, ...] }` 104 | 105 | 106 | 107 | 108 | 109 | `db.student.find({$or:[{$and:[{sex:'女'}, {age:23}]},{$and:[{sex:'男'}, {age:{$gte:18}}]}]})` 110 | 111 | 112 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190319104553439.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDUxMDYxNQ==,size_16,color_FFFFFF,t_70) 113 | 114 | ### 修改文档(数据) 115 | 116 | 117 | `db.集合名称.update(, , {multi:})` 118 | - 修改一条数据: `db.student.update({sex:'男'}, {age:20})` 119 | 120 | 把表中的男的`age`改为`20` 121 | - 指定属性修改:` { $set: {age:20} } ` 122 | 123 | 124 | `db.student.update({name:'毛利'}, {$set: {age:666, sex: '不告诉你'}} )` 125 | 126 | 把毛利的`age`改为`666`,`sex`改为不告诉你 127 | 128 | - 更新集合中所有满足条件的文档: `{ multi: true } ` 129 | 130 | ``` 131 | db.student.update({sex:'男'}, {$set:{sex:'女'}}, { multi:true} ) 132 | ``` 133 | 把所有按的改为女的 134 | 135 | 136 | ### 删除文档(数据) 137 | 138 | 139 | `db.集合名称.remove(, {justOne:})` 140 | 141 | 142 | - 删除集合中所有的文档: 143 | `db.student.remove({})` 144 | - 删除集合中满足条件的所有文档 145 | `db.student.remove({sex: '男'})` 146 | - 只删除集合中满足条件的第一条文档: `{ justOne: true } ` 147 | 148 | 149 | ```db.student.remove({sex:'男'}, { justOne:true} )``` 150 | 151 | 152 | 153 | 154 | ## 在Python程序中操作MongoDB 155 | 156 | 157 | 可以通过pip安装pymongo来实现对MongoDB的操作。`pip3 install pymongo` 158 | 159 | ```Shell 160 | >>> from pymongo import MongoClient 161 | >>> client = MongoClient('mongodb://192.168.92.92:27017') 162 | >>> db = client.school 163 | >>> for student in db.students.find(): 164 | ... print('姓名:', student['name']) 165 | ``` 166 | -------------------------------------------------------------------------------- /51-60/52、ViM的使用.md: -------------------------------------------------------------------------------- 1 |  2 | @Author:Runsen 3 | @Date:2020/04/03 4 | ![](https://img-blog.csdnimg.cn/20200527115119893.png) 5 | 6 | 7 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 8 | 9 | 10 | 11 | @[TOC] 12 | 13 | # linux介绍 14 | 15 | 16 | ![](https://img-blog.csdnimg.cn/20190318121644669.png) 17 | 18 | Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。 19 | 20 | # Linux系统发行版本 21 | 22 | 1. [Redhat](https://www.redhat.com/en) 23 | 2. [Ubuntu](https://www.ubuntu.com/) 24 | 3. [CentOS](https://www.centos.org/) 25 | 4. [Fedora](https://getfedora.org/) 26 | 5. [Debian](https://www.debian.org/) 27 | 6. [openSUSE](https://www.opensuse.org/) 28 | 29 | 30 | # Linux常用命令 31 | 32 | 33 | 34 | 35 | 基本必知 | 作用 | 示例 36 | ---|---|--- 37 | cd| 切换工作目录 | cd ~ 回到主目录 cd .. 回到上级路径 cd - 回到上次路径 38 | pwd| 显示工作路径 | pwd 39 | ls | 显示文件列表 | ls 40 | mkdir | 创建文件夹 | mkdir test 41 | rmdir | 删除文件夹 | rmdir test 42 | cp | 复制 | cp a.txt b.txt 43 | mv | 移动和重命名 | mv b.txt ../ 44 | cat | 查看文件内容 | cat a.txt 45 | touch | 创建文件 | touch c.txt 46 | rm | 删除文件 | rm c.txt 47 | help | 帮助 | help cd 48 | 49 | 50 | 51 | Vim编辑py文件 52 | 53 | 54 | # Vim 55 | 56 | 57 | 58 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS9hM2MxNmEwZC1iN2E0LTQ1ZGItOTVkMy00NjA3ZGIwOGFjMTAucG5n?x-oss-process=image/format,png) 59 | 60 | 61 | `VIM` (Unix及类Unix系统文本编辑器) 62 | 63 | `Vim` 是一个类似于Vi的著名的功能强大、高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性。 64 | 65 | 66 | 重点 67 | 68 | 69 | 在Vim中,有命令模式,输入模式 和 末行模式三种模式。 70 | 71 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS9jMjZmZTJkMi02ZmQyLTQ1YTAtYTA1Ni1lMzk4ZDE3OTZkMzkucG5n?x-oss-process=image/format,png) 72 | 73 | 74 | 75 | - 按 ESC 进入命令模式 76 | - 输入 Shift + ; 进入末行模式 77 | - 输入插入命令,如(i,a,o) 进入插入模式 78 | 79 | `注意点 进入末行模式的前提一定是要命令模式,也就是输入完指令,必须先回到命令模式` 80 | 81 | 进入`vim filename ` 82 | 83 | ## 退出 84 | 85 | + :wq 末行模式,wq 保存退出 86 | + :q 末行模式,q 直接退出 87 | - :q! 末行模式,q! 强制退出,不保存 88 | 89 | ## 移动光标 90 | 91 | - gg 到文件第一行 92 | - G 到文件最后一行 (Shift + g) 93 | - ^ 非空格行首 94 | - 0 行首(数字0) 95 | - $ 行尾 96 | 97 | 98 | ## 输入模式 99 | 100 | - i 从光标所在位置前面开始插入 101 | - I 在当前行首插入 102 | - a 从光标所在位置后面开始输入 103 | - A 在当前行尾插入 104 | - o 在光标所在行下方新增一行并进入输入模式 105 | - O 在当前上面一行插入 106 | 107 | 108 | - 进入输入模式后,在最后一行会出现--INSERT—的字 109 | 110 | 111 | 112 | 这些命令都是在命令模式下的 113 | 复制和粘贴(必须灵活使用) 114 | 115 | - yy 复制整行内容 116 | - 3yy 复制3行内容 117 | - yw 复制当前光标到单词尾内容 118 | - p 粘贴 119 | 120 | 121 | ## 删除 122 | 123 | - dd 删除光标所在行 124 | - dw 删除一个单词 125 | - x 删除光标所在字符 126 | - u 撤销上一次操作 127 | - ctrl + r 撤销 u 128 | 129 | ## 块操作 130 | 131 | - v 块选择 132 | - ctrl + v 列块选择 133 | 134 | ## 查找 135 | 136 | - / 命令模式下输入:/ 向前搜索 137 | - ? 命令模式下输入:? 向后搜索 138 | - n 向下查找 139 | - N 向上查找 140 | 141 | 142 | ## 替换 末行模式 143 | 144 | - :s/s1/s2 替换当前行第一个s1为s2 145 | - :s/s1/s2/g 替换当前行中所有s1为s2 146 | - :%s/s1/s2/g 替换文中所有s1为 s2 147 | 148 | 149 | 关键是要多练 150 | 151 | 152 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS9lNzdmMDhhZS1mYWI4LTQ4MWQtYjNhNy1lNjJkOWNhMDFlYjEucG5n?x-oss-process=image/format,png) 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /51-60/56、教用Python中的turtle海龟画图(上篇).md: -------------------------------------------------------------------------------- 1 |  2 | @Author:Runsen 3 | @Date:2020/5/27 4 | 5 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 6 | 7 | 在Python中的turtle海龟画图,我相信大家都有了解,我在之前也写过这类的博文,但是我发现真的不行,今天就重写,保留好的地方,添加更多的要点 8 | 9 | 10 | 11 | 我觉得没有什么东西可以写,就是需要不断地实践。 12 | 13 | 14 | @[TOC] 15 | 16 | 17 | 18 | # 画一条线 19 | 20 | 21 | ```css 22 | import turtle 23 | t = turtle.Pen() 24 | t.forward(100) 25 | ``` 26 | 27 | 28 | t = turtle.Pen()告诉计算机我们使用t表示海龟的钢笔, 29 | forward(distance) :别名 turtle.fd( distance ) 沿着当前方向前进指定距离,这里的距离的单位是像素。 30 | 31 | ![](https://img-blog.csdnimg.cn/20200529111800162.png) 32 | 黑色的小三角就是我们的小海龟。三角后面的直线,就是小海龟“前进100步”所留下的痕迹 33 | 34 | 35 | # 画一个正方形 36 | 37 | 38 | 如果一直前进而不转弯,画出的图也会相当单调。这不是我们所希望的,我们需要“转弯语句”。我们可以“向右转90度”,使用“t.right(90)”,或“向左转90度”,使用“t.left(90)”。这里我们选向右转吧。将“t.right(90)”加入代码,运行: 39 | 40 | 41 | ```css 42 | import turtle 43 | t = turtle.Pen() 44 | t.forward(100) 45 | t.right(90) 46 | t.forward(100) 47 | t.right(90) 48 | t.forward(100) 49 | t.right(90) 50 | t.forward(100) 51 | t.right(90) 52 | ``` 53 | 54 | 55 | 56 | ![](https://img-blog.csdnimg.cn/20200529112333480.png) 57 | 58 | 59 | 60 | # 画一个三角形 61 | 62 | 63 | 64 | 65 | 我们使用turtle.setup(400,400)来设置画布的大小,设置一个400 * 400的窗口大小。 66 | t.left(120)以箭头的方向向左旋转120角度。 67 | 68 | ```css 69 | import turtle 70 | turtle.setup(400,400) 71 | t = turtle.Pen() 72 | t.forward(100) 73 | t.left(120) 74 | t.forward(100) 75 | t.left(120) 76 | t.forward(100) 77 | t.left(120) 78 | ``` 79 | 80 | ![](https://img-blog.csdnimg.cn/20200529112754795.png) 81 | # 画一个圆 82 | 83 | 84 | 85 | t.circle(50),就是画一个半径为50的圆。 86 | 87 | 88 | ```css 89 | import turtle 90 | turtle.setup(400,400) 91 | t = turtle.Pen() 92 | t.circle(50) 93 | turtle.done() 94 | ``` 95 | 96 | 97 | 98 | ![](https://img-blog.csdnimg.cn/20200529113224314.png) 99 | 100 | turtle.done()就是画完的时候停下来,不要马上关闭。 101 | 102 | 103 | # 绘制梯形 104 | 105 | 106 | 107 | 108 | ```css 109 | import turtle 110 | turtle.up() 111 | turtle.fillcolor('yellow') 112 | turtle.begin_fill() 113 | turtle.goto(100,-100) 114 | turtle.down() 115 | turtle.goto(200,-100) 116 | turtle.goto(250,-200) 117 | turtle.goto(50,-200) 118 | turtle.goto(100,-100) 119 | turtle.end_fill() 120 | turtle.done() 121 | 122 | 123 | ``` 124 | 此梯形绘制在第四象限,所以梯形形每个顶点的坐标中,x坐标为正,y坐标为负。四个点的坐标分别选择为(100,-100)、(200,-100)、(250,-200)、(50,-200)。goto也是画的意思,goto(x,y)就是以x和y坐标定位画线。down就是停下来。end_fill就是给封闭图形添加颜色。 125 | ![](https://img-blog.csdnimg.cn/20200529113621144.png) 126 | # 画一个星星 127 | 128 | 星星就是四个圆弧组成,转弯是180度 129 | 130 | ```css 131 | import turtle 132 | turtle.setup(800, 600) # 创建绘图窗口 133 | 134 | for i in range(4): # 循环四次 135 | turtle.circle(90,90) # 顺时针画一个半径90,90度对应的圆弧 顺时针是正 136 | turtle.right(180) # 右转180度 137 | 138 | turtle.done() 139 | ``` 140 | 141 | ![](https://img-blog.csdnimg.cn/20200529114831673.gif) 142 | 143 | # 画一个五角星 144 | 五角星是边数最少多角形。最简单的画法是先画一个正五边形,把各角用直线相连并擦去原来的五边形或者延长原五边形的各边直到它们相交,从而得到一个大的五角星。 145 | 146 | 147 | 148 | ```css 149 | import turtle 150 | turtle.color('black','red') 151 | turtle.begin_fill() 152 | for i in range(5): 153 | turtle.forward(100) 154 | turtle.right(144) 155 | turtle.end_fill() 156 | ``` 157 | 158 | 159 | 160 | 161 | ![](https://img-blog.csdnimg.cn/20200529115402257.png) 162 | 163 | # 画一个图案 164 | 165 | ```css 166 | import turtle 167 | t = turtle.Pen() 168 | for x in range(100): 169 | t.forward(x) 170 | t.left(90) 171 | turtle.done() 172 | 173 | ``` 174 | 175 | 176 | 177 | ![](https://img-blog.csdnimg.cn/20200529115602232.gif) 178 | # 方法总结 179 | 180 | 181 | 182 | ```css 183 | turtle.fd(d)、 184 | turtle.forward(d):以当前方向,往前行进d像素。 185 | 186 | turtle.bk(d)、 187 | turtle.backword(d):保持当前方向不变,往后退行d像素。 188 | 189 | turtle.circle(r,angle,steps=):从当前位置以r为半径圆的angle角度旋转。 190 | 191 | turtle.seth(angle):以x轴方向为起点将方向偏转为angle度,逆时针为正。只改变行进方向但不行进。 192 | 193 | turtle.left(angle):在当前行进方向的基础上,向左旋转angle度。 194 | 195 | turtle.right(angle):在当前行进方向的基础上,向右旋转angle度。 196 | ``` 197 | 198 | -------------------------------------------------------------------------------- /51-60/57、教用Python中的turtle海龟画图(下篇).md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/5/27 3 | 4 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 5 | 6 | 在Python中的turtle海龟画图,我相信大家都有了解,我在之前也写过这类的博文,但是我发现真的不行,今天就重写,保留好的地方,添加更多的要点 7 | 8 | 我觉得没有什么东西可以写,就是需要不断地实践。 9 | 10 | @[TOC] 11 | 12 | 13 | # 画一个朵花 14 | 15 | ```csharp 16 | import turtle 17 | t = turtle.Pen() 18 | def draw_leaf(): 19 | for i in range(2): 20 | for j in range(15): 21 | t.forward(5) 22 | t.right(6) 23 | t.right(90) 24 | t.goto(0,-150) 25 | t.left(90) 26 | t.forward(50) 27 | draw_leaf() 28 | t.forward(150) 29 | for i in range(6): 30 | draw_leaf() 31 | t.right(60) 32 | t.down() 33 | ``` 34 | 35 | 上图是画一朵花的程序,使用了函数来定义drawleaf,每一掰叶子由两条弧线组成,每一条弧线重复画15次,每次前进5步,右转6度。 36 | 37 | 看不懂看下步骤 38 | 39 | 40 | ![](https://img-blog.csdnimg.cn/20200529120443382.png) 41 | 42 | 43 | 这朵花由4部分组成,一个向上长50步的直线,一片叶子,长150步的直线和6片叶子组成的花。 44 | 45 | 46 | 47 | ![](https://img-blog.csdnimg.cn/20200529120855841.gif) 48 | 49 | 50 | 最后给叶子填充颜色,给花朵填充颜色。 51 | 52 | 53 | 54 | ```csharp 55 | import turtle 56 | t = turtle.Pen() 57 | def draw_leaf(): 58 | for i in range(2): 59 | for j in range(15): 60 | t.forward(5) 61 | t.right(6) 62 | t.right(90) 63 | t.goto(0,-150) 64 | t.left(90) 65 | t.forward(50) 66 | t.fillcolor("green") 67 | t.begin_fill() 68 | draw_leaf() 69 | t.end_fill() 70 | t.forward(50) 71 | t.right(270) 72 | t.fillcolor("green") 73 | t.begin_fill() 74 | draw_leaf() 75 | t.end_fill() 76 | t.right(90) 77 | t.forward(130) 78 | t.fillcolor("red") 79 | t.begin_fill() 80 | for i in range(6): 81 | draw_leaf() 82 | t.right(60) 83 | t.end_fill() 84 | t.down() 85 | ``` 86 | 87 | 88 | 89 | 90 | 91 | ![](https://img-blog.csdnimg.cn/20200529121458717.gif) 92 | 93 | 94 | 95 | # 酷炫的图形 96 | 97 | 98 | ```csharp 99 | import turtle 100 | 101 | for i in range(360): 102 | turtle.rt(1) 103 | turtle.circle(100,None,4) 104 | turtle.exitonclick() 105 | ``` 106 | 107 | ![](https://img-blog.csdnimg.cn/20200529122206413.gif) 108 | 109 | # 画时钟 110 | 111 | ![](https://img-blog.csdnimg.cn/20190419230504599.png) 112 | ![](https://img-blog.csdnimg.cn/20190419230608390.png?0) 113 | ![](https://img-blog.csdnimg.cn/20190419230646596.png) 114 | 115 | ``` 116 | # -*- coding:utf-8 -*- 117 | # time :2019/4/19 22:53 118 | # author: 毛利 119 | 120 | import turtle 121 | import datetime 122 | # 移动一段距离 123 | def skip(distance): 124 | """ 125 | 移动乌龟一段距离,不留痕迹 126 | :param distance: 像素 127 | :return: 128 | """ 129 | turtle.penup() 130 | turtle.forward(distance) 131 | turtle.pendown() 132 | 133 | def draw_clock(): 134 | # 先画表盘 135 | # 先画点 136 | # 移动一段距离,画一个点,然后退回 137 | # 转动6°,再移动一段距离,画一个点,然后退回 138 | # 循环 60次 139 | # 让乌龟的方向默认向上 140 | turtle.reset() 141 | turtle.hideturtle() 142 | for i in range(60): 143 | 144 | skip(160) 145 | # 根据 5格一个时钟 146 | if i % 5 == 0: 147 | turtle.pensize(7) 148 | # 画时钟 149 | turtle.forward(20) 150 | if i == 0: 151 | turtle.write(12, align='center', font=('Courier', 14, 'bold')) 152 | elif i == 25 or i == 30 or i == 35: 153 | skip(25) 154 | turtle.write(int(i/5), align='center', font=('Courier', 14, 'bold')) 155 | skip(-25) 156 | 157 | else: 158 | turtle.write(int(i/5), align='center', font=('Courier', 14, 'bold')) 159 | skip(-20) 160 | else: 161 | turtle.pensize(1) 162 | turtle.dot() 163 | skip(-160) 164 | turtle.right(6) 165 | 166 | 167 | def get_week(t): 168 | week = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'] 169 | return week[t.weekday()] 170 | 171 | 172 | def create_hand(length, name): 173 | turtle.reset() 174 | skip(-length * 0.1) 175 | turtle.begin_poly() 176 | turtle.forward(length * 1.1) 177 | turtle.end_poly() 178 | # 注册 179 | turtle.register_shape(name, turtle.get_poly()) 180 | hand = turtle.Turtle() 181 | hand.shape(name) 182 | hand.shapesize(1, 1, 3) 183 | return hand 184 | 185 | def run(): 186 | # 不停的获取时间 187 | t = datetime.datetime.today() 188 | bob.forward(65) 189 | bob.write(get_week(t), align='center', font=('Courier', 14, 'bold')) 190 | bob.back(130) 191 | bob.write(t.strftime('%Y-%m-%d'), align='center', font=('Courier', 14, 'bold')) 192 | bob.home() 193 | # 指针移动 194 | second = t.second + t.microsecond * 0.000001 195 | minute = t.minute + second/60 196 | hour = t.hour + minute/60 197 | turtle.tracer(True) 198 | second_hand.setheading(6*second) 199 | minute_hand.setheading(6*minute) 200 | hour_hand.setheading(30*hour) 201 | turtle.ontimer(run, 200) 202 | if __name__ == '__main__': 203 | # 画秒针,分针,时针 204 | turtle.mode('logo') 205 | turtle.hideturtle() 206 | global second_hand, minute_hand, hour_hand, bob 207 | 208 | second_hand = create_hand(135, 'second_hand') 209 | minute_hand = create_hand(125, 'minute_hand') 210 | hour_hand = create_hand(90, 'hour_hand') 211 | # 创建一个新的turtle对象,去循环的操作 212 | bob = turtle.Turtle() 213 | bob.hideturtle() 214 | bob.penup() 215 | 216 | turtle.tracer(False) 217 | draw_clock() 218 | run() 219 | 220 | turtle.mainloop() 221 | 222 | ``` 223 | ![](https://img-blog.csdnimg.cn/20190419230020836.gif) 224 | 225 | 对于urtle海龟画图,没必要研究这么深,就是小孩子的玩意,学习下,以后教下儿子就可以了。 226 | -------------------------------------------------------------------------------- /51-60/59、Python中的网络通信Socket.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/5/29 3 | 4 | 5 | 6 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 7 | 8 | 9 | 我预计写零基础学Python写到一百篇,这是第五十九篇。 10 | 11 | 12 | 今天,我要写的是Python中的网络通信Socket,写之前,先去[菜鸟教程](https://www.runoob.com/python/python-socket.html)看看,偷窥学习一下Socket通讯的基本方式。 13 | 14 | 15 | 16 | 17 | @[TOC] 18 | 19 | # TCP 20 | 21 | 我是化工专业的,TCP/IP这些怎么能不知道?在了解Socket前,我先给装个逼,介绍下TCP/IP。 22 | 23 | 24 | 计算机与网络设备两情侣要谈恋爱,相互通信,那么双方就必须有规则。基于相同的方法,不同的硬件、操作系统之间的通信,都需要一种规则。而我们就把这种规则称为协议(protocol)。 25 | 26 | 27 | TCP/IP 是互联网相关各类协议族的总称。TCP/IP是指TCP和IP这两种协议。TCP/IP是在IP协议的通信过程中,使用到的协议族的统称。 28 | 29 | 30 | 31 | # 七层 32 | 33 | 34 | TCP/IP协议族按层次分别为 应用层,传输层,网络层,数据链路层,物理层。可以按照不同的模型分4层或者是7层。 35 | 36 | 将TCP/IP分为5层,越靠下越接近硬件。 37 | 38 | 应用层,应用程序收到传输层的数据后,接下来就是要进行解读,解读必须要先规定好格式,而应用层就是规定应用程序的数据格式,主要协议有HTTP等。 39 | 40 | 传输层,该层为两台主机上的应用程序提供端到端的通信,传输层有两个传输协议为TCP(传输控制协议)和UDP(用户数据报协议),TCP是一个可靠的面向连接的协议,UDP是不可靠或者说无连接的协议。 41 | 42 | 网络层,决定如何将数据从发送方到接收方,是建立主机到主机的通信。 43 | 44 | 数据链路层,控制网络层与物理层之间的通信,主要功能是保证物理线路上进行可靠的数据传递。 45 | 46 | 物理层,该层负责物理传输,与链路有关,也与传输的介质有关。 47 | 48 | 49 | 50 | ![](https://img-blog.csdnimg.cn/2020052916170248.png) 51 | 52 | 53 | 54 | ![](https://img-blog.csdnimg.cn/20200529161811896.png) 55 | 56 | 57 | 58 | 59 | ![](https://img-blog.csdnimg.cn/20200529161821652.png) 60 | 61 | 别看我很牛逼,其实都是抄百度百科的,图片都是网络的,出自《图解HTTP》书籍的 62 | 63 | 64 | # 三次握手,四次挥手 65 | 66 | TCP三次握手,四次挥手,Runsen也不会怎么说,就把网上最通俗的图放在下面 了,还是别看我很牛逼,牛逼的是做图的大佬。 67 | 68 | 69 | 70 | ![](https://img-blog.csdnimg.cn/20200529162029248.png) 71 | 三次握手示意图: 72 | 73 | 74 | 75 | ![](https://img-blog.csdnimg.cn/2020052916222474.png) 76 | 77 | 三次握手过程: 78 | 79 | 80 | 第一次握手是在建立连接,客户端发送连接请求报文段,把标有SYN的数据包发给服务器端即为接收端。 81 | 82 | 第二次握手是服务器端即接收端收到客户端的SYN的报文段,同时发送标有SYN/ACK的数据包。 83 | 84 | 第三次握手是客户端收到服务器端的SYN/ACK的数据包后,向服务器端发送标有ACK的数据包。 85 | 86 | 87 | 88 | 89 | 四次握手其实就是把第二步变成了两步,所以就成了[四次握手」。 90 | 91 | 92 | 93 | 94 | ![](https://img-blog.csdnimg.cn/20200529162851493.png) 95 | 96 | 97 | # Socket 98 | 99 | 我是来偷窥Python中的网络通信Socket,不小心偷窥到了一个非常不错的Socket好图 100 | 101 | 102 | 103 | ![](https://img-blog.csdnimg.cn/20200529161222362.png) 104 | 105 | # 实现简单的通讯程序 106 | 服务端,server.py 107 | 108 | 109 | ```css 110 | #导入socket模块 111 | import socket 112 | #创建套接字 或使用server = socket.socket() 113 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 114 | #定义绑定的ip和端口,用元组定义 115 | ip_port = ('127.0.0.1', 8888) 116 | #绑定监听:bind(address),在AF_INET下,以元组(ip,port)的形式表示地址 117 | server.bind(ip_port) 118 | #设置最大连接数,默认为1 119 | server.listen(5) 120 | #不断接受连接:one by one 121 | while True: 122 | print("等待数据连接中……") 123 | #接受客服端数据请求 124 | conn, address = server.accept() 125 | ''' 126 | 向客服端返回信息 127 | (注意:python3.x以上,网络数据的发送接收都是byte类型, 128 | 发送接收String类型数据时需要对数据进行编码(发送:messages.enconde();接收后转为String类型:messages.deconde()),pyhon2.x则直接发送数据无须编码) 129 | ''' 130 | messages = "连接成功!" 131 | conn.send(messages.encode()) 132 | #计数信息条数 133 | count = 0 134 | #一个连接中,不断的接受客户端发来的数据 135 | while True: 136 | data = conn.recv(1024) 137 | #打印客户端发来的数据信息 138 | print(data.decode()) 139 | #判断是否退出当前连接,等在下一个连接 140 | if data == b'exit': 141 | break 142 | #处理客户端数据(如:响应请求等) 143 | count = count + 1 144 | string = "第" + str(count) + "条信息:" + data.decode() 145 | conn.send(string.encode()) 146 | #主动关闭连接 147 | conn.close() 148 | ``` 149 | 150 | 151 | 客户端,client.py 152 | 153 | 154 | 155 | ```css 156 | import socket 157 | 158 | #创建套接字 159 | client = socket.socket() 160 | #访问的服务器的ip和端口,用元组定义 161 | ip_port = ("127.0.0.1", 8888) 162 | #连接服务器主机 163 | client.connect(ip_port) 164 | #同一链接中,不断向服务器发生数据或请求 165 | while True: 166 | #接收服务器发送或响应的数据 167 | data = client.recv(1024) 168 | #打印接收的数据;python3.x以上数据要编码(发送:data.enconde();接收后转为String类型:data.deconde()) 169 | print(data.decode()) 170 | messages = input("请输入发生或请求的数据(exit退出):") 171 | client.send(messages.encode()) 172 | if messages == 'exit': 173 | break 174 | ''' 175 | #接收服务器发送或响应的数据 176 | data = client.recv(1024) 177 | #打印接收的数据;python3.x以上数据要编码,发送enconde();接收deconde() 178 | print(data.decode()) 179 | ''' 180 | #关闭连接 181 | client.close() 182 | ``` 183 | 184 | ![](https://img-blog.csdnimg.cn/20200529173904180.png) 185 | 186 | # 多线程通信 187 | TCP服务器与多个TCP客户端同时进行连续通信,只需要通过threading创建多线程任务handle_client就可以了。 188 | 189 | 190 | 191 | 192 | ```css 193 | import socket 194 | import threading 195 | import random 196 | 197 | 198 | def handle_client(): 199 | # 接受客户端请求链接 200 | client, address = server.accept() 201 | print("[*] Accept connection from: %s:%d" % (address[0], address[1])) 202 | messages = "Hello World!" 203 | client.send(messages.encode()) 204 | # 连续与当前连接的客户端通信 205 | while True: 206 | # 接受客户端数据 207 | request = (client.recv(1024)).decode() 208 | # 判断是否结束通信 209 | if request == 'exit': 210 | break 211 | print("[*] Received from %s:%d : %s" % (address[0], address[1], request)) 212 | # 发送响应信息给客户端 213 | client.send((str(random.randint(1, 1000)) + ":" + "ACK!").encode()) 214 | # 关闭当前连接 215 | client.close() 216 | 217 | 218 | if __name__ == "__main__": 219 | # 创建套接字 220 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 221 | # 定义绑定ip和端口 222 | ip = '127.0.0.1' 223 | port = 8888 224 | # 绑定监听 225 | server.bind((ip, port)) 226 | # 设置最大连接数,默认为1 227 | server.listen(5) 228 | print("[*] Listening on %s:%d" % (ip, port)) 229 | # 循环开启线程,接受多个客户端的链接通信 230 | while True: 231 | # 创建一个线程 232 | client_handler = threading.Thread(target=handle_client) 233 | # 开启线程 234 | client_handler.start() 235 | 236 | ``` 237 | ![](https://img-blog.csdnimg.cn/20200529175334353.png) 238 | 239 | 240 | python3.x以上,网络数据messages的发送接收都是byte类型,若要发送接收String类型数据时需要通过messages.enconde()对数据进行编码,接收后通过messages.deconde()转为String类型。pyhon2.x则直接发送数据无须编码。 241 | 242 | 243 | 244 | 代码来自:https://www.imooc.com/learn/1031 245 | -------------------------------------------------------------------------------- /51-60/60、网络通信Socket模块实现文件传输.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/5/29 3 | 4 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 5 | 6 | 我预计写零基础学Python写到一百篇,这是第六十篇,还剩四十篇 7 | 8 | 9 | 实现的效果如下的Gif所示,就是网络通信Socket模块实现文件传输。 10 | 11 | ![](https://img-blog.csdnimg.cn/20200530234705789.gif) 12 | 13 | @[TOC] 14 | 15 | # 服务端 16 | 17 | 18 | 首先需要获取本机ip,这里服务端采用多线程的方法,就是定义一个函数,然后用threading创建任务。客户端连接成功,接收客户端的请求信息,就是下载的文件名。所以需要判断,有输出文件字节数。然后在问用户是不是要下载,得到信息就使用 while True: 读文件的内容,再一个send。就是这么简单,看代码是不是就是这么回事。 19 | 20 | 21 | 22 | ```css 23 | import socket 24 | import os 25 | import threading 26 | 27 | # 获取本机ip 28 | def get_host_ip(): 29 | try: 30 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 31 | s.connect(('8.8.8.8', 80)) 32 | ip = s.getsockname()[0] 33 | finally: 34 | s.close() 35 | 36 | return ip 37 | 38 | # 处理客户端请求下载文件的操作(从主线程提出来的代码) 39 | def deal_client_request(ip_port, service_client_socket): 40 | # 连接成功后,输出“客户端连接成功”和客户端的ip和端口 41 | print("客户端连接成功", ip_port) 42 | # 接收客户端的请求信息【recv】 43 | file_name = service_client_socket.recv(1024) 44 | # 解码 45 | file_name_data = file_name.decode("utf-8") 46 | # 判断文件是否存在 47 | if os.path.exists(file_name_data): 48 | #输出文件字节数 49 | fsize = os.path.getsize(file_name_data) 50 | #转化为兆单位 51 | fmb = fsize/float(1024*1024) 52 | #要传输的文件信息 53 | senddata = "文件名:%s 文件大小:%.2fMB"%(file_name_data,fmb) 54 | #发送和打印文件信息【send】 55 | service_client_socket.send(senddata.encode("utf-8")) 56 | print("请求文件名:%s 文件大小:%.2f MB"%(file_name_data,fmb)) 57 | #接受客户是否需要下载【recv】 58 | options = service_client_socket.recv(1024) 59 | if options.decode("utf-8") == "y": 60 | # 打开文件 61 | with open(file_name_data, "rb") as f: 62 | # 计算总数据包数目 63 | nums = fsize/1024 64 | # 当前传输的数据包数目 65 | cnum = 0 66 | 67 | while True: 68 | file_data = f.read(1024) 69 | cnum = cnum + 1 70 | #progress = cnum/nums*100 71 | 72 | #print("当前已下载:%.2f%%"%progress,end = "\r") 73 | if file_data: 74 | # 只要读取到数据,就向客户端进行发送【send】 75 | service_client_socket.send(file_data) 76 | # 数据读完,退出循环 77 | else: 78 | print("请求的文件数据发送完成") 79 | break 80 | else: 81 | print("下载取消!") 82 | else: 83 | print("下载的文件不存在!") 84 | # 关闭服务当前客户端的套接字【close】 85 | service_client_socket.close() 86 | 87 | 88 | if __name__ == '__main__': 89 | # 获取本机ip 90 | print("TCP文件传输服务器,本机IP:" + get_host_ip()) 91 | 92 | # 把工作目录切换到data目录下 93 | os.chdir("./data") 94 | # 创建套接字【socket】 95 | tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 96 | # 绑定端口号【bind】 97 | tcp_server_socket.bind(("", 3356)) 98 | # 设置监听,将主动套接字变为被动套接字【listen】 99 | tcp_server_socket.listen(128) 100 | 101 | # 循环调用【accept】,可以支持多个客户端同时连接,和多个客户端同时下载文件 102 | while True: 103 | service_client_socket, ip_port = tcp_server_socket.accept() 104 | # 连接成功后打印套接字号 105 | #print(id(service_client_socket)) 106 | 107 | # 创建子线程 108 | sub_thread = threading.Thread(target=deal_client_request, args=(ip_port, service_client_socket)) 109 | # 启动子线程 110 | sub_thread.start() 111 | ``` 112 | 113 | 114 | 115 | 116 | 117 | 118 | # 客户端 119 | 客户端更简单,连接服务端,发送下载文件的请求,定义一个写入的文件夹,就是小儿科东西。不写了,看代码。 120 | 121 | 122 | 123 | ```css 124 | # -*- coding:utf-8 -*- 125 | # 多任务文件下载器客户端 126 | import socket 127 | import os 128 | 129 | if __name__ == '__main__': 130 | # 创建套接字【socket】 131 | tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 132 | # 和服务端连接【connect】 133 | server_ip = input("输入服务器IP:") 134 | tcp_client_socket.connect((server_ip, 3356)) 135 | # 发送下载文件的请求 136 | file_name = input("请输入要下载的文件名:") 137 | # 编码 138 | file_name_data = file_name.encode("utf-8") 139 | # 发送文件下载请求数据【send】 140 | tcp_client_socket.send(file_name_data) 141 | # 接收要下载的文件信息【recv】 142 | file_info = tcp_client_socket.recv(1024) 143 | # 文件信息解码 144 | info_decode = file_info.decode("utf-8") 145 | print(info_decode) 146 | #获取文件大小 147 | fileszie = float(info_decode.split(':')[2].split('MB')[0]) 148 | fileszie2 = fileszie*1024 149 | # 是否下载?输入y 确认 输入q 取消 150 | opts = input("是否下载?(y 确认 q 取消)") 151 | if opts == 'q': 152 | print("下载取消!程序退出") 153 | else: 154 | print("正在下载 >>>>>>") 155 | #向服务器确认正在下载【send】 156 | tcp_client_socket.send(b'y') 157 | 158 | recvpath = "./receive/" 159 | if not os.path.exists(recvpath): 160 | os.mkdir(recvpath) 161 | 162 | # 把数据写入到文件里 163 | with open(recvpath + file_name, "wb") as file: 164 | #目前接收到的数据包数目 165 | cnum = 0 166 | 167 | while True: 168 | # 循环接收文件数据【recv】 169 | file_data = tcp_client_socket.recv(1024) 170 | # 接收到数据 171 | if file_data: 172 | # 写入数据 173 | file.write(file_data) 174 | cnum = cnum+1 175 | #progress =cnum/fileszie2*100 176 | #print("当前已下载:%.2f%%"%progress,end = "\r") 177 | # 接收完成 178 | else: 179 | print("下载结束!") 180 | break 181 | # 关闭套接字【close】 182 | tcp_client_socket.close() 183 | ``` 184 | 185 | -------------------------------------------------------------------------------- /61-70/61、Python中的smtplib和email实现邮件发送.md: -------------------------------------------------------------------------------- 1 | ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pbWdrci5jbi1iai51ZmlsZW9zLmNvbS9mOGM0YjhmZC0zZGY5LTQ0NDktOGVhMi1lMWJhNjE5MGY3MTEucG5n?x-oss-process=image/format,png) 2 | 3 | 4 | 5 | 6 | @Author : By Runsen 7 | 8 | 9 | 10 | 11 | 在Python中分别有两个库实现发送邮件,分别是smtplib和email。 12 | 13 | 14 | smtplib是用来发送邮件用的,email是用来构建邮件内容的。 15 | 16 | 17 | 18 | 19 | 下面是具体使用: 20 | 21 | 22 | ```python 23 | import smtplib 24 | 25 | server = smtplib.SMTP() 26 | server.connect(host, port) 27 | 28 | 29 | #连接(connect)指定的服务器,host是指定连接的邮箱服务器,通过搜索“xx邮箱服务器地址”,就可以找到 30 | #例如QQ邮箱的SMTP服务器地址是:smtp.qq.com。port是端口,一般情况下SMTP默认端口号为25 31 | 32 | server.login(username, password) 33 | #username:登录邮箱的用户名 34 | #password:授权码 35 | server.sendmail(sender, to_addr, msg.as_string()) 36 | 37 | #from_addr:邮件发送地址,就是上面的username 38 | #to_addr:邮件收件人地址 39 | #msg.as_string():为一个字符串类型 ,as_string()是将发送的信息msg变为字符串类型。 40 | server.quit() 41 | #退出服务器,结束SMTP会话 42 | ``` 43 | 44 | 备注:SMTP 协议是由源服务器到目的地服务器传送邮件的一组规则。 45 | 46 | 47 | 48 | email 模块:也就是用来写邮件内容的模块。这个内容可以是纯文本、HTML内容、图片、附件等多种形式。 49 | 50 | 51 | 52 | ```python 53 | import email 54 | from email.mime.text import MIMEText 55 | #纯文本或HTML页面 56 | fromemail.mime.image import MIMEImage 57 | #内容形式为图片 58 | fromemail.mime.multipart import MIMEMultipart 59 | #多形式组合,可包含文本和附件 60 | 61 | MIMEText方法: 62 | MIMEText(msg,type,chartset) 63 | # msg:文本内容,可自定义 64 | # type:文本类型,默认为plain(纯文本) 65 | # chartset:文本编码,中文为“utf-8” 66 | ``` 67 | 68 | 69 | 70 | # 测试Demo 71 | 72 | 73 | 这是我把自己的username和password省略了 74 | 75 | ```python 76 | # 测试 77 | import smtplib 78 | from email.mime.textimport MIMEText 79 | 80 | username='你的@qq.com' 81 | password='XXXXXXXXX' 82 | sender='发给谁@qq.com' 83 | to_addr='run24118cajie@163.com' 84 | msg=MIMEText('你好这是用python发的一封邮件','plain','utf-8') 85 | 86 | server =smtplib.SMTP() 87 | server.connect('smtp.qq.com', 25) 88 | server.login(username,password) 89 | server.sendmail(sender,to_addr, msg.as_string()) 90 | server.quit() 91 | ``` 92 | 93 | 发送成功 94 | 95 | 96 | ![](https://img-blog.csdnimg.cn/20190505234114734.png) 97 | 98 | # 标准发邮件的格式 99 | 100 | 101 | ```python 102 | # 首先,主送、抄送就是两个用逗号分割的字符串,subject是标题,正文是context,支持html。 103 | from email import encoders 104 | from email.header import Header 105 | from email.mime.text import MIMEText 106 | from email.mime.base import MIMEBase 107 | from email.mime.multipart import MIMEMultipart 108 | import smtplib 109 | import os 110 | 111 | from_addr = 'xxxxx@qq.com' 112 | password = 'xxxxx' 113 | smtp_server = 'smtp.qq.com' 114 | def sendmail(to_addr, cc_addr, subject, content, attach_full_path): 115 | # create a message 116 | msg = MIMEMultipart() 117 | msg['From'] = from_addr 118 | msg['To'] = to_addr 119 | msg['Cc'] = cc_addr 120 | msg['Subject'] = Header(subject, 'utf-8').encode() 121 | # 正文: 122 | msg.attach(MIMEText(content, 'html', 'utf-8')) 123 | # 附件 124 | (filepath, file) = os.path.split(attach_full_path) 125 | with open(attach_full_path + '', 'rb') as f: 126 | # 设置附件的MIME和文件名: 127 | mime = MIMEBase('application', 'octet-stream', filename=file) 128 | # 加上必要的头信息: 129 | mime.add_header('Content-Disposition', 'attachment', filename=file) 130 | # 把附件的内容读进来: 131 | mime.set_payload(f.read()) 132 | # 用Base64编码: 133 | encoders.encode_base64(mime) 134 | # 添加到MIMEMultipart: 135 | msg.attach(mime) 136 | # 发送邮件 137 | server = smtplib.SMTP(smtp_server, 25) 138 | server.set_debuglevel(1) 139 | server.starttls() 140 | server.login(from_addr, password) 141 | server.sendmail(from_addr, to_addr.split(',') + cc_addr.split(','), msg.as_string()) 142 | server.quit() 143 | 144 | ``` 145 | -------------------------------------------------------------------------------- /61-70/62、多线程真的比单线程快?那是因为你不知道Python中的全局解释器锁GIL.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | @Author:Runsen 4 | 5 | @Date:2020/6/4 6 | 7 | 8 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 9 | 10 | 前面文章,点击下面链接 11 | 12 | [我的Python教程,不断整理,反复学习](https://blog.csdn.net/weixin_44510615/article/details/106162925) 13 | 14 | 15 | 16 | 17 | 18 | 今日,我决定继续更新Python教程,介绍的是Python 中的全局解释器锁GIL。已经到了六十二,还剩下区区三十八篇。长得帅就是我的动力,不对,明明就是太穷了才是我的动力。 19 | 20 | @[toc] 21 | 22 | 23 | # 多线程比单线程快? 24 | 25 | 26 | 在Python中,可以通过多进程、多线程和多协程来实现多任务。这个不清楚,看看我之前的文章,难道多线程比单线程快? 27 | 28 | 29 | 你竟然敢质疑我,我太开心了。我得用一个例子证明我自己得观点。 30 | 31 | ```python 32 | ''' 33 | @Author: Runsen 34 | @微信公众号: 润森笔记 35 | @博客: https://blog.csdn.net/weixin_44510615 36 | @Date: 2020/6/4 37 | ''' 38 | 39 | import threading, time 40 | def my_counter(): 41 | i = 0 42 | for _ in range(100000000): 43 | i = i+1 44 | return True 45 | 46 | def main1(): 47 | thread_ary = {} 48 | start_time = time.time() 49 | for tid in range(2): 50 | t = threading.Thread(target=my_counter) 51 | t.start() 52 | t.join() # 第一次循环的时候join方法引起主线程阻塞,但第二个线程并没有启动,所以两个线程是顺序执行的 53 | 54 | print("单线程顺序执行total_time: {}".format(time.time() - start_time)) 55 | 56 | def main2(): 57 | thread_ary = {} 58 | start_time = time.time() 59 | for tid in range(2): 60 | t = threading.Thread(target=my_counter) 61 | t.start() 62 | thread_ary[tid] = t 63 | 64 | for i in range(2): 65 | thread_ary[i].join() # 两个线程均已启动,所以两个线程是并发的 66 | 67 | print("多线程执行total_time: {}".format(time.time() - start_time)) 68 | 69 | if __name__ == "__main__": 70 | main1() 71 | main2() 72 | ``` 73 | 74 | 运行结果 75 | 76 | ```python 77 | 单线程顺序执行total_time: 17.754502773284912 78 | 多线程执行total_time: 20.01178550720215 79 | ``` 80 | 81 | 我怕你说我乱得出来得结果,我还是截个图看清楚点 82 | 83 | 84 | ![](https://img-blog.csdnimg.cn/20200604114813483.png) 85 | 86 | 没错, Python 的线程失效了,没有起到并行计算的作用。 87 | 88 | 89 | 90 | Python 的线程,的确封装了底层的操作系统线程,在 Linux 系统里是 Pthread(全称为 POSIX Thread),而在 Windows 系统里是 Windows Thread。另外,Python 的线程,也完全受操作系统管理,比如协调何时执行、管理内存资源、管理中断等等。所以,虽然 Python 的线程和 C++ 的线程本质上是不同的 91 | 92 | 93 | 94 | # GIL并不是Python的特性 95 | 96 | GIL 的概念用简单的一句话来解释,就是**「任一时刻,无论线程多少,单一 CPython 解释器只能执行一条字节码」**。这个定义需要注意的点: 97 | 98 | 首先需要明确的一点是**GIL并不是Python的特性**,它是在实现Python解析器(CPython)时所引入的一个概念。 99 | 100 | 101 | C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。 102 | 103 | Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。 104 | 105 | 106 | **其他 Python 解释器不一定有 GIL**。例如 Jython (JVM) 和 IronPython (CLR) 没有 GIL,而 CPython,PyPy 有 GIL; 107 | 108 | 109 | 因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:**GIL并不是Python的特性,Python完全可以不依赖于GIL** 110 | 111 | 112 | 113 | 114 | 115 | 116 | # GIL本质就是一把互斥锁 117 | 118 | GIL本质就是一把互斥锁,既然是互斥锁,所有互斥锁的本质都一样,都是将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。 119 | 120 | 可以肯定的一点是:保护不同的数据的安全,就应该加不同的锁。 121 | 122 | 123 | 124 | 125 | 126 | GIL 是工作原理:下面这张图,就是一个 GIL 在 Python 程序的工作示例。其中,Thread 1、2、3 轮流执行,每一个线程在开始执行时,都会锁住 GIL,以阻止别的线程执行;同样的,每一个线程执行完一段后,会释放 GIL,以允许别的线程开始利用资源。 127 | 128 | ![](https://img-blog.csdnimg.cn/20200604115658938.png) 129 | 130 | 131 | 细心的你可能会发现一个问题:为什么 Python 线程会去主动释放 GIL 呢?毕竟,如果仅仅是要求 Python 132 | 133 | CPython 使用引用计数来管理内存,所有 Python 脚本中创建的实例,都会有一个引用计数,来记录有多少个指针指向它。当引用计数只有 0 时,则会自动释放内存。 134 | 135 | ```python 136 | import sys 137 | a = [] 138 | b = a 139 | print(sys.getrefcount(a)) 140 | >>> 3 141 | ``` 142 | 143 | 144 | 这个例子中,a 的引用计数是 3,因为有 a、b 和作为参数传递的 getrefcount 这三个地方,都引用了一个空列表。这样一来,如果有两个 Python 线程同时引用了 a,就会造成引用计数的 race condition,引用计数可能最终只增加 1,这样就会造成内存被污染。因为第一个线程结束时,会把引用计数减少 1,这时可能达到条件释放内存,当第二个线程再试图访问 a 时,就找不到有效的内存了。 145 | 146 | 147 | # 计算密集型 148 | 149 | 150 | 我们先来看一个简单的计算密集型示例: 151 | 152 | ```python 153 | import time 154 | COUNT = 50_000_000 155 | 156 | def count_down(): 157 | global COUNT 158 | while COUNT > 0: 159 | COUNT -= 1 160 | 161 | s = time.perf_counter() 162 | count_down() 163 | c = time.perf_counter() - s 164 | print('time taken in seconds - >:', c) 165 | 166 | time taken in seconds - >: 9.2957003 167 | 168 | ``` 169 | 170 | 171 | 这个是单线程, 时间是9s, 下面我们用两个线程看看结果又如何: 172 | 173 | ```python 174 | import time 175 | from threading import Thread 176 | 177 | COUNT = 50_000_000 178 | 179 | def count_down(): 180 | global COUNT 181 | while COUNT > 0: 182 | COUNT -= 1 183 | 184 | s = time.perf_counter() 185 | t1 = Thread(target=count_down) 186 | t2 = Thread(target=count_down) 187 | t1.start() 188 | t2.start() 189 | t1.join() 190 | t2.join() 191 | c = time.perf_counter() - s 192 | print('time taken in seconds - >:', c) 193 | 194 | time taken in seconds - >: 17.110625 195 | 196 | ``` 197 | 其实结果一点也不奇怪, 我们程序主要的操作就是在计算, cpu没有等待, 而改为多线程后, 增加了线程后, 在线程之间频繁的切换,增大了时间开销, 时间当然会增加了。 198 | 199 | 200 | 201 | 202 | **对于io密集型工作(爬虫),多线程可以大幅提高代码效率。对CPU计算密集型(数据分析),多线程的效率可能比单线程还略低。** 203 | -------------------------------------------------------------------------------- /61-70/63、面试最常见的问题:Python的垃圾回收机制到底是怎么样的?.md: -------------------------------------------------------------------------------- 1 |  2 | @Author:Runsen 3 | 4 | @Date:2020/6/4 5 | 6 | 7 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 8 | 9 | 前面文章,点击下面链接 10 | 11 | [我的Python教程,不断整理,反复学习](https://blog.csdn.net/weixin_44510615/article/details/106162925) 12 | 13 | 14 | 15 | 16 | 17 | 今日,我决定继续更新Python教程,介绍的是Python的垃圾回收机制。已经到了六十三,还剩下区区三十七篇。长得帅就是我的动力,不对,明明就是太穷了才是我的动力。 18 | ![](https://img-blog.csdnimg.cn/2020060418232457.png) 19 | 20 | 21 | @[toc] 22 | 23 | 24 | 25 | 参考:[极客时间Python专栏](https://time.geekbang.org/column/article/104265) 26 | 27 | 28 | 在这篇文章,带着这个问题来一直往下看:怎么知道一个对象,是否永远都不能被调用了呢? 29 | 30 | 31 | 32 | # 引用计数 33 | 在一些代码中,如果存在一些变量但是没有用,会造成内存空间,因此叫做垃圾,所以要回收。 34 | 35 | 引用计数也是一种最直观,最简单的垃圾收集技术。原理非常简单,每一个对象都包含了两个头部信息,一个是类型标志符,标识这个对象的类型;另一个是计数器,记录当前指向该对象的引用数目,表示这个对象被多少个变量名所引用。 36 | 37 | 38 | 39 | 用来记录对象被引用的次数,每当对象被创建或者被引用时将该对象的引用次数加一,当对象的引用被销毁时该对象的引用次数减一,当对象的引用次数减到零时说明程序中已经没有任何对象持有该对象的引用,换言之就是在以后的程序运行中不会再次使用到该对象了,那么其所占用的空间也就可以被释放了了。 40 | 41 | 42 | 下面是查看引用计数的方法, 43 | 44 | ```python 45 | print(sys.getrefcount()) 46 | ``` 47 | 48 | 注意调用getrefcount()函数会临时增加一次引用计数,得到的结果比预期的多一次。 49 | 50 | 我们通过一些例子来看下,可以使python对象的引用计数增加或减少的场景,代码来自专栏。 51 | 52 | 53 | 54 | ```python 55 | import sys 56 | a = [] 57 | # 两次引用,一次来自 a,一次来自 getrefcount 58 | print(sys.getrefcount(a)) 59 | def func(a): 60 | # 四次引用,a,python 的函数调用栈,函数参数,和 getrefcount 61 | print(sys.getrefcount(a)) 62 | 63 | func(a) 64 | # 两次引用,一次来自 a,一次来自 getrefcount,函数 func 调用已经不存在 65 | print(sys.getrefcount(a)) 66 | 67 | ########## 输出 ########## 68 | 2 69 | 4 70 | 2 71 | ``` 72 | 我认为这个代码是这篇文章最容易看懂的代码 73 | 74 | # 内存空间 75 | 我们来看看下面的例子。代码来自专栏 76 | 77 | 78 | 79 | 80 | 81 | ```python 82 | import os 83 | import psutil 84 | 85 | 86 | # 显示当前 python 程序占用的内存大小 87 | def show_memory_info(hint): 88 | pid = os.getpid() 89 | p = psutil.Process(pid) 90 | 91 | info = p.memory_full_info() 92 | memory = info.uss / 1024. / 1024 93 | print('{} memory used: {} MB'.format(hint, memory)) 94 | 95 | 96 | def func(): 97 | show_memory_info('initial') 98 | a = [i for i in range(10000000)] 99 | show_memory_info('after a created') 100 | 101 | func() 102 | show_memory_info('finished') 103 | 104 | ########## 输出 ########## 105 | 106 | initial memory used: 20.82421875 MB 107 | after a created memory used: 408.125 MB 108 | finished memory used: 21.10546875 MB 109 | ``` 110 | 111 | 112 | 如果代码运行遇到psutil.AccessDenied: psutil.AccessDenied (pid=14204),解决的方法就是用管理员身份打开。 113 | 114 | 115 | 函数 show_memory_info用来获取程序占用的内存空间大小,在 func函数中创建一个包含一百万个整数的列表。从打印结果我们可以看出,创建完列表之后程序耗用的内存空间上升到了 408.125 MB。而当函数 foo 调用完毕之后内存消耗又恢复正常。 116 | 117 | 这是因为我们在函数 func中创建的 list 变量是局部变量,其作用域是当前函数内部,一旦函数执行完毕,局部变量的引用会被自动销毁,即其引用次数会变为零,所占用的内存空间也会被回收。(代码来自专栏,但是领悟来自于Runsen) 118 | 119 | 120 | ```python 121 | 122 | def func(): 123 | show_memory_info('initial') 124 | a = [i for i in derange(10000000)] 125 | show_memory_info('after a created') 126 | return a 127 | 128 | a = func() 129 | show_memory_info('finished') 130 | 131 | ########## 输出 ########## 132 | initial memory used: 20.8515625 MB 133 | after a created memory used: 408.1484375 MB 134 | finished memory used: 408.1484375 MB 135 | ``` 136 | 137 | 138 | 稍加改造之后,即使 func函数调用结束其所消耗的内存也未被释放。 139 | 140 | 主要是因为我们将函数 func内部产生的列表返回并在主程序中接收之后,这样就会导致该列表的引用依然存在,该对象后续仍有可能被使用到,垃圾回收便不会回收该对象。 141 | 142 | 143 | 144 | # 计数增加和减少 145 | 下面引用计数增加的场景: 146 | 147 | - 对象被创建并赋值给某个变量,比如:a = 'ABC' 148 | - 变量间的相互引用(相当于变量指向了同一个对象),比如:b=a 149 | - 变量作为参数传到函数中。比如:ref_method(a), 150 | - 将对象放到某个容器对象中(列表、元组、字典)。比如:c = [1, a, 'abc'] 151 | 152 | 引用计数减少的场景: 153 | 154 | - 当一个变量离开了作用域,比如:函数执行完成时,执行方法前后的引用计数保持不变,这就是因为方法执行完后,对象的引用计数也会减少,如果在方法内打印,则能看到引用计数增加的效果。 155 | - 对象的引用变量被销毁时,比如del a 或者 del b。注意如果del a,再去获取a的引用计数会直接报错。 156 | - 对象被从容器对象中移除,比如:c.remove(a) 157 | - 直接将整个容器销毁,比如:del c 158 | - - 对象的引用被赋值给其他对象,相当于变量不指向之前的对象,而是指向了一个新的对象,这种情况,引用计数肯定会发生改变。(排除两个对象默认引用计一致的场景)。 159 | 160 | 161 | ```python 162 | import sys 163 | 164 | def ref_method(str): 165 | print(sys.getrefcount(str)) 166 | print("我调用了{}".format(str)) 167 | print('方法执行完了') 168 | 169 | def ref_count(): 170 | # 引用计数增加的场景 171 | print('测试引用计数增加') 172 | a = 'ABC' 173 | print(sys.getrefcount(a)) 174 | b = a 175 | print(sys.getrefcount(a)) 176 | ref_method(a) 177 | print(sys.getrefcount(a)) 178 | c = [1, a, 'abc'] 179 | print(sys.getrefcount(a)) 180 | 181 | # 引用计数减少的场景 182 | print('测试引用计数减少') 183 | del b 184 | print(sys.getrefcount(a)) 185 | c.remove(a) 186 | print(sys.getrefcount(a)) 187 | del c 188 | print(sys.getrefcount(a)) 189 | a = 783 190 | print(sys.getrefcount(a)) 191 | 192 | if __name__ == '__main__': 193 | ref_count() 194 | 195 | 测试引用计数增加 196 | 7 197 | 8 198 | 10 199 | 我调用了ABC 200 | 方法执行完了 201 | 8 202 | 9 203 | 测试引用计数减少 204 | 8 205 | 7 206 | 7 207 | 4 208 | ``` 209 | 210 | 211 | 212 | 213 | # 释放内存 214 | 215 | 216 | 217 | python给我们提供了手动释放内存的方法 gc.collect() 218 | 219 | 220 | 221 | ```python 222 | 223 | import gc 224 | import os 225 | import psutil 226 | # 显示当前 python 程序占用的内存大小 227 | def show_memory_info(hint): 228 | pid = os.getpid() 229 | p = psutil.Process(pid) 230 | 231 | info = p.memory_full_info() 232 | memory = info.uss / 1024. / 1024 233 | print('{} memory used: {} MB'.format(hint, memory)) 234 | 235 | 236 | 237 | def func(): 238 | show_memory_info('initial') 239 | a = [i for i in range(10000000)] 240 | b = [i for i in range(10000000)] 241 | show_memory_info('after a, b created') 242 | a.append(b) 243 | b.append(a) 244 | 245 | func() 246 | gc.collect() 247 | show_memory_info('finished') 248 | 249 | ########## 输出 ########## 250 | initial memory used: 26.16796875 MB 251 | after a, b created memory used: 802.03515625 MB 252 | finished memory used: 27.5 MB 253 | ``` 254 | 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /61-70/64、开始刷Leetcode之旅(Python版本).md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | 3 | @Date:2020/6/4 4 | 5 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 6 | 7 | 8 | 9 | 从大一写Python文章,到现在其都有上百篇,现在到了六十四,我觉得这个时候应该去刷题了,其实很多学Python的都不是专科的,都是给培训机构宣传牛逼,其实在编程语言中,Python是最简单,最没有难度的编程语言。我在之后的文章都更新数据结构和Leetcode。都用Python解决的方法。其实Leetcode上的一部分题我都基本刷过,那么我就开始吧。 10 | 11 | 12 | 13 | 14 | @[toc] 15 | 16 | 17 | # 注册Leetcode账号 18 | 19 | 20 | 目前Leetcod有国际和中文的两个版本,下图就是我的中文版本,刷的不够,其实我也挺菜的。这个是中文的网址:https://leetcode-cn.com/problemset/all/ 21 | ![](https://img-blog.csdnimg.cn/20200605154056199.png) 22 | 23 | 下图就是我的国际版本,其实我主要在国际版混日子,刷了100多题,其实我很菜的。这是它的官网,https://leetcode.com。 24 | ![](https://img-blog.csdnimg.cn/20200605154019683.png) 25 | 26 | 27 | 不同点,非中国区的人多点,做完了也可以参考下老外是用什么思路做的,挺好的。所以你比要到非中国区,看看老外是怎么干的。 28 | 29 | 30 | 31 | # Pycharm装Leetcode插件 32 | 33 | 34 | 直接打开Pycharm,依次点击File-Settings-Plugins-Maketplace ,然后在搜索框输入leetcode,就会显示我们的leetcode editor插件,点击Install,跳出的界面点检accept,之后等待安装好就行了 35 | 36 | 37 | 我这个是安装好的了。 38 | ![](https://img-blog.csdnimg.cn/20200605155930517.png) 39 | 40 | 如果你用vscode也是一样,给我装vscode插件。 41 | 42 | ![](https://img-blog.csdnimg.cn/20200605160057766.png) 43 | 44 | 因为,我习惯Python用Pycharm,Java用IDEA,前端用vscode。所以这Runsen使用Pycharm。 45 | 46 | 47 | 48 | 然后就是登陆我的Leetcode账号。 49 | 50 | ![](https://img-blog.csdnimg.cn/20200605160401821.png) 51 | 52 | 然后就是登录你的账号。 53 | 54 | ![](https://img-blog.csdnimg.cn/20200605160506779.png) 55 | 56 | 57 | 58 | 点击右下角,选择刷新或者加载按钮,就可以获取到leetcode中题库了,根据颜色可以区分题目的难易程度: 59 | 绿色-中等; 60 | 黄色-简单; 61 | 红色-困难 62 | 63 | 64 | ![](https://img-blog.csdnimg.cn/20200605160638614.png) 65 | 66 | 更详细的使用说明参考文档:https://github.com/shuzijun/leetcode-editor 67 | 68 | 69 | # 怎么刷Leetcode 70 | ## 以前菜鸡的我做法 71 | 以前Runsen的做法: 72 | 1. 打开leetcode 73 | 2. 启动Pycharm 74 | 3. 开始思考,冷静分析 75 | 4. 打开leetcode官网的评论区答案,寻找跟我一样的菜逼 76 | 5. 满意离开评论区 77 | 78 | 79 | 上面其实都是像之前的我,都是菜鸡,其实现在我还是菜鸡。 80 | 81 | ## 分类归纳/总结 82 | 刷Leetcode,必须分类归纳/总结 83 | 84 | (1)、数组和相关题型 85 | 86 | 对于算法题,还是有很多种题型需要去总结的,如果你懂这个题型,以后遇到类似的题,相信很快就能做出来的。有哪些题型可以总结呢?答是非常多,例如: 87 | 88 | (1)、给你一个非负数的数组,求最大子数组和的长度 89 | 90 | 这算是一个题型,关于这个题型,有很多种变形、拓展,这里建议一起归纳总结,例如: 91 | 92 | (2)、刚才给的数组是非负数的,现在变一下,给的数组是可正可负。 93 | 94 | 还能继续拓展吗?答是可以的,例如: 95 | 96 | (3)、给你个矩阵(即二维数组),求最大子矩阵和的面积 97 | 98 | 还有吗?有,例如刚才是求最大和,现在我改成求最大乘积。 99 | 100 | 我其实是想告诉你,对于前期的学习,我建议分类刷题,总结题型,像我上面举的这些例子,遇到相似的,就直接可以秒杀了,因为这类题,没啥边界或者规律。 101 | 102 | 103 | 关于题型的,还是很多的,我这里无法一一给你列举,只能靠你刷题的过程中,进行分类、总结。不过我可以给你推荐一些资料,后面推荐。下面我在说一些题型吧。 104 | 105 | 106 | ## 三分学七分练 107 | 108 | 三分学七分练,这是我从极客时间的覃超,前Facebook工程师,传授的方法。 109 | 110 | 111 | ![](https://img-blog.csdnimg.cn/20200605161852501.png) 112 | 113 | 114 | 115 | 俗话说:学钢琴,三分学,七分练。其中练习是最为重要的一个环节,想学好钢琴必须得时常练习且多多益善。 116 | 117 | 118 | 119 | 所以刷Leetcode的最大的弊端都是:缺乏练习。 120 | 121 | 122 | 123 | # 两数相加 124 | 125 | 那么我们就开始干他,Leetcode中的Hello World就是两数相加。 126 | 127 | 128 | 这个题是我2018年遇见了,现在2020年半,两年多时间。 129 | 130 | 131 | ```python 132 | #给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 133 | # 134 | # 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 135 | # 136 | # 示例: 137 | # 138 | # 给定 nums = [2, 7, 11, 15], target = 9 139 | # 140 | #因为 nums[0] + nums[1] = 2 + 7 = 9 141 | #所以返回 [0, 1] 142 | # 143 | # Related Topics 数组 哈希表 144 | 145 | ``` 146 | 147 | 148 | 其实这一题真的很简单,无非就是将“昂贵”的时间复杂度转换成“廉价”的空间复杂度,把双重遍历,变成一次遍历。 149 | 150 | 这里最佳的方法就是使用字典。下面是我去年的代码,就是三种的解决方法。 151 | 152 | 153 | 列表解法 154 | ``` 155 | def twoSum_1( nums, target): 156 | result = [] 157 | for i in range (len(nums)): 158 | onenum = nums[i] 159 | twonum = target - onenum 160 | if twonum in nums: 161 | j = nums.index(twonum) 162 | if i != j: 163 | result.append(i) 164 | result.append(j) 165 | return result 166 | ``` 167 | 字典解法 168 | ``` 169 | def twoSum_2(nums,target): 170 | dict={} 171 | for i in range(len(nums)): 172 | m = nums[i] 173 | if target-m in dict: 174 | return [dict[target-m],i] 175 | dict[m] = i 176 | ``` 177 | 字典推导式 178 | ``` 179 | def twosum_3(nums,target): 180 | l = len(nums) 181 | dict = {nums[i]:i for i in range(l)} 182 | print(dict) 183 | for j in range(l): 184 | a = nums[j] 185 | b = target - a 186 | if b in dict and j != dict[b]: 187 | return [j,dict[b]] 188 | ``` 189 | 190 | 191 | 192 | # 关于学习课程 193 | 194 | 195 | 196 | 在之前深入Leetcode,学了下面的课程 197 | 198 | ![](https://img-blog.csdnimg.cn/2020060516351882.png) 199 | ![](https://img-blog.csdnimg.cn/20200605163542636.png) 200 | 201 | 202 | ![](https://img-blog.csdnimg.cn/20200605163457240.png) 203 | 204 | 205 | 因此下面的文章主要是总结回顾之前学到东西,只有不断地反复学习,才有新的突破 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /61-70/69、Python _ Leetcode链表系列(中篇).md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/6/19 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 (作者:Runsen ) 5 | 6 | 7 | 8 | 9 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 10 | 前面文章,点击下面链接 11 | 12 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 13 | 14 | 今日,我决定继续更新Python教程,今天就开始了六十九、Python | Leetcode链表系列(中篇)。 15 | 16 | 17 | 18 | @[toc] 19 | 20 | 21 | 22 | 23 | 24 | 25 | # LeetCode 第21题:合并两个有序链表 26 | 27 | ```java 28 | #将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 29 | # 示例: 30 | # 31 | # 输入:1->2->4, 1->3->4 32 | #输出:1->1->2->3->4->4 33 | # 34 | # Related Topics 链表 35 | ``` 36 | 37 | 38 | 这个解决的方法使用递归,如果L1为空就返回L2,L2为空返回L1,L1的val<=L2的val,那么继续递归 39 | ```java 40 | # Definition for singly-linked list. 41 | # class ListNode: 42 | # def __init__(self, x): 43 | # self.val = x 44 | # self.next = None 45 | 46 | 47 | class Solution(object): 48 | def mergeTwoLists(self, l1, l2): 49 | """ 50 | :type l1: ListNode 51 | :type l2: ListNode 52 | :rtype: ListNode 53 | """ 54 | #递归的结束点就是L1或者L2为空就返回 55 | #如果L1为空就返回L2,L2为空返回L1 56 | # if not (l1 and l2): 57 | # return l1 if l1 else l2 58 | if not l1: 59 | return l2 60 | elif not l2: 61 | return l1 62 | #L1的val<=L2的val,那么继续递归 63 | #当前L1的next指向一个递归函数 64 | #意思是L1的下一个和L2哪个大,就作为当前L1的next 65 | elif l1.val<=l2.val: 66 | l1.next = self.mergeTwoLists(l1.next,l2) 67 | return l1 68 | else: 69 | l2.next = self.mergeTwoLists(l1,l2.next) 70 | return l2 71 | 72 | ``` 73 | 74 | 75 | 76 | 77 | 78 | ![](https://img-blog.csdnimg.cn/20200628114647839.png) 79 | 80 | 81 | # LeetCode 第 23 题:合并 k 个排序链表 82 | ```java 83 | #合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 84 | # 示例: 85 | # 输入: 86 | #[ 87 | # 1->4->5, 88 | # 1->3->4, 89 | # 2->6 90 | #] 91 | #输出: 1->1->2->3->4->4->5->6 92 | # Related Topics 堆 链表 分治算法 93 | ``` 94 | 95 | 96 | 第1种法就是常规思路,直接将所有的元素取出,然后排个序,再重组就达到了目的。 97 | 98 | 99 | 遍历所有链表,将所有节点的值放到一个数组中。将这个数组排序,然后遍历所有元素得到正确顺序的值。用遍历得到的值,创建一个新的有序链表。 100 | 101 | 102 | 时间复杂度:$O(N\log N)$ ,其中 N 是节点的总数目 103 | 104 | 105 | 106 | 空间复杂度:$O(N)$。 107 | 108 | 排序花费$O(N)$空间(这取决于你选择的算法)。 109 | 创建一个新的链表花费 $O(N)$的空间。 110 | 111 | ```python 112 | # Definition for singly-linked list. 113 | # class ListNode: 114 | # def __init__(self, x): 115 | # self.val = x 116 | # self.next = None 117 | 118 | 119 | class Solution: 120 | def mergeKLists(self, lists: List[ListNode]) -> ListNode : 121 | """ 122 | :type lists: List[ListNode] 123 | :rtype: ListNode 124 | """ 125 | self.nodes = [] 126 | head = point = ListNode(0) 127 | for l in lists: 128 | while l: 129 | self.nodes.append(l.val) 130 | l = l.next 131 | for x in sorted(self.nodes): 132 | point.next = ListNode(x) 133 | point = point.next 134 | return head.next 135 | ``` 136 | 137 | 138 | 139 | 140 | 时间复杂度:$O(N \log k)$,这里 N 是这 k 个链表的结点总数,每一次从一个优先队列中选出一个最小结点的时间复杂度是 $O(logk)$,故时间复杂度为 $O(N \log k)$。 141 | 空间复杂度:$O(k)$,使用优先队列需要 k 个空间,“穿针引线”需要常数个空间,因此空间复杂度为 $O(k)$。 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | # LeetCode 第 141 题:判断链表中是否有环 154 | 155 | 156 | 157 | ![](https://img-blog.csdnimg.cn/20191122154610446.png) 158 | 159 | 160 | > 你能用 O(1)(即,常量)内存解决此问题吗? 161 | 162 | 遍历整个数组, 给出的数据包含在集合中则说明有环, 返回 True; 若遍历完毕, 则说明无环, 返回 False,如果用列表也是一样。 163 | 164 | **暴力解法** 165 | 166 | ```python 167 | class Solution: 168 | def hasCycle(self, head: ListNode) -> bool: 169 | """ 170 | 暴力法:通过遍历链表,用set来存储访问的节点,如果在set出现一样的节点,说明有坏,时间复杂度O(n) 171 | :type head: ListNode 172 | :rtype: bool 173 | """ 174 | st = set() 175 | while head: 176 | if head in st: 177 | return True 178 | st.add(head ) 179 | head = head.next 180 | return False 181 | 182 | 183 | # 下面是列表 184 | l = [] 185 | while head: 186 | if head in l: 187 | return True 188 | else: 189 | l.append(head) 190 | head = head.next 191 | return False 192 | 193 | ``` 194 | 195 | 196 | 197 | 198 | 199 | ![](https://img-blog.csdnimg.cn/20200628121724978.png) 200 | 201 | 暴力的时间空间复杂度都是O(n) 202 | 203 | 204 | 205 | 206 | 207 | 208 | 题目要求用 $O(1)$空间复杂度 209 | 210 | 211 | > 这道题考的是**快慢指针** $O(1)$空间复杂度 212 | 213 | 214 | 215 | 216 | 217 | 218 | 通过使用具有 不同速度 的快、慢两个指针遍历链表,空间复杂度可以被降低至$O(1)$。慢指针每次移动一步,而快指针每次移动两步。 219 | 220 | 如果列表中不存在环,最终快指针将会最先到达尾部,此时我们可以返回 false。 221 | 222 | 223 | 224 | 进阶的要求是以 O(1) 的空间复杂度实现, 想象这样一个场景, 你和一个朋友一起散步, 你每次移动两步, 朋友每次一步, 如为单向定长道路, 你必然先到达重点. 若是环绕操场,则你们终将相遇. 225 | 226 | 227 | 228 | 229 | 230 | ```java 231 | class Solution(object): 232 | def hasCycle(self, head): 233 | slow = fast = head 234 | while slow and fast and fast.next: 235 | slow = slow.next 236 | fast = fast.next.next 237 | if slow == fast: 238 | return True 239 | return False 240 | ``` 241 | 242 | 243 | 244 | # LeetCode 第 206 题:反转链表 245 | 246 | 247 | 248 | 249 | 250 | ```java 251 | #反转一个单链表。 252 | # 示例: 253 | # 输入: 1->2->3->4->5->NULL 254 | #输出: 5->4->3->2->1->NULL 255 | # 进阶: 256 | #你可以迭代或递归地反转链表。你能否用两种方法解决这道题? 257 | # Related Topics 链表 258 | ``` 259 | 260 | 将当前节点的next指针指向前驱的节点,需要有2个指针来记录,一个记录当前节点,一个记录前驱节点,循环5次直到列表结束,三个简单复制语句 261 | 262 | ```python 263 | class Solution: 264 | def reverseList(self, head): 265 | cur, prev = head, None 266 | while cur: 267 | cur.next, prev, cur = prev, cur, cur.next 268 | return prev 269 | ``` 270 | 271 | -------------------------------------------------------------------------------- /71-80/72、Python _ Leetcode字符串系列(下篇).md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/7/3 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 (作者:Runsen ) 5 | 6 | 7 | 8 | 9 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 10 | 前面文章,点击下面链接 11 | 12 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 13 | 14 | 今日,我决定继续更新Python教程,今天就开始了七十二、Python | Leetcode字符串系列(下篇)。 15 | 16 | 17 | 18 | @[toc] 19 | 20 | # LeetCode 第14题:最长公共前缀 21 | 22 | 23 | 24 | ```java 25 | #编写一个函数来查找字符串数组中的最长公共前缀。 26 | # 如果不存在公共前缀,返回空字符串 ""。 27 | # 示例 1: 28 | # 输入: ["flower","flow","flight"] 29 | #输出: "fl" 30 | # 示例 2: 31 | # 输入: ["dog","racecar","car"] 32 | #输出: "" 33 | #解释: 输入不存在公共前缀。 34 | # 说明: 35 | # 所有输入只包含小写字母 a-z 。 36 | # Related Topics 字符串 37 | ``` 38 | 39 | 40 | 41 | 42 | 43 | 44 | 解题思路:使用 zip 根据字符串下标合并成数组,判断合并后数组里元素是否都相同 45 | 46 | 47 | 48 | 49 | ```java 50 | class Solution(object): 51 | def longestCommonPrefix(self, strs): 52 | ans = '' 53 | for i in zip(*strs): 54 | if len(set(i)) == 1: 55 | ans += i[0] 56 | else: 57 | break 58 | return ans 59 | ``` 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | # LeetCode 第28题:实现 strStr() 68 | 69 | 70 | ```java 71 | #实现 strStr() 函数。 72 | # 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。 73 | # 示例 1: 74 | # 输入: haystack = "hello", needle = "ll" 75 | #输出: 2 76 | # 示例 2: 77 | # 输入: haystack = "aaaaa", needle = "bba" 78 | #输出: -1 79 | # 说明: 80 | # 当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。 81 | # 对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。 82 | # Related Topics 双指针 字符串 83 | ``` 84 | 85 | 通过index进行needle数据查询,当不存在是index会报错,直接将其输出-1即可 86 | 87 | 88 | 89 | ```python 90 | class Solution: 91 | def strStr(self, haystack: str, needle: str) -> int: 92 | if needle in haystack: 93 | num = haystack.index(needle) 94 | else: 95 | return -1 96 | return num 97 | ``` 98 | 99 | 100 | 101 | # LeetCode 第67题: 二进制求和 102 | 103 | 104 | 105 | ```java 106 | #给你两个二进制字符串,返回它们的和(用二进制表示)。 107 | # 输入为 非空 字符串且只包含数字 1 和 0。 108 | # 示例 1: 109 | # 输入: a = "11", b = "1" 110 | #输出: "100" 111 | # 示例 2: 112 | # 输入: a = "1010", b = "1011" 113 | #输出: "10101" 114 | # 提示: 115 | # 每个字符串仅由字符 '0' 或 '1' 组成。 116 | # 1 <= a.length, b.length <= 10^4 117 | # 字符串如果不是 "0" ,就都不含前导零。 118 | # Related Topics 数学 字符串 119 | ``` 120 | 用python在十进制与二进制之间进行转换,求和转化返回。 121 | 122 | 123 | 124 | ```java 125 | class Solution: 126 | def addBinary(self, a: str, b: str) -> str: 127 | atmp = eval('0b' + a) #a对应的10进制数 128 | btmp = eval('0b' + b) #b对应的10进制数 129 | sumtmp = atmp + btmp #a+b对应的10进制数 130 | res = bin(sumtmp) #10进制数转化为二进制数字符串 131 | return res[2:] #返回结果字符串 132 | ``` 133 | 134 | 135 | 136 | 137 | 138 | 位运算模拟二进制加法运算。异或运算的特点是a和b不一样才为1,与运算的特点是a和b同为1时才为1,否则为0,刚好可以逐步记录进位。 139 | 140 | ![](https://img-blog.csdnimg.cn/20200703101705855.png) 141 | 142 | 143 | ```java 144 | class Solution: 145 | def addBinary(self, a: str, b: str) -> str: 146 | atmp = eval('0b' + a) 147 | btmp = eval('0b' + b) 148 | while btmp: 149 | ans = (atmp ^ btmp) 150 | btmp = (atmp & btmp) << 1 151 | atmp = ans 152 | return bin(atmp)[2:] 153 | ``` 154 | # LeetCode 第344题: 反转字符串 155 | 156 | ```java 157 | #编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。 158 | # 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 159 | # 你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。 160 | # 示例 1: 161 | # 输入:["h","e","l","l","o"] 162 | #输出:["o","l","l","e","h"] 163 | # 示例 2: 164 | # 输入:["H","a","n","n","a","h"] 165 | #输出:["h","a","n","n","a","H"] 166 | # Related Topics 双指针 字符串 167 | ``` 168 | 双指针思想,左右交换 169 | 170 | 171 | 172 | ```java 173 | class Solution: 174 | def reverseString(self, s: List[str]) -> None: 175 | """ 176 | Do not return anything, modify s in-place instead. 177 | """ 178 | i,j=0,len(s)-1 179 | while i<=j: 180 | s[i],s[j]=s[j],s[i] 181 | i+=1 182 | j-=1 183 | 184 | 185 | class Solution: 186 | def reverseString(self, s: List[str]) -> None: 187 | """ 188 | Do not return anything, modify s in-place instead. 189 | """ 190 | s.reverse() 191 | 192 | ``` 193 | 194 | 195 | # LeetCode 第557题: 反转字符串中的单词 III 196 | 197 | ```java 198 | #给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。 199 | # 示例 1: 200 | #输入: "Let's take LeetCode contest" 201 | #输出: "s'teL ekat edoCteeL tsetnoc" 202 | # 注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。 203 | # Related Topics 字符串 204 | ``` 205 | 206 | 207 | 将字符串分割成单词列表 然后把每个单词反转切片 208 | 209 | ```java 210 | class Solution(object): 211 | def reverseWords(self, s): 212 | return " ".join(word[::-1] for word in s.split(" ")) 213 | ``` 214 | 215 | 216 | 217 | 先反转单词列表 再反转字符串 218 | 219 | 以字符串` “I love drag queen” `为例: 220 | 221 | `s.split(" ") `将字符串分割成单词列表: 222 | 223 | 224 | `['I', 'love', 'drag', 'queen']` 225 | 226 | 227 | `s.split(" ")[::-1] `将单词列表反转: 228 | 229 | 230 | `['queen', 'drag', 'love', 'I']` 231 | 232 | `" ".join(s.split(" ")[::-1]) `将单词列表转换为字符串,以空格分隔: 233 | 234 | 235 | `"queen drag love I"` 236 | 237 | 238 | `" ".join(s.split(" ")[::-1])[::-1] `将字符串反转: 239 | 240 | 241 | `”I evol gard neeuq“` 242 | 243 | ```java 244 | class Solution(object): 245 | def reverseWords(self, s): 246 | return " ".join(s.split(" ")[::-1])[::-1] 247 | ``` 248 | 249 | -------------------------------------------------------------------------------- /71-80/75、Python _ Leetcode哈希表系列.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/7/3 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 (作者:Runsen ) 5 | 6 | 7 | 8 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 9 | 前面文章,点击下面链接 10 | 11 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 12 | 13 | 今日,我决定继续更新Python教程,今天就开始了七十五、Python | Leetcode哈希表系列。 14 | 15 | @[toc] 16 | 17 | 18 | 19 | # 哈希表 20 | 21 | 哈希表(散列表)的思想是将关键字 Key 映射到存放记录的散列表中从而进行快速访问,其中映射函数 f(key) 称为哈希函数(散列函数),依据哈希函数建立的查找表称为哈希表。 22 | 23 | Hash,音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 24 | 25 | 26 | 假如班级里面有50个学生,都有各自的名字,我们想把学生的名字放在一个表上,同时便于很快的查找,你会毫无想到数组,但是查找的复杂度是`O(n)`,所以哈希表就是为了解决这问题,将查找的复杂度达到 `O(1)` 27 | 28 | ![](https://img-blog.csdnimg.cn/20190319091629943.png) 29 | 30 | 31 | 32 | 33 | 假如有个学生的名字叫做`lies`,通过hash函数,得到下标`9` ,将`lies`的ASCII码加起来 `429%30 =9` ,这样的过程就是`hash`函数。 34 | 35 | 但是又没有可能出现`hash`碰撞,就是出现了一样的`hash`值,当然有可能 36 | 37 | 38 | ![](https://img-blog.csdnimg.cn/20190319091548415.png) 39 | 40 | 41 | 假如有个人的名字叫做`foes`,那么如何查找呢?当然是将数据储存成链表,用链表的方式来查找。 42 | 43 | 44 | 45 | 其实,哈希表就是一个具备映射关系的表,我们可以通过映射关系由键找到值。下面是一个简单的哈希表: 46 | 47 | ```cpp 48 | class Map: 49 | def __init__(self): 50 | self.items =[None]*100 51 | def hash(self,a): 52 | return a*1+0 53 | def put(self,k,v): 54 | self.items[hash(k)] = v 55 | def get(self,k): 56 | hashcode=hash(k) 57 | return self.items[hashcode] 58 | ``` 59 | 60 | 61 | 这个哈希函数十分简单,但简单不妨碍它成为一个哈希函数,事实上,它叫直接定址法,是一个线性函数:$hash(k)= a*k+b$ 62 | 63 | 直接定址法的优点很明显,就是它不会产生重复的hash值。但由于它与键值本身有关系,所以当键值分布很散的时候,会浪费大量的存储空间。所以一般是不会用到直接定址法的。 64 | 65 | 66 | 67 | 68 | ![](https://img-blog.csdnimg.cn/20200703231235952.png) 69 | 70 | # LeetCode 第 136题:只出现一次的数字 71 | 72 | 73 | 74 | ```cpp 75 | #给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 76 | # 说明: 77 | # 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 78 | # 示例 1: 79 | # 输入: [2,2,1] 80 | #输出: 1 81 | # 示例 2: 82 | # 输入: [4,1,2,1,2] 83 | #输出: 4 84 | # Related Topics 位运算 哈希表 85 | ``` 86 | 87 | 88 | 下面一行代码不做解释。 89 | ```cpp 90 | class Solution: 91 | def singleNumber(self, nums: List[int]) -> int: 92 | return sum(set(nums))*2-sum(nums) 93 | 94 | ``` 95 | 一遍遍历,用哈希表计数;再遍历,返回个数是1的数。`{}`用于创建空字典,空集合用`set()` 96 | dict的.get(a,b)中取出字典中键为a的值,如果不存在这样的键,则返回b。 97 | 98 | 99 | 100 | ```cpp 101 | class Solution: 102 | def singleNumber(self, nums: List[int]) -> int: 103 | dic = {} 104 | for i in nums: 105 | dic[i] = dic.get(i,0)+1 106 | 107 | for i in nums: 108 | if dic.get(i)==1: 109 | return i 110 | ``` 111 | 112 | 113 | # LeetCode 第 217题:存在重复元素 114 | 115 | 116 | 117 | ```cpp 118 | #给定一个整数数组,判断是否存在重复元素。 119 | # 如果任意一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。 120 | # 示例 1: 121 | # 输入: [1,2,3,1] 122 | #输出: true 123 | # 示例 2: 124 | # 输入: [1,2,3,4] 125 | #输出: false 126 | # 示例 3: 127 | # 输入: [1,1,1,3,3,4,3,2,4,2] 128 | #输出: true 129 | # Related Topics 数组 哈希表 130 | ``` 131 | 132 | 下面代码不解释 133 | ```cpp 134 | class Solution: 135 | def containsDuplicate(self, nums: List[int]) -> bool: 136 | if len(set(nums)) == len(nums): 137 | return False 138 | else: 139 | return True 140 | ``` 141 | 142 | 初试化哈希表`dic = {}`。遍历数组:若i不在hash中,则令`dic[i] = 1`为key,1为value(随便什么都可以)。若已存在,则返回True。 143 | 144 | 145 | ```cpp 146 | class Solution: 147 | def containsDuplicate(self, nums: List[int]) -> bool: 148 | dic = {} 149 | for i in nums: 150 | if dic.get(i): 151 | return True 152 | dic[i] = 1 153 | return False 154 | ``` 155 | 156 | 157 | # 剑指 Offer 50. 第一个只出现一次的字符 158 | 159 | 160 | 161 | ```cpp 162 | #在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。 163 | # 示例: 164 | # s = "abaccdeff" 165 | #返回 "b" 166 | #s = "" 167 | #返回 " " 168 | # 限制: 169 | # 0 <= s 的长度 <= 50000 170 | # Related Topics 哈希表 171 | ``` 172 | 173 | 174 | 遍历字符串 s ,使用哈希表统计 “各字符数量是否 > 1 ”。 175 | 再遍历字符串 s ,在哈希表中找到首个 “数量为 1的字符”,并返回。 176 | 177 | 178 | ```cpp 179 | class Solution: 180 | def firstUniqChar(self, s: str) -> str: 181 | dicts={} 182 | for i in s: 183 | dicts[i]=dicts.get(i,0)+1 184 | for i in s: 185 | if dicts[i]==1: 186 | return i 187 | return ' ' 188 | ``` 189 | 190 | -------------------------------------------------------------------------------- /81-90/87、Python _ 十大排序算法系列(上篇).md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/7/10 3 | 4 | 5 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 (作者:Runsen ) 6 | 7 | 8 | 9 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 10 | 11 | 12 | 前面文章,点击下面链接 13 | 14 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 15 | 16 | 、辣鸡的我决定继续更新Python教程,今天就开始了八十七、Python | 十大排序算法系列(上篇)。还有不到区区的十三篇,我快完成了。 17 | 18 | 如果把基础的数据结构与算法都自己亲自实现一遍,那么你已经比 90% 的 Python 程序员更优秀了。 19 | 20 | 21 | 22 | 关于排序就是下面的十大排序算法 23 | 24 | ![](https://img-blog.csdnimg.cn/20200708224346201.png) 25 | 26 | @[toc] 27 | 28 | 29 | # 冒泡排序 30 | 31 | 32 | python实现冒泡排序的核心思想是通过从列表一端迭代循环元素,再通过一个循环让这个元素之后的元素相邻两个比较,从而依次将最大值移动到最末端,如下图示意。 33 | 34 | ![](https://img-blog.csdnimg.cn/20200710225605314.png) 35 | 36 | Python冒泡排序的代码实现。 37 | 38 | 39 | 40 | 41 | ```csharp 42 | def bubble_sort(nums): 43 | for i in range(len(nums) - 1): 44 | for j in range(len(nums) - i - 1): 45 | if nums[j] > nums[j + 1]: 46 | nums[j], nums[j + 1] = nums[j + 1], nums[j] 47 | return nums 48 | ``` 49 | # 选择排序 50 | 51 | 排序算法:首先搜索整个列表,找到最小项的位置,如果该位置不是列表的第1项,就交换这两个位置的元素。然后从列表的第2个元素开始,重复上述过程,直到算法达到整个过程的最后一个位置,图形解释如下 52 | 53 | 54 | 下面使用55、23、87、62、16数列从小到大的排序过程来说明选择排序法的演算流程。原始数据如图: 55 | 56 | 57 | 1、首先找到此数列中最小值后,与数列中的第一个元素交换,如下图所示。 58 | 59 | ![](https://img-blog.csdnimg.cn/20200710225916995.png) 60 | 61 | 62 | 从第二个值开始找,找到剩余数列中(不含第一个填充为绿色的数字)的最小值,再和第二个值交换,如下图所示。 63 | 64 | ![](https://img-blog.csdnimg.cn/20200710230000474.png) 65 | 66 | 67 | 从第三个值开始找,找到此数列中(不含第一、二个的最小值),再和第三个值交换,如下图 68 | 69 | 70 | ![](https://img-blog.csdnimg.cn/20200710230017145.png) 71 | 72 | 73 | 74 | 从第四个值开始找,找到剩余数列的最小值,再和第四个值交换,排序完成,如下图。 75 | 76 | 77 | ![](https://img-blog.csdnimg.cn/20200710230038146.png) 78 | 79 | 80 | Python选择排序的代码实现。 81 | 82 | ```csharp 83 | def selectionSort(x): 84 | i = 0 85 | while i < len(x) - 1: 86 | minindex = i 87 | j = i + 1 88 | while j < len(x) : 89 | if x[minindex] > x[j]: 90 | minindex = j 91 | j+= 1 92 | if minindex != i: 93 | swap(x,i,minindex) 94 | i+= 1 95 | return x 96 | ``` 97 | 98 | # 插入排序 99 | 100 | 插入排序的实现思路顾名思义,就是不断地在一个已经是有序的数组中,寻找合适位置并插入新元素。 101 | 102 | 从后往前依次进行比较,如果待插入元素大于当前元素,则将待插入元素插入到当前元素的后一位,如果待插入元素小于当前元素,则将当前元素后移一位。不断重复该过程直至到数组的最后一位 103 | 104 | ![](https://img-blog.csdnimg.cn/20200710230139430.png) 105 | 106 | 107 | Python插入排序的代码实现。 108 | 109 | 110 | ```csharp 111 | def insertion_sort(a): 112 | length = len(a) 113 | if length <=1: 114 | return 115 | for i in range(1,length): 116 | j = i-1 117 | value = a[i] 118 | while j >=0: 119 | if a[j]= 1: 154 | for j in range(gap, n): 155 | i = j 156 | while( i - gap ) >= 0: 157 | if list[i] < list[ i - gap ]: 158 | list[i], list[ i - gap ] = list[ i - gap ], list[i] 159 | i -= gap 160 | else: 161 | break 162 | gap //= 2 163 | 164 | if __name__ == '__main__': 165 | alist = [54, 26, 93, 17, 77, 31, 44, 55, 20] 166 | print("原列表为:%s" % alist) 167 | shell_sort(alist) 168 | print("新列表为:%s" % alist) 169 | ``` 170 | # 归并排序 171 | 172 | 归并排序的基本思想:将待排序序列`R[0…n-1]`看成是`n`个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到`n/4`个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。 173 | 174 | ![](https://img-blog.csdnimg.cn/2020071023152225.png) 175 | 176 | 177 | 178 | 179 | 归并排序其实要做两件事: 180 | 181 | (1)“分解”——将序列每次折半划分。 182 | 183 | (2)“合并”——将划分后的序列段两两合并后排序。 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | ![](https://img-blog.csdnimg.cn/20200710231610643.gif) 192 | 193 | Python 归并排序的代码实现。 194 | 195 | 196 | ```csharp 197 | def merge(left, right): 198 | i = 0 199 | j = 0 200 | temp = [] 201 | while i <= len(left) - 1 and j <= len(right) - 1: 202 | if left[i] <= right[j]: 203 | temp.append(left[i]) 204 | i += 1 205 | else: 206 | temp.append(right[j]) 207 | j += 1 208 | temp += left[i:] + right[j:] 209 | return temp 210 | 211 | print(merge([1,3,4],[2,3,3])) 212 | ``` 213 | 214 | -------------------------------------------------------------------------------- /81-90/89、Python的GUI系列 _ 使用PyQt5 快速构建一个GUI 应用.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | @Author:Runsen 6 | @Date:2020/7/11 7 | 8 | 9 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 (作者:Runsen ) 10 | 11 | 12 | 13 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 14 | 15 | 16 | 前面文章,点击下面链接 17 | 18 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 19 | 20 | 21 | 22 | 在很早之前就学过了PyQt5 ,我决定在更新了几篇PyQt5 。之前写的PyQt5 博客基本覆盖于此。这篇是第八十九篇、Python的GUI系列 | 使用PyQt5 快速构建一个GUI 应用。离收官还有十一篇。 23 | 24 | 25 | 26 | @[toc] 27 | 28 | 29 | 30 | # Pyqt5的安装 31 | 32 | 33 | 34 | 35 | 安装 pyqt5 36 | 37 | `pip install pyqt5` 38 | 39 | 40 | 如果出现了运行出现了 No module named 'PyQt5.sip' 41 | 42 | 解决方法 : 43 | 44 | ` pip install --user pyqt5==5.10.1` 45 | 46 | 将pyqt5退了版本 47 | 48 | 49 | 50 | # 添加外部设置工具 51 | 52 | 53 | 安装成功后,这个时候,我们在pycharm中添加外部设置工具。 54 | 55 | 56 | ## 配置QtDesigner 57 | 58 | 步骤如下:File -> Settings -> Tools -> External Tools -> 59 | 60 | 61 | ![](https://img-blog.csdnimg.cn/2020071115410494.png) 62 | 63 | 64 | 65 | 66 | Name填入QtDesigner(方便后续使用,名称无所谓)。 67 | 68 | 69 | program :自己的designer的位置,如`F:\anaconda\Library\bin\designer.exe` 70 | 71 | 72 | ![](https://img-blog.csdnimg.cn/20200711214134921.png) 73 | 74 | 75 | ## 配置PyUIC 76 | 77 | 78 | 然后添加PyUIC(UI转换工具),PyUIC的Program为Python.exe,在Python的安装目录下面的Scripts目录下,Working directory同理设为我们的工作目录,Arguments则填入如下代码: 79 | 80 | 81 | 82 | 83 | ```csharp 84 | -m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py 85 | ``` 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 至于工作目录填写`项目的路径`,也可以填` $FileDir$`。 94 | ![](https://img-blog.csdnimg.cn/20200711220533733.png) 95 | ## 配置pyrcc 96 | 97 | 98 | 最后添加pyrcc用于PyQt5的资源文件转码。具体配置与上述内容相同,Arguments填入: 99 | 100 | 101 | ```csharp 102 | -mPyQt5.uic.pyuic $FileName$ -o$FileNameWithoutExtension$.py 103 | ``` 104 | 105 | 106 | 至于工作目录填写`项目的路径`,也可以填` $FileDir$`。 107 | 108 | 109 | 110 | 111 | ![](https://img-blog.csdnimg.cn/20200711220639251.png) 112 | 113 | 114 | 115 | 116 | 117 | ` 118 | 119 | 120 | 点击Apply保存配置。配置完成之后,PyCharm中会加入3个工具。 121 | 122 | 123 | 124 | ![](https://img-blog.csdnimg.cn/20200711215316346.png) 125 | 126 | # QtDesigner设计第一个QT应用 127 | 128 | 129 | 130 | 下面打开QtDesigner界面,点击QtDesigner则打开QtDesigner的界面。 131 | 132 | 133 | ![](https://img-blog.csdnimg.cn/20200711215406810.png) 134 | 135 | 136 | 刚打开Qt Designer,则弹出如下图所示的窗口。 137 | 138 | 139 | ![](https://img-blog.csdnimg.cn/20200711215455451.png) 140 | 141 | 142 | 创建新的Form给出了5个模板,其中Widget与Main Window最为常用。这里我们选择创建一个Main Window。 143 | 144 | 145 | ![](https://img-blog.csdnimg.cn/20200711215603979.png) 146 | 147 | 我们什么也不干,直接保存就可以了。 148 | ![](https://img-blog.csdnimg.cn/202007112159561.png) 149 | 150 | 151 | # 将一个.ui 文件生成一个.py文件 152 | 153 | 将demo.ui 文件打开其实是一个xml网页代码 154 | 155 | 156 | ![](https://img-blog.csdnimg.cn/20190421142300673.png) 157 | 158 | 159 | 160 | 161 | 在命令行 162 | 163 | ![](https://img-blog.csdnimg.cn/20190421142826586.png) 164 | 165 | ![](https://img-blog.csdnimg.cn/20190421142838791.png) 166 | 167 | 168 | 169 | ![](https://img-blog.csdnimg.cn/20200711220210231.png) 170 | 171 | 172 | 这样就会生成一个py文件。 173 | 174 | ![](https://img-blog.csdnimg.cn/20200711221046862.png) 175 | 176 | 但是直接运行是没有启动的,因为没有使用QApplication和QWidget两个类。这两个类都在PyQt5.QtWidgets。 177 | 178 | 179 | 180 | 181 | 182 | ```python 183 | from PyQt5 import QtCore, QtGui, QtWidgets 184 | class Ui_MainWindow(object): 185 | def setupUi(self, MainWindow): 186 | MainWindow.setObjectName("MainWindow") 187 | MainWindow.resize(800, 600) 188 | self.centralwidget = QtWidgets.QWidget(MainWindow) 189 | self.centralwidget.setObjectName("centralwidget") 190 | MainWindow.setCentralWidget(self.centralwidget) 191 | self.menubar = QtWidgets.QMenuBar(MainWindow) 192 | self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23)) 193 | self.menubar.setObjectName("menubar") 194 | MainWindow.setMenuBar(self.menubar) 195 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 196 | self.statusbar.setObjectName("statusbar") 197 | MainWindow.setStatusBar(self.statusbar) 198 | 199 | self.retranslateUi(MainWindow) 200 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 201 | 202 | def retranslateUi(self, MainWindow): 203 | _translate = QtCore.QCoreApplication.translate 204 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 205 | 206 | import sys 207 | from PyQt5.QtWidgets import QApplication,QMainWindow 208 | if __name__ == '__main__': 209 | app = QApplication(sys.argv) 210 | mainWindow = QMainWindow() 211 | ui = Ui_MainWindow() 212 | # 向主窗口上添加控件 213 | ui.setupUi(mainWindow) 214 | mainWindow.show() 215 | sys.exit(app.exec_()) 216 | 217 | ``` 218 | 运行上面的代码,效果如下所。这就是我们的第一个QT的GUI 应用 219 | 220 | 221 | ![](https://img-blog.csdnimg.cn/20200711221338872.png) 222 | -------------------------------------------------------------------------------- /91-99/92、Python爬取深圳租房信息小案例.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/6/19 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 (作者:Runsen ) 5 | 6 | 7 | 8 | 9 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 10 | 前面文章,点击下面链接 11 | 12 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 13 | 14 | 15 | 今天介绍的是Python中的爬虫小例子,离收官还有八篇。 16 | 17 | 18 | @[TOC] 19 | 20 | 21 | 22 | # 1、前言 23 | 24 | 25 | 在某日夏天的夜晚、突然有妹子加我微信,原来竟然叫我帮忙写作业。 26 | 27 | 28 | 29 | 30 | ![](https://img-blog.csdnimg.cn/20200628124023811.png) 31 | 32 | 33 | 34 | 对于,我这个屌丝来说,还是花个半小时帮忙搞定下。爬取的网站又是链家网,你看我直接不是早已写成博客了吗? 35 | 36 | ![](https://img-blog.csdnimg.cn/20200628124340804.png) 37 | 38 | 39 | 我想对链家网说:链家网求你不要再害大家爬你的,真的让广大学生都是讨厌你。 40 | 41 | 爬取的链接是:https://sz.lianjia.com/zufang/ 42 | 43 | ![](https://img-blog.csdnimg.cn/20200628124603502.png) 44 | 45 | 什么租房经纪人成交数据有吗?我看老师都是傻傻的不知道乱搞一通。难为是我啊?没有的东西爬了毛? 46 | 47 | 48 | # 2、明确爬取的信息 49 | 50 | 在链家网的租房信息中,有如下的信息,我都圈出来了。 51 | ![](https://img-blog.csdnimg.cn/2020062812485470.png) 52 | 53 | 明确爬取的信息,分别有整租,我就叫类型算了。新城花园就叫名称, 面积就是101,朝向南, 54 | 55 | 3室1厅1卫就叫房间数,价格每个月1800,真贵。反正我这种穷人要不起。 56 | 57 | 58 | 59 | 60 | 61 | # 3、 Requests访问链接 62 | 63 | 64 | Requests库就是发请求的库,需要加上请求头,这样就不用禁止了。 65 | 66 | 67 | 根据每个页面的网址发现就是换了一个pg参数。比如,第一页的网址是`https://sz.lianjia.com/zufang/pg0`, 68 | 69 | 那么第二页就是`https://sz.lianjia.com/zufang/pg1`,那么就是傻瓜式构造。我们爬它个100页,代码如下。 70 | 71 | 72 | 73 | 74 | 75 | ```java 76 | for i in range(1, 101): 77 | page_url = 'https://sz.lianjia.com/zufang/pg{}'.format(i) 78 | res = requests.get(page_url, headers=headers) 79 | ``` 80 | 81 | # 4、 xpath解析内容 82 | 83 | 返回的页面就需要解析,我经常用的说xpath,至于bs4赶紧忘记算了。 84 | 85 | 86 | 87 | 具体解析过程如下图所示。 88 | 89 | 90 | ![](https://img-blog.csdnimg.cn/20200628183147843.png) 91 | 92 | 93 | 94 | # 5、保存数据 95 | 我们选择用csv来保存数据,通过`with open('demo.csv', 'a+') as f`进行创建csv,然后通过`f.write`进行写入爬取的数据。 96 | 97 | 98 | 最终保存数据如下图所示。 99 | ![](https://img-blog.csdnimg.cn/20200628183414740.png) 100 | 101 | 102 | # 6、全部代码 103 | 104 | 105 | 106 | ```python 107 | ''' 108 | @Author: Runsen 109 | @微信公众号: 润森笔记 110 | @博客: https://blog.csdn.net/weixin_44510615 111 | @Date: 2020/6/27 112 | ''' 113 | import requests 114 | from lxml import etree 115 | 116 | headers = { 117 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36' 118 | } 119 | with open('demo.csv', 'a+') as f: 120 | f.write( 121 | '类型' + ',' + '名称' + ',' + '地点' + ',' + '面积' + ',' + '朝向' + ',' + '房间数' + ',' + '价格' + '\n') 122 | for i in range(1, 101): 123 | page_url = 'https://sz.lianjia.com/zufang/pg{}'.format(i) 124 | 125 | res = requests.get(page_url, headers=headers) 126 | # 这里千万不要判断res的状态码200 127 | page = etree.HTML(res.text) 128 | content = page.xpath("//a[@class='content__list--item--aside']/@title") 129 | 130 | where1 = page.xpath("//p[@class='content__list--item--des']/a[1]/text()") 131 | where2 = page.xpath("//p[@class='content__list--item--des']/a[2]/text()") 132 | where3 = page.xpath("//p[@class='content__list--item--des']/a[3]/text()") 133 | squares = page.xpath("//p[@class='content__list--item--des']/text()[5]") 134 | decorates = page.xpath("//p[@class='content__list--item--des']/text()[6]") 135 | nums = page.xpath("//p[@class='content__list--item--des']/text()[7]") 136 | Prices = page.xpath("//span[@class='content__list--item-price']/em/text()") 137 | for j,w1,w2 , w3,s,d, n, Price in zip(content, where1, where2,where3, squares, decorates,nums,Prices): 138 | type = j.replace("·", " ").split(" ")[0] 139 | name = j.replace("·", " ").split(" ")[1] 140 | location = w1+ w2 + w3 141 | square = s.replace("\n", "").replace(" ", "") 142 | decorate =d.replace(" ", "") 143 | num = n.replace("\n", "").replace(" ", "") 144 | price = Price+ "元/月" 145 | print("正在写入 :" + type + ',' + name + ',' + location + ',' + square + ',' + decorate + ',' + num + ',' + price + '\n') 146 | f.write(type + ',' + name + ',' + location + ',' + square + ',' + decorate + ',' + num + ',' + price + '\n') 147 | ``` 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /91-99/93、Python使用百度云接口API实现截图,文字识别和语音合成.md: -------------------------------------------------------------------------------- 1 |  2 | @Author:Runsen 3 | @Date:2020/7/13 4 | 5 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 (作者:Runsen ) 6 | 7 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 8 | 9 | 前面文章,点击下面链接 10 | 11 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 12 | 13 | 14 | 15 | 16 | 在实际的业务中,难免会跟第三方系统进行数据的交互与传递,其实就是写接口API的。今天就开始第九十三篇、Python使用百度云接口API实现截图,文字识别和语音合成 17 | 18 | 19 | @[toc] 20 | 21 | 22 | # 接口RESTful API 23 | 24 | 25 | 随着微信以及各种数据平台的兴起,大家对跟这些平台对接的需求越来越多。目前,包括以上平台在内的一些主流公共平台都会以一种 REST 架构原则,向大众提供对接的接口。这种符合 REST 风格的接口,就称为 RESTful API。 26 | 27 | 28 | 29 | 30 | 比如注册百度云帐号,打开百度云平台:https://login.bce.baidu.com/reg.html?tpl=bceplat&from=portal进行账号注册 31 | 32 | 33 | 记住: AppID,API Key,Secret Key 34 | 35 | 上面三个就是用户的接口。 36 | 37 | 38 | 39 | 40 | 41 | 42 | # 安装keyboard 43 | 下面我们实现Python使用百度云接口API实现截图,文字识别的功能。需要安装keyboard。 44 | 45 | keyboard是一个监控键盘输入的库 46 | 47 | 48 | 安装:`pip install keyborad` 49 | 50 | 51 | 执行下面的代码就是可以截图了。 52 | ```python 53 | import keyboard 54 | import time 55 | from PIL import ImageGrab 56 | def screen(): 57 | print('开始截图') 58 | # 使用微信的截图热键 59 | keyboard.wait(hotkey='alt+a') 60 | # 保存 61 | keyboard.wait(hotkey='enter') 62 | # 图片保存需要时间 63 | time.sleep(0.5) 64 | # 读取剪切板的图片 65 | image = ImageGrab.grabclipboard() 66 | # 保存图片 67 | image.save('screen.jpg') 68 | print('图片保存完成') 69 | screen() 70 | ``` 71 | 当在键盘敲ctrl+a来得到图片 72 | 73 | 74 | ![](https://img-blog.csdnimg.cn/20190502231944769.png) 75 | 76 | 截取的图片 77 | 78 | ![](https://img-blog.csdnimg.cn/20190502232009661.png) 79 | 80 | 81 | # 文字识别 82 | 下面我使用百度云来进行识别 83 | 84 | 为什么用百度云,因为百度的技术,阿里的运营,腾讯的产品。技术当然选百度云,而且识别效果比较高。 85 | 86 | 87 | 88 | 89 | ![](https://img-blog.csdnimg.cn/20190502232210590.png) 90 | 91 | 92 | 93 | ![](https://img-blog.csdnimg.cn/20190502232100232.png) 94 | 95 | 96 | 要安装百度的接口:[官方的教程](https://cloud.baidu.com/doc/OCR/OCR-Python-SDK.html#.E6.8E.A5.E5.8F.A3.E8.AF.B4.E6.98.8E):https://cloud.baidu.com/doc/OCR/OCR-Python-SDK.html#.E6.8E.A5.E5.8F.A3.E8.AF.B4.E6.98.8E 97 | 98 | 99 | 下面就是教程的模板。 100 | 101 | ```python 102 | from aip import AipOcr 103 | 104 | """ 你的 APPID AK SK """ 105 | APP_ID = '' 106 | API_KEY = '' 107 | SECRET_KEY = '' 108 | 109 | client = AipOcr(APP_ID, API_KEY, SECRET_KEY) 110 | 111 | 112 | 113 | """读取图片""" 114 | 115 | def get_file_content(filepath): 116 | with open(filepath,'rb') as f: 117 | return f.read() 118 | 119 | 120 | 121 | def get_img_content(img): 122 | 123 | image_content='' 124 | content = client.basicAccurate(image=img) 125 | # print(content) 126 | for words in content['words_result']: 127 | print(words) # 字典 128 | image_content += words['words'] 129 | print(image_content) 130 | 131 | ``` 132 | 133 | ![](https://img-blog.csdnimg.cn/20190502232738379.png) 134 | 135 | 下面就是将截图整合到其中,封装全代码。 136 | ```python 137 | # -*- coding:utf-8 -*- 138 | # time :2019/5/2 23:02 139 | # author: 毛利 140 | 141 | 142 | import keyboard 143 | import time 144 | from PIL import ImageGrab 145 | def screen(): 146 | print('开始截图') 147 | # 使用微信的截图热键 148 | keyboard.wait(hotkey='alt+a') 149 | # 保存 150 | keyboard.wait(hotkey='enter') 151 | # 图片保存需要时间 152 | time.sleep(0.5) 153 | # 读取剪切板的图片 154 | image = ImageGrab.grabclipboard() 155 | # 保存图片 156 | image.save('screen.jpg') 157 | 158 | # 使用百度云中的文字识别 159 | from aip import AipOcr 160 | 161 | """ 你的 APPID AK SK """ 162 | APP_ID = '' #你的账号的id 163 | API_KEY = '' 164 | SECRET_KEY = '' 165 | 166 | client = AipOcr(APP_ID, API_KEY, SECRET_KEY) 167 | 168 | 169 | 170 | """读取图片""" 171 | 172 | def get_file_content(filepath): 173 | with open(filepath,'rb') as f: 174 | return f.read() 175 | 176 | 177 | 178 | def get_img_content(img): 179 | 180 | image_content='' 181 | content = client.basicAccurate(image=img) 182 | # print(content) 183 | for words in content['words_result']: 184 | # print(words) # 字典 185 | image_content += words['words'] 186 | print(image_content) 187 | 188 | if __name__ == '__main__': 189 | screen() 190 | img = get_file_content('screen.jpg') 191 | get_img_content(img) 192 | ``` 193 | 194 | 195 | 196 | 197 | 下面就是具体的使用: 198 | ![](https://img-blog.csdnimg.cn/20190502233844342.png) 199 | 200 | 201 | 202 | ![](https://img-blog.csdnimg.cn/20190502233919839.png) 203 | 204 | 205 | 206 | 207 | # 语言合成 208 | 209 | 210 | 211 | 百度AP开发平台(ai.baidu.com),注册成功之后,点击控制台,进入到百度云-管理中心。就可以创建应用了。 212 | 我这里创建了一个带有语音接口的应用:[官方教程](https://ai.baidu.com/docs#/ASR-Online-Python-SDK/top) 213 | 214 | 215 | https://ai.baidu.com/docs#/ASR-Online-Python-SDK/top 216 | 217 | ![](https://img-blog.csdnimg.cn/20200713115655335.png) 218 | 219 | 220 | ![](https://img-blog.csdnimg.cn/20200713115719836.png) 221 | 222 | 223 | 具体代码如下。 224 | 225 | 226 | ```csharp 227 | from aip import AipSpeech 228 | app_id = "" 229 | api_key = "" 230 | secret_key = "" 231 | client = AipSpeech(app_id, api_key, secret_key) 232 | result = client.synthesis("好好学习,天天向上爱", "zh", 1, { 233 | "vol": 9, 234 | "spd": 6, 235 | "pit": 7, 236 | "per": 4, 237 | }) 238 | with open("audio.mp3", "wb") as f: 239 | f.write(result) 240 | 241 | ``` 242 | 243 | ![](https://img-blog.csdnimg.cn/20200713115750256.png) 244 | 245 | 音频的内容就是好好学习,天天向上 246 | 247 | 248 | 就是这么简单,不知道你学会了没有。 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /91-99/96、轻松搞定Python中的PPT办公自动化系列.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/7/14 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 5 | > (作者:Runsen ) 6 | 7 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 8 | 9 | 前面文章,点击下面链接 10 | 11 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 12 | 13 | 14 | 15 | 这篇是九十六、轻松搞定Python中的PPT办公自动化系列。离收官还有四篇。 16 | 17 | @[toc] 18 | 19 | 20 | # 安装python-pptx 21 | 22 | python-pptx就是为了进行PPT的操作而生,下面大致介绍一下这个python库。安装就是`pip install python-pptx`。下面以两个例子大致了解一下这个库中某些函数的用法。第一个例子用来讲述向幻灯片中增加基本内容; 23 | 24 | ```csharp 25 | from pptx import Presentation # 导入库 26 | 27 | prs = Presentation() # 创建PPT文档 28 | 29 | # 对幻灯片进行布局 30 | title_slide_layout = prs.slide_layouts[0] 31 | slide = prs.slides.add_slide(title_slide_layout) 32 | title = slide.shapes.title 33 | subtitle = slide.placeholders[1] 34 | 35 | # 各各部分添加内容 36 | title.text = "Hello, World!" 37 | subtitle.text = "我是python-pptx!" 38 | 39 | prs.save('增加内容.pptx') # 保存PPT文档 40 | ``` 41 | 42 | 43 | ![](https://img-blog.csdnimg.cn/20200714121431696.png) 44 | 45 | 46 | 47 | 第二个例子用来介绍向幻灯片中增加一个表格,代码如下。 48 | 49 | 50 | ```csharp 51 | from pptx import Presentation 52 | from pptx.util import Inches 53 | 54 | prs = Presentation() 55 | title_only_slide_layout = prs.slide_layouts[5] 56 | slide = prs.slides.add_slide(title_only_slide_layout) 57 | shapes = slide.shapes 58 | 59 | shapes.title.text = '增加一个表格' 60 | 61 | rows = cols = 3 62 | left = top = Inches(2.0) 63 | width = Inches(6.0) 64 | height = Inches(0.8) 65 | 66 | table = shapes.add_table(rows, cols, left, top, width, height).table 67 | 68 | # 设置表格列宽 69 | table.columns[0].width = Inches(2.0) 70 | table.columns[1].width = Inches(2.0) 71 | table.columns[2].width = Inches(2.0) 72 | 73 | # 表格头 74 | table.cell(0, 0).text = '姓名' 75 | table.cell(0, 1).text = '年龄' 76 | 77 | # 添加表格内容 78 | table.cell(1, 0).text = '张三' 79 | table.cell(1, 1).text = '42' 80 | 81 | table.cell(2,0).text = '李四' 82 | table.cell(2,1).text = '24' 83 | 84 | prs.save('增加表格.pptx') # 保存PPT 85 | ``` 86 | ![](https://img-blog.csdnimg.cn/20200714121544672.png) 87 | 88 | 89 | python-pptx学习网站:https://python-pptx.readthedocs.io/en/latest/ 90 | 91 | # 将一个PPT文件中的所有文字批量导出 92 | 93 | 94 | 有时,我们需要将一个PPT文件中的所有文字批量导出,以便查看,或者复制什么的。一页一页PPT去复制粘贴,会很不方便。下面我们就来试试用Python搞定这个吧。 95 | 96 | 97 | 使用的文件是我化工专业的设备材料选择的东西。 98 | ![](https://img-blog.csdnimg.cn/20200714122326305.png) 99 | 100 | 下面的代码已经将名字改为`测试.pptx` 101 | 102 | ```csharp 103 | #提取所有文本字符 104 | from pptx import Presentation 105 | data = [] 106 | prs = Presentation('测试.pptx') 107 | for slide in prs.slides: #遍历每页PPT 108 | for shape in slide.shapes: #遍历PPT中的每个形状 109 | if shape.has_text_frame: #判断该是否包含文本,保证有文本才提取 110 | for paragraph in shape.text_frame.paragraphs: #按文本框中的段落提取 111 | data.append(paragraph.text) #提取一个段落的文本,就存到列表data中 112 | 113 | #写入文本文件 114 | TxtFile = open('测试.txt', 'w',encoding='utf-8') 115 | for i in data: 116 | TxtFile.write(i+'\n') #写入并换行,以保证正确分段 117 | TxtFile.close() #保存 118 | 119 | #写入word文件 120 | import docx 121 | doc=docx.Document()#创建一个word文件对象 122 | for i in data: 123 | doc.add_paragraph(i) #增加一个段落,并将列表中的一个字符串写入word文件 124 | doc.save('测试.docx')#保存 125 | ``` 126 | ![](https://img-blog.csdnimg.cn/20200714125031419.png) 127 | -------------------------------------------------------------------------------- /91-99/97、轻松搞定Python中的PDF办公自动化系列.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/7/15 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 5 | > (作者:Runsen ) 6 | 7 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 8 | 9 | 前面文章,点击下面链接 10 | 11 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 12 | 13 | 14 | 15 | 这篇是九十七、轻松搞定Python中的PDF办公自动化系列。离收官还有三篇。 16 | 17 | @[toc] 18 | 19 | # pdfminer3k 20 | 21 | 22 | PDF的基本操作主要是读取、创建,合并等操作。使用Python的第三方包pdfminer3k读写合并PDF文件变得非常简单。这里不推荐使用PyPDF2,因为现在完全不维护的样子。 23 | 24 | 25 | 安装 pdfminer3k 26 | ```csharp 27 | pip install pdfminer3k 28 | ``` 29 | 30 | # 读取PDF 31 | 32 | 我是使用的是我的专业课程设计 `化工原理课程换热器设计.pdf `,具体内容如下。 33 | 34 | ![](https://img-blog.csdnimg.cn/20200715100841782.png) 35 | 36 | 37 | 38 | 还有的是PyPDF2 是不能读取中文的,只能提取英文字符串。因此我建议使用pdfminer来读取中文。下面代码就是提取PDF的文字到txt文件中。 39 | ```csharp 40 | from pdfminer.pdfinterp import PDFResourceManager, process_pdf 41 | from pdfminer.converter import TextConverter 42 | from pdfminer.layout import LAParams 43 | from io import StringIO 44 | 45 | 46 | def convert_pdf(path): 47 | rsrcmgr = PDFResourceManager() 48 | retstr = StringIO() 49 | laparams = LAParams() 50 | device = TextConverter(rsrcmgr, retstr, laparams=laparams) 51 | fp = open(path, 'rb') 52 | process_pdf(rsrcmgr, device, fp) 53 | 54 | fp.close() 55 | device.close() 56 | out = retstr.getvalue() 57 | retstr.close() 58 | return out 59 | 60 | 61 | a = convert_pdf('化工原理课程换热器设计.pdf') 62 | with open("a.txt" ,'w',encoding='utf-8') as f: 63 | f.write(a) 64 | 65 | ``` 66 | 67 | 68 | ![](https://img-blog.csdnimg.cn/20200715102714360.png) 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /91-99/98、轻松搞定Python中的Markdown系列.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/7/15 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 5 | > (作者:Runsen ) 6 | 7 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 8 | 9 | 前面文章,点击下面链接 10 | 11 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 12 | 13 | 14 | 这篇是九十八、轻松搞定Python中的Markdown系列。离收官还有二篇。 15 | 16 | 17 | @[toc] 18 | 19 | 20 | 21 | # tomd 22 | 23 | 本文是介绍tomd工具,大家可以去看[其](https://github.com/gaojiuli/tomd/)README的中文翻译。 24 | 25 | 安装 26 | 27 | 28 | ```csharp 29 | pip install tomd 30 | ``` 31 | 32 | 这个tomd应该是一个人开发的。直接看官方的示例,这里不罗嗦了,其实很简单的。 33 | 34 | 35 | 36 | 37 | # 将md批量转为docx 38 | 39 | 40 | 将markdown快速转为word格式,可以使用小工具pandoc, 非常好用, 这个是我在文本编辑器Typora导出功能发现的。 41 | 42 | 43 | 44 | 45 | 46 | 比如我有一个名为Python资料.md的文件, 我只需在命令行运行 47 | 48 | ```csharp 49 | pandoc Python资料.md -o Python资料.docx 50 | ``` 51 | 52 | pandoc支持相互转换的格式, 多的惊人! 53 | 54 | 55 | 56 | 57 | 但是如果用命令,那么一个一个的就是傻逼式行为,我就拿之前的文章做一个小示例。 58 | 59 | ![](https://img-blog.csdnimg.cn/20200715190539619.png) 60 | 61 | 62 | 下面就是简化的操作的代码。 63 | 64 | ```csharp 65 | import os 66 | 67 | # 当前目录下所有文件的名字 68 | all_files_name = os.listdir() 69 | 70 | # 保存所有md文件的名字 71 | all_md_files = [] 72 | 73 | # 获取目录下的md文件, 并保存 74 | for file_name in all_files_name: 75 | try: 76 | if file_name[-3:] == ".md": 77 | all_md_files.append(file_name) 78 | except Exception as e: 79 | print(e) 80 | # 将md文件批量装换为docx 81 | for md_file in all_md_files: 82 | try: 83 | tmp_doc_name = md_file[0: -3] + ".docx" 84 | new_command = "pandoc "+ md_file + " -o " + tmp_doc_name 85 | result = os.popen(new_command).readlines() 86 | if len(result) == 0: 87 | print(md_file, "转换成功") 88 | except Exception as e: 89 | print(e) 90 | ``` 91 | 92 | 93 | 运行结果 94 | ![](https://img-blog.csdnimg.cn/20200715191111381.png) 95 | 96 | 下面就是结果图 97 | 98 | 99 | 100 | ![](https://img-blog.csdnimg.cn/20200715191122461.png) 101 | 102 | 103 | 104 | 105 | 最后补充下关于Markdown的操作 106 | 107 | 108 | 109 | - #:此为Markdown中的标题语法,但是只支持到四级标题。 110 | - -:此为Markdown中的无须项目符号语法,笔者在此保留并进行拓展,和标题类似,可以键入多个减号来实现多级项目符号,最多三级。 111 | - **:此为Markdown中的粗体语法,笔者在此保留并简化,规定此语法只能在正文段落中使用。 112 | - $:此为Markdown中的Latex公式语法,笔者在此保留,为了便于添加到Word中,此处将公式转化为图片。 113 | - !:此为Markdown中的图片语法的简化写法 114 | 115 | 116 | 在此也向读者安利一个Markdown文本编辑器Typora,非常好用!不是打广告。 117 | -------------------------------------------------------------------------------- /91-99/99、Python所学经验分享.md: -------------------------------------------------------------------------------- 1 | @Author:Runsen 2 | @Date:2020/7/16 3 | 4 | > 人生最重要的不是所站的位置,而是内心所朝的方向。只要我在每篇博文中写得自己体会,修炼身心;在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰难,奋勇前行,不忘初心,砥砺前行,人生定会有所收获,不留遗憾 5 | > (作者:Runsen ) 6 | 7 | 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件。导致翘课严重,专业排名中下。.在大学60%的时间,都在CSDN。决定今天比昨天要更加努力。 8 | 9 | 前面文章,点击下面链接 10 | 11 | [我的Python教程,不断整理,反复学习](https://maoli.blog.csdn.net/article/details/106162925) 12 | 13 | 14 | 这是倒数第二篇,Python所学经验分享。 15 | 16 | 17 | @[toc] 18 | 19 | 20 | # 关于我 21 | 某不知名 辣鸡大学的大二学生,读的是化工专业。目前学分绩点可是2.08。我基本是专业排名中靠后的。作为一个曾经高考落榜的人,我并不是什么大神。 22 | 23 | 24 | 25 | python 那极为简洁与优美的语法给了当时的我极大的震撼,时至今日,写 py 代码对我而言依然是一种带有艺术意味的享受。 26 | 27 | 大一的时候,学习过一个学期的c语言,我相信大部分人都学过,期末考试过后就基本没有再用过。 28 | 29 | 30 | 我最初学python是应该是大一下,python特别容易入门,而且应用广泛,然后就培训机构迷惑了,大二傻傻的去培训了,其实经过培训,掌握了方法。于是我当机立断,打开百度就去搜索python和Java基础教程了,在自学中感觉很快乐。 31 | 32 | 33 | 我在整个学习Python的过程中,会看别人的博客和书,书面上出的Python相关的书我基本都看过。还有就是去看python标准库的代码,剩下的就是有勇气给开源社区提一些issue和pr。 34 | 35 | 36 | 37 | 38 | 39 | # 书籍推荐 40 | 41 | 42 | 给大家推荐的只有两本书 43 | 44 | 一本是《Python3基础教程》,大一下就是看这本东西。这本书浅显易懂,很全面,目前很多东西我还是不懂,这本书的作者实力很强。 45 | 46 | 47 | 48 | ![](https://img-blog.csdnimg.cn/20200716095234479.png) 49 | 50 | 第二本是《Python3标准库》,Python就是导包侠,那些Python大佬基本就比你会导包而已。你比他们会更多的库,然后开发自己库,让别人学你的库,那么你就是大佬了。 51 | 52 | 53 | ![](https://img-blog.csdnimg.cn/20200716095520902.png) 54 | 55 | 56 | **下面分享所学经验** 57 | 58 | 59 | 60 | # 经验一:有个小目标 61 | 62 | 63 | 让我们定一个小目标:怎么学习Py了,先定个小目标吧:在Pycharm上运行python,点亮一个灯。 64 | 65 | 66 | 67 | 记得在2018年暑假的时候,我在自己电脑对面的墙上贴了四个大字“暑假计划”。每一次抬头都能看到这四个字。我知道这四个字背后代表着什么,那是我给自己定的一个小目标。 68 | 69 | 暑假要求搞PR,思维导图,日语水平提高。从坚持到有效坚持的意识转变,能力就会有很大的提高。 70 | 71 | 我相信成长率的存在。每一个小事,每个步的计划都能体现出从小白到菜鸟的变化。 72 | 73 | 74 | 75 | # 经验二:一个教程多看几遍,多看几个教程 76 | 77 | 78 | 我第一个看的就是菜鸟教程,的确很符合它的名字,难度确实很符合菜鸟的标准,但是风格和教科书别无二致,毕竟那是我就是一个菜鸟。 79 | 80 | 81 | 82 | 83 | 84 | 下面给大家推荐一个Python资源。有位名叫骆昊 (jackfrued) 的资深程序员,为大家规划了一条从“从新手到大师”的百天之路。 85 | 86 | 从全方位熟悉语言,到Python的进阶用法,再到天南地北的实战攻略:只要沿着这条路走下去,就都会遇到的。 87 | 88 | 89 | 90 | 91 | ![](https://img-blog.csdnimg.cn/20200716103901755.png) 92 | 93 | 学Python善用搜索引擎获得自己想要的答案,学会看报错信息;一开始学习的时候,往往会忽视这一点。 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | # 经验三:学Python就是导包侠 106 | 107 | python目前很火,因为它确实是目前上面上最适合做机器学习,大数据分析,人工智能的语言,毕竟库多。 108 | 109 | 110 | 111 | 112 | Python这玩意脚本语言入门的确不难,现成的包也一堆基本就是拿来就用,但只是入个门,自学真的绰绰有余 113 | 114 | 115 | 众所周知我等写python的人都是调包侠,怎么可能比得上无敌的c和cpp呢。 116 | 117 | 118 | python又慢语法又low,不配称为编程语言,可长期以来被开发者们吹的漫天飞,同时饱受其他语言开发者的调侃和诟病以及鄙视。 119 | 120 | 121 | cpp语法高深莫测,自己的代码别人想读懂是难上加难,在大大增加安全性的同时,还显示出编程这项工作的高技术性,难度性,故深受程序员们的喜爱。 122 | 123 | 本人误入歧途学习python,最近正在努力转cpp和Java,希望能早日走上正轨。 124 | 125 | 126 | 127 | # 经验四:持续写博客记录 128 | 129 | 决定开始写博客之前,我也看到过一些技术大牛在文章里面建议大家现在就开始写博客,说这是一个很好的总结学到的东西的方式,以及博客写多了就会越写越顺手,难的是开始的过程。 130 | 131 | 132 | 133 | 我觉得很有道理,加上我在大二培训的时候,也被师傅逼着写博客,也学了很多知识,其实这100篇教程很多是那是开始的。 134 | 135 | 136 | 开始写博客之后,就会发现这是一件很快乐的事情。能够把学到的知识总结下来,让别人看懂,会带来一种成就感。看着自己的文章数越来越多,能够感受到自己的进步,能让自己学习时更有动力。 137 | 138 | 139 | 140 | 141 | 142 | 143 | # 经验五:混IT,只会Python未来没戏 144 | 145 | 146 | 147 | 148 | 现在铺天盖地宣传python,我觉得是因为教Python比较容易。一看这广告把python吹得天花乱坠的,不学python都要变成21世纪的文盲了,别人学了python工作效率蹭蹭的往上提。 149 | 150 | 151 | 152 | 在我看来这就是在贩卖焦虑,你仔细想想,培训班几个月出来的是国家要的人工智能人才吗?会python的人,工作效率就能提高了么? 153 | 154 | 155 | 理想的确很美好,但现实也是真的现实,你敲代码改bug补充所需编程知识的时间可能比你手动去完成这些工作还要费心费力,更别提以后使用场景变更,还得重写代码。 156 | 157 | 这些广告说辞里面最靠谱的可能就是“初次编程选Python,零基础易上手”,但是学完python就可以找到一份月薪20k、30k的工作了么? 158 | 159 | 160 | “你要悄悄学Python,然后惊艳全世界” 161 | 162 | 广告铺天盖地的来,从来没听过“你要悄悄学c#,惊艳全世界”的吧,至少可以分析出来。 163 | 164 | 派森简单易学,用处广,卖课很挣钱。 165 | 166 | 167 | 因此,Python只能做第二编程语言来搞,第一我选用Java。 168 | --------------------------------------------------------------------------------