diff --git "a/Article/Linux/Linux\345\221\275\344\273\244-\346\226\207\344\273\266\347\256\241\347\220\206\346\250\241\345\235\227.md" "b/Article/Linux/Linux\345\221\275\344\273\244-\346\226\207\344\273\266\347\256\241\347\220\206\346\250\241\345\235\227.md" new file mode 100644 index 00000000..1533c35f --- /dev/null +++ "b/Article/Linux/Linux\345\221\275\344\273\244-\346\226\207\344\273\266\347\256\241\347\220\206\346\250\241\345\235\227.md" @@ -0,0 +1,429 @@ + +## 文件管理 + +#### 1.查看文件信息:`ls` + + +**简介:** + +`ls` 是英文单词 list 的简写,其功能为列出目录的内容,是用户最常用的命令之一。 + +Linux 文件或者目录名称最长可以有 265 个字符,“.” 代表当前目录,“..” 代表上一级目录,以 “.” 开头的文件为隐藏文件,需要用 -a 参数才能显示。 + + +**ls常用参数:** + +| 参数 | 含义 | +| --- | --- | +| -a | 显示指定目录下所有子目录与文件,包括隐藏文件 | +| -l | 以列表方式显示文件的详细信息 | +| -h | 配合 -l 以人性化的方式显示文件大小 | + + +**ls 匹配通配符:** + +与 DOS 下的文件操作类似,在 Unix/Linux 系统中,也同样允许使用特殊字符来同时引用多个文件名,这些特殊字符被称为通配符。 + +| 通配符 | 含义 | +| ------- | ----- | +| * | 文件代表文件名中所有字符 | +| ls te* | 查找以 `te` 开头的文件 | +| ls *html | 查找结尾为 `html` 的文件 | +| ? | 代表文件名中任意一个字符 | +| ls ?.c | 只找第一个字符任意,后缀为 `.c` 的文件 | +| ls a.? | 只找只有 3 个字符,前 2 字符为 `a.` ,最后一个字符任意的文件 | +| [] | `"[”` 和 `“]”` 将字符组括起来,表示可以匹配字符组中的任意一个。`“-”` 用于表示字符范围。 | +| [abc] | 匹配 a、b、c 中的任意一个 | +| [a-f] | 匹配从 a 到 f 范围内的的任意一个字符 | +| ls [a-f]* | 找到从 a 到 f 范围内的的任意一个字符开头的文件 | +| ls a-f | 查找文件名为 a-f 的文件,当 `“-”` 处于方括号之外失去通配符的作用 | +| \ | 如果要使通配符作为普通字符使用,可以在其前面加上转义字符。`“?”` 和 `“*”` 处于方括号内时不用使用转义字符就失去通配符的作用。 | +| ls \*a | 查找文件名为 `*a` 的文件 | + + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/ls.jpeg) + + +#### 2. 输出重定向命令:`>` + +**简介:** + +Linux 允许将命令执行结果重定向到一个文件,本应显示在终端上的内容保存到指定文件中。 + +如:ls > test.txt ( test.txt 如果不存在,则创建,存在则覆盖其内容 ) + +注意: `> 输出重定向会覆盖原来的内容, >> 输出重定向则会追加到文件的尾部。` + + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/%E9%87%8D%E5%AE%9A%E5%90%91.jpeg) + + + +#### 3. 分屏显示:`more` + +**简介:** + +查看内容时,在信息过长无法在一屏上显示时,会出现快速滚屏,使得用户无法看清文件的内容,此时可以使用 `more` 命令,每次只显示一页,按下空格键可以显示下一页,按下 `q` 键退出显示,按下 `h` 键可以获取帮助。 + + + + + +#### 4. 管道:`|` + +**简介:** + +管道:一个命令的输出可以通过管道做为另一个命令的输入。 + +管道我们可以理解现实生活中的管子,管子的一头塞东西进去,另一头取出来,这里 `|` 的左右分为两端,左端塞东西(写),右端取东西(读)。 + + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/%E7%AE%A1%E9%81%93.png) + + +#### 5. 清屏:`clear` + +`clear` 作用为清除终端上的显示(类似于 DOS 的 cls 清屏功能),也可使用快捷键:Ctrl + l ( “l” 为字母 “L” 的小写 )。 + + + + +#### 6. 切换工作目录:`cd` + + +**简介:** + +在使用 Unix/Linux 的时候,经常需要更换工作目录。`cd` 命令可以帮助用户切换工作目录。`Linux 所有的目录和文件名大小写敏感` + +`cd` 后面可跟绝对路径,也可以跟相对路径。如果省略目录,则默认切换到当前用户的主目录。 + + +**cd 常用命令:** + +| 命令 | 含义 | +| --- | --- | +| `cd` | 切换到当前用户的主目录(/home/用户目录),用户登陆的时候,默认的目录就是用户的主目录。 | +| `cd ~` | 切换到当前用户的主目录(/home/用户目录) | +| `cd .` | 切换到当前目录 | +| `cd ..` | 切换到上级目录 | +| `cd -` | 可进入上次所在的目录 | + + +注意: + +* 如果路径是从根路径开始的,则路径的前面需要加上 “ / ”,如 “ /mnt ”,通常进入某个目录里的文件夹,前面不用加 “ / ”。 + + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/cd.png) + + + + +#### 7. 显示当前路径:`pwd` + +**简介:** + +使用 `pwd` 命令可以显示当前的工作目录,该命令很简单,直接输入 `pwd` 即可,后面不带参数。 + + + + + + + + +#### 8. 创建目录:`mkdir` + +**简介:** + +通过 `mkdir` 命令可以创建一个新的目录。参数 -p 可递归创建目录。 + +需要注意的是新建目录的名称不能与当前目录中已有的目录或文件同名,并且目录创建者必须对当前目录具有写权限。 + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/mkdir.png) + + +#### 9. 删除目录:`rmdir` + +**简介:** + +可使用 `rmdir` 命令删除一个目录。必须离开目录,并且目录必须为空目录,不然提示删除失败。 + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/rmdir.png) + + +#### 10. 删除文件:`rm` + +**简介:** + +可通过 `rm` 删除文件或目录。使用 `rm` 命令要小心,因为文件删除后不能恢复。为了防止文件误删,可以在 `rm` 后使用 `-i` 参数以逐个确认要删除的文件。 + + +**`rm` 常用参数:** + +| 参数 | 含义 | +| --- | --- | +| -i | 以进行交互式方式执行 | +| -f | 强制删除,忽略不存在的文件,无需提示 | +| -r | 递归地删除目录下的内容,删除文件夹时必须加此参数 | + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/rm.png) + + + +#### 11. 建立链接文件:`ln` + + +**简介:** + + +Linux 链接文件类似于 Windows 下的快捷方式。 + +链接文件分为软链接和硬链接。 + +软链接:软链接不占用磁盘空间,源文件删除则软链接失效。 + +硬链接:硬链接只能链接普通文件,不能链接目录。 + +使用格式: + +``` +ln 源文件 链接文件 +ln -s 源文件 链接文件 +``` + + +如果`没有-s`选项代表建立一个硬链接文件,两个文件占用相同大小的硬盘空间,即使删除了源文件,链接文件还是存在,所以-s选项是更常见的形式。 + +注意:如果软链接文件和源文件不在同一个目录,源文件要使用绝对路径,不能使用相对路径。 + + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/ln.png) + + + + + +#### 12. 查看或者合并文件内容:`cat` + + +**简介:** + +查看文件内容 + + + + +#### 13. 文本搜索:`grep` + + +**简介:** + +Linux 系统中 grep 命令是一种强大的文本搜索工具,grep 允许对文本文件进行模式查找。如果找到匹配模式, grep 打印包含模式的所有行。 + +grep一般格式为: + +``` +grep [-选项] ‘搜索内容串’文件名 +``` + + +在 grep 命令中输入字符串参数时,最好引号或双引号括起来。例如:grep‘a ’1.txt。 + + +**`grep` 常用参数:** + +| 选项 | 含义 | +| --- | --- | +| -v | 显示不包含匹配文本的所有行(相当于求反) | +| -n | 显示匹配行及行号 | +| -i | 忽略大小写 | + +grep 搜索内容串可以是正则表达式。 + + +**grep 常用正则表达式:** + +| 参数 | 含义 | +| --- | --- | +| ^a | 行首,搜寻以 m 开头的行;grep -n '^a' 1.txt | +| ke$ | 行尾,搜寻以 ke 结束的行;grep -n 'ke$' 1.txt | +| [Ss]igna[Ll] | 匹配 [] 里中一系列字符中的一个;搜寻匹配单词signal、signaL、Signal、SignaL的行;grep -n '[Ss]igna[Ll]' 1.txt | +| . | (点)匹配一个非换行符的字符;匹配 e 和 e 之间有任意一个字符,可以匹配 eee,eae,eve,但是不匹配 ee,eaae;grep -n 'e.e' 1.txt | + + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/grep.png) + + + +#### 14. 查找文件:`find` + +**简介:** + +find 命令功能非常强大,通常用来在特定的目录下搜索符合条件的文件,也可以用来搜索特定用户属主的文件。 + +**常用用法:** + +| 命令 | 含义 | +| --- | --- | +| find ./ -name test.sh | 查找当前目录下所有名为test.sh的文件 | +| find ./ -name '*.sh' | 查找当前目录下所有后缀为.sh的文件 | +| find ./ -name "[A-Z]*" | 查找当前目录下所有以大写字母开头的文件 | +| find /tmp -size 2M | 查找在/tmp 目录下等于2M的文件 | +| find /tmp -size +2M | 查找在/tmp 目录下大于2M的文件 | +| find /tmp -size -2M | 查找在/tmp 目录下小于2M的文件 | +| find ./ -size +4k -size -5M | 查找当前目录下大于4k,小于5M的文件 | +| find ./ -perm 0777 | 查找当前目录下权限为 777 的文件或目录 | + + + + + +#### 1.15 拷贝文件:`cp` + +**简介:** + +`cp` 命令的功能是将给出的文件或目录复制到另一个文件或目录中,相当于 DOS 下的 copy 命令。 + +**常用参数说明:** + +| 选项 | 含义 | +| --- | --- | +| -a | 该选项通常在复制目录时使用,它保留链接、文件属性,并递归地复制目录,简单而言,保持文件原有属性。 | +| -f | 已经存在的目标文件而不提示 | +| -i | 交互式复制,在覆盖目标文件之前将给出提示要求用户确认 | +| -r | 若给出的源文件是目录文件,则cp将递归复制该目录下的所有子目录和文件,目标文件必须为一个目录名。 | +| -v | 显示拷贝进度 | + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/find.png) + + +#### 16. 移动文件:`mv` + +**简介:** + +用户可以使用 `mv` 命令来移动文件或目录,也可以给文件或目录重命名。 + +**常用参数说明:** + +| 选项 | 含义 | +| --- | --- | +| -f | 禁止交互式操作,如有覆盖也不会给出提示 | +| -i | 确认交互方式操作,如果mv操作将导致对已存在的目标文件的覆盖,系统会询问是否重写,要求用户回答以避免误覆盖文件 | +| -v | 显示移动进度 | + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/mv.png) + + +#### 17. 归档管理:`tar` + + +**简介:** + +计算机中的数据经常需要备份,tar 是 Unix/Linux 中最常用的备份工具,此命令可以把一系列文件归档到一个大文件中,也可以把档案文件解开以恢复数据。其实说白了,就是打包。 + + + +**`tar` 使用格式:** + +``` +tar [参数] 打包文件名 文件 +``` + + +**`tar` 常用参数:** + +tar 命令很特殊,其参数前面可以使用“-”,也可以不使用。 + +| 参数 | 含义 | +| --- | --- | +| -c | 生成档案文件,创建打包文件 | +| -v | 列出归档解档的详细过程,显示进度 | +| -f | 指定档案文件名称,f后面一定是.tar文件,所以必须放选项最后 | +| -t | 列出档案中包含的文件 | +| -x | 解开档案文件 | + +注意:除了f需要放在参数的最后,其它参数的顺序任意。 + + + + + + +#### 18. 文件压缩解压:`gzip` + +**简介:** + +tar 与 gzip 命令结合使用实现文件打包、压缩。 tar 只负责打包文件,但不压缩,用 gzip 压缩 tar 打包后的文件,其扩展名一般用xxxx.tar.gz。 + +**`gzip` 使用格式如下:** + +``` +gzip [选项] 被压缩文件 +``` + +**常用选项:** + +| 选项 | 含义 | +| --- | --- | +| -d | 解压 | +| -r | 压缩所有子目录 | + + +tar这个命令并没有压缩的功能,它只是一个打包的命令,但是在tar命令中增加一个选项(-z)可以调用gzip实现了一个压缩的功能,实行一个先打包后压缩的过程。 + +压缩用法:tar cvzf 压缩包包名 文件1 文件2 ... + +```-z :指定压缩包的格式为:file.tar.gz``` + + +解压用法: tar zxvf 压缩包包名 + +```-z:指定压缩包的格式为:file.tar.gz``` + + +解压到指定目录:-C (大写字母“C”) + + + + +#### 19. 文件压缩解压:`bzip2` + +**简介:** + +tar与bzip2命令结合使用实现文件打包、压缩(用法和gzip一样)。 + +tar只负责打包文件,但不压缩,用bzip2压缩tar打包后的文件,其扩展名一般用xxxx.tar.gz2。 + +在tar命令中增加一个选项(-j)可以调用bzip2实现了一个压缩的功能,实行一个先打包后压缩的过程。 + +压缩用法:tar -jcvf 压缩包包名 文件...(tar jcvf bk.tar.bz2 *.c) + +解压用法:tar -jxvf 压缩包包名 (tar jxvf bk.tar.bz2) + + + + +#### 20. 文件压缩解压:`zip` 、`unzip` + +通过zip压缩文件的目标文件不需要指定扩展名,默认扩展名为zip。 + +压缩文件:zip [-r] 目标文件(没有扩展名) 源文件 + +解压文件:unzip -d 解压后目录文件 压缩文件 + + + + + +#### 21. 查看命令位置:`which` + +**简介:** + +查看命令的路径 + +![](http://p1ceh5usj.bkt.clouddn.com/linux/%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E6%A8%A1%E5%9D%97/which.png) + + + + diff --git "a/Article/Linux/Linux\345\221\275\344\273\244-\347\224\250\346\210\267,\346\235\203\351\231\220\347\256\241\347\220\206\346\250\241\345\235\227.md" "b/Article/Linux/Linux\345\221\275\344\273\244-\347\224\250\346\210\267,\346\235\203\351\231\220\347\256\241\347\220\206\346\250\241\345\235\227.md" new file mode 100644 index 00000000..fe569e7b --- /dev/null +++ "b/Article/Linux/Linux\345\221\275\344\273\244-\347\224\250\346\210\267,\346\235\203\351\231\220\347\256\241\347\220\206\346\250\241\345\235\227.md" @@ -0,0 +1,38 @@ +## 用户,权限管理 + +用户是 Unix/Linux 系统工作中重要的一环,用户管理包括用户与组账号的管理。 + +在 Unix/Linux 系统中,不论是由本机或是远程登录系统,每个系统都必须拥有一个账号,并且对于不同的系统资源拥有不同的使用权限。 + +Unix/Linux 系统中的 root 账号通常用于系统的维护和管理,它对 Unix/Linux 操作系统的所有部分具有不受限制的访问权限。 + +在 Unix/Linux 安装的过程中,系统会自动创建许多用户账号,而这些默认的用户就称为“标准用户”。 + +在大多数版本的 Unix/Linux 中,都不推荐直接使用 root 账号登录系统。 + +#### 1.多用户系统 + +> 什么是多用户呢? + +「多用户」指允许多个用户(逻辑上的账户),同时使用的操作系统或应用软件。 + +而 Linux 就是多用户操作系统,允许多个用户通过远程登录的方式访问一台机器并同时进行使用,相互之间互不影响。 + +> 那我们经常使用的 Windows 是不是多用户操作系统呢? + +Windows 系列的话,Windows 1.x、2.x、3.x(不含NT 3.x)、9x、Me 均为单用户操作系统,其中 9x 虽然有多用户的雏形但基本形同虚设,Windows Me 是最后一个非 NT 内核的 Windows 系统,同样不具备实用性的多用户设计。 + +有人会问, Windows 不是可以创建多个账号吗?为什么不是多用户操作系统呢? + +其实 Windows 的多用户不是真正的多用户,就好比你在家里远程登录了你公司的电脑,你公司的电脑会立刻进入到锁屏状态,而且被人是不可以操作的。这就说明不能多账号同时操作一台电脑了。 + + + + + + + + + + + diff --git a/Article/PythonBasis/python0/WhyStudyPython.md b/Article/PythonBasis/python0/WhyStudyPython.md new file mode 100644 index 00000000..511cbab4 --- /dev/null +++ b/Article/PythonBasis/python0/WhyStudyPython.md @@ -0,0 +1,43 @@ +### Python 越来越火爆 + +Python 在诞生之初,因为其功能不好,运转功率低,不支持多核,根本没有并发性可言,在计算功能不那么好的年代,一直没有火爆起来,甚至很多人根本不知道有这门语言。 + +随着时代的发展,物理硬件功能不断提高,而软件的复杂性也不断增大,开发效率越来越被企业重视。因此就有了不一样的声音,在软件开发的初始阶段,性能并没有开发效率重要,没必然为了节省不到 1ms 的时间却让开发量增加好几倍,这样划不过来。也就是开发效率比机器效率更为重要,那么 Python 就逐渐得到越来越多开发者的亲睐了。 + +在 12-14 年,云计算升温,大量创业公司和互联网巨头挤进云计算领域,而最著名的云核算开源渠道 OpenStack 就是基于 Python 开发的。 + +随后几年的备受关注的人工智能,机器学习首选开发语言也是 Python。 + +至此,Python 已经成为互联网开发的焦点。在「Top 10 的编程语言走势图」可以看到,Python 已经跃居第三位,而且在 2017 年还成为了最受欢迎的语言。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-07-06-084240.png) + +### Python 开发薪资高 + +Python 开发人员是收入最高的开发人员之一,特别是在数据科学,机器学习和 Web 开发方面。 + +在北上广深一线城市上,Python 开发的薪资都达到了 2w+ 。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-07-06-090549.jpg) + +### Python 容易入门且功能强大 + +如果你是一名初学者,学习 Python 就是你最好的选择,因为它容易学,功能强大,很容易就能构建 Web 应用,非常适合初学者作为入门的开发语言。 + +Python 还一度被爆纳入高考,收编到小学课本。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-07-06-091204.png) + +如果你有一定的编程语言基础,学习 Python 也是不错的选择,因为 Python 很可能就是未来开发的主流方向,多学一门语言,多一个防身技能。而且 Python 有强大的功能库,能非常快速的开发工具,为你的本职开发工作提供护航。 + + + + + + + + + + + + diff --git a/Article/PythonBasis/python1/IDE.md b/Article/PythonBasis/python1/IDE.md new file mode 100644 index 00000000..724b7cf0 --- /dev/null +++ b/Article/PythonBasis/python1/IDE.md @@ -0,0 +1,9 @@ +# 四、集成开发环境(IDE): PyCharm # + +我本人一直是建议在学习周期使用文本编辑器或者是[Sublime Text](http://www.sublimetext.com/) 这个工具来写 Python 程序的,因为这样有利于我们了解整个流程。 + +当然,如果你有一定的编程基础,是可以使用集成的开发环境的,这样可以提高效率。这时,你可以选择 PyCharm ,PyCharm 是由 JetBrains 打造的一款 Python IDE,支持 macOS、 Windows、 Linux 系统。 + +PyCharm 下载地址 : [https://www.jetbrains.com/pycharm/download/](https://www.jetbrains.com/pycharm/download/) + + diff --git a/Article/PythonBasis/python1/Installation.md b/Article/PythonBasis/python1/Installation.md new file mode 100644 index 00000000..9c26e821 --- /dev/null +++ b/Article/PythonBasis/python1/Installation.md @@ -0,0 +1,68 @@ +# 二、Python 的安装 # + +因为 Python 是跨平台的,它可以运行在 Windows、Mac 和各种 Linux/Unix 系统上。目前,Python 有两个版本,一个是 2.x 版,一个是 3.x版,这两个版本是不兼容的。本草根安装的是 3.6.1 版本的。 + +至于在哪里下载,草根我建议大家最好直接官网下载,随时下载下来的都是最新版本。官网地址:[https://www.python.org/](https://www.python.org/) + +## 1、windows 系统下安装配置 ## + +如果是 windows 系统,下载完后,直接安装,不过这里记得勾上Add Python 3.6 to PATH,然后点 「Install Now」 即可完成安装。 + +这里要注意了,记得把「Add Python 3.6 to Path」勾上,勾上之后就不需要自己配置环境变量了,如果没勾上,就要自己手动配置。 + +![Python安装.png](http://upload-images.jianshu.io/upload_images/2136918-2bf6591f0a12e80b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + +如果你一时手快,忘记了勾上 「Add Python 3.6 to Path」,那也不要紧,只需要手动配置一下环境变量就好了。 + +在命令提示框中 cmd 上输入 : + +``` +path=%path%;C:\Python +``` + +特别特别注意: `C:\Python` 是 Python 的安装目录,如果你的安装目录是其他地方,就得填上你对应的目录。 + +安装完成后,打开命令提示符窗口,敲入 python 后,出现下面的情况,证明 Python 安装成功了。 + +![运行python.png](http://upload-images.jianshu.io/upload_images/2136918-817c22f802e8cfce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + +而你看到提示符 `>>>` 就表示我们已经在 Python 交互式环境中了,可以输入任何 Python 代码,回车后会立刻得到执行结果。 + + +## 2、Mac 系统下安装配置 ## + +MAC 系统一般都自带有 Python2.x 版本的环境,不过现在都不用 2.x 的版本了,所以建议你在 https://www.python.org/downloads/mac-osx/ 上下载最新版安装。 + +安装完成之后,如何配置环境变量呢? + +先查看当前环境变量: + +``` +echo $PATH +``` + +然后打开 ``` ~/.bash_profile(没有请新建) ``` + +``` +vi ~/.bash_profile +``` + +我装的是 Python3.7 ,Python 执行路径为:`/Library/Frameworks/Python. Framework/Versions/3.7/bin` 。于是写入 + +``` +export PATH="/Library/Frameworks/Python. Framework/Versions/3.7/bin:$PATH" +``` + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-07-22-084149.png) + +最后保存退出,激活运行一下文件: + +``` +source ~/.bash_profile +``` + + + + + + diff --git a/python1/Introduction.md b/Article/PythonBasis/python1/Introduction.md similarity index 85% rename from python1/Introduction.md rename to Article/PythonBasis/python1/Introduction.md index f227575b..3093e3b0 100644 --- a/python1/Introduction.md +++ b/Article/PythonBasis/python1/Introduction.md @@ -6,11 +6,11 @@ Python 是著名的“龟叔” Guido van Rossum 在 1989 年圣诞节期间, 这是 2017 年 2 月编程语言排行榜 TOP20 榜单: -![2 月编程语言排行榜 TOP20 榜单.png](http://upload-images.jianshu.io/upload_images/2136918-f7fc786f001cbfc0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![2 月编程语言排行榜 TOP20 榜单.png](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-07-22-080118.jpg) 还有就是 Top 10 编程语言 TIOBE 指数走势: -![Top 10 编程语言 TIOBE 指数走势.png](http://upload-images.jianshu.io/upload_images/2136918-2714dba010ea5d75.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-07-22-080145.jpg) 总的来说,这几种编程语言各有千秋,但不难看出,最近几年 Python 的发展非常的快,特别最近流行的机器学习,数据分析,更让 python 快速的发展起来。 @@ -21,3 +21,5 @@ Python 是高级编程语言,它有一个特点就是能快速的开发。Pyth 第一个缺点就是运行速度慢,和C程序相比非常慢,因为Python是解释型语言,你的代码在执行时会一行一行地翻译成CPU能理解的机器码,这个翻译过程非常耗时,所以很慢。而C程序是运行前直接编译成CPU能执行的机器码,所以非常快。 第二个缺点就是代码不能加密。如果要发布你的 Python 程序,实际上就是发布源代码。像 JAVA , C 这些编译型的语言,都没有这个问题,而解释型的语言,则必须把源码发布出去。 + + diff --git a/Article/PythonBasis/python1/Preface.md b/Article/PythonBasis/python1/Preface.md new file mode 100644 index 00000000..de40b80a --- /dev/null +++ b/Article/PythonBasis/python1/Preface.md @@ -0,0 +1,8 @@ +# 前言 # + +每个编程语言的学习,第一个程序都是先向世界问好,Python 也不例外,这节我们先写下第一个 Python 程序 —— Hello World 。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-16-%E7%AC%AC%E4%B8%80%E4%B8%AA%20Python%20%E7%A8%8B%E5%BA%8F.png) + diff --git a/Article/PythonBasis/python1/The_first_procedure.md b/Article/PythonBasis/python1/The_first_procedure.md new file mode 100644 index 00000000..2561c52b --- /dev/null +++ b/Article/PythonBasis/python1/The_first_procedure.md @@ -0,0 +1,28 @@ +# 三、第一个 Python 程序 # + +好了,说了那么多,现在我们可以来写一下第一个 Python 程序了。 + +一开始写 Python 程序,个人不太建议用专门的工具来写,不方便熟悉语法,所以这里我先用 [Sublime Text](http://www.sublimetext.com/) 来写,后期可以改为用 PyCharm 。 + +第一个 Python 程序当然是打印 Hello Python 啦。 + +如果你没编程经验,什么都不懂,没关系,第一个 Python 程序,只要跟着做,留下个印象,尝试一下就好。 + +新建一个文件,命名为 `HelloPython.py` , 注意,这里是以 `.py` 为后缀的文件。 + +然后打开文件,输入 `print('Hello Python')` + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-17-075948.jpg) + + +最后就可以打开命令行窗口,把当前目录切换到 HelloPython.py 所在目录,就可以运行这个程序了,下面就是运行的结果。 + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-17-075956.jpg) + + +当然,如果你是使用 [Sublime Text](http://www.sublimetext.com/) ,并且在安装 Python 的时候配置好了环境变量,直接按 Ctrl + B 就可以运行了,运行结果如下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-17-080018.jpg) + diff --git a/python10/1.md b/Article/PythonBasis/python10/1.md similarity index 52% rename from python10/1.md rename to Article/PythonBasis/python10/1.md index 867d1831..42a13271 100644 --- a/python10/1.md +++ b/Article/PythonBasis/python10/1.md @@ -1,6 +1,8 @@ # 一、Python 的 Magic Method # -在 Python 中,所有以 "__" 双下划线包起来的方法,都统称为"魔术方法"。比如我们接触最多的 `__init__` 。魔术方法有什么作用呢? +在 Python 中,所有以 "__" 双下划线包起来的方法,都统称为"魔术方法"。比如我们接触最多的 `__init__` 。 + +魔术方法有什么作用呢? 使用这些魔术方法,我们可以构造出优美的代码,将复杂的逻辑封装成简单的方法。 @@ -22,6 +24,10 @@ if __name__ == '__main__': 输出的结果: -![Python 类的魔术方法](http://p1ceh5usj.bkt.clouddn.com/Python%20%E7%B1%BB%E7%9A%84%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95.png) +``` +['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] +``` + +可以看到,一个类的魔术方法还是挺多的,不过我们只需要了解一些常见和常用的魔术方法就好了。 + -可以看到,一个类的魔术方法还是挺多的,截图也没有截全,不过我们只需要了解一些常见和常用的魔术方法就好了。 diff --git a/python10/2.md b/Article/PythonBasis/python10/2.md similarity index 75% rename from python10/2.md rename to Article/PythonBasis/python10/2.md index 18af9f42..db00b527 100644 --- a/python10/2.md +++ b/Article/PythonBasis/python10/2.md @@ -1,6 +1,8 @@ # 二、构造(`__new__`)和初始化(`__init__`) # -通过上一篇的内容,我们已经知道定义一个类时,我们经常会通过 `__init__(self)` 的方法在实例化对象的时候,对属性进行设置。比如下面的例子: +通过之前的学习,我们已经知道定义一个类时,我们经常会通过 `__init__(self)` 的方法在实例化对象的时候,对属性进行设置。 + +比如下面的例子: ```python #!/usr/bin/env python3 @@ -14,9 +16,11 @@ class User(object): user=User('两点水',23) ``` -实际上,创建一个类的过程是分为两步的,一步是创建类的对象,还有一步就是对类进行初始化。`__new__` 是用来创建类并返回这个类的实例, 而`__init__` 只是将传入的参数来初始化该实例.`__new__` 在创建一个实例的过程中必定会被调用,但 `__init__` 就不一定,比如通过pickle.load 的方式反序列化一个实例时就不会调用 `__init__` 方法。 +实际上,创建一个类的过程是分为两步的,一步是创建类的对象,还有一步就是对类进行初始化。 + +`__new__` 是用来创建类并返回这个类的实例, 而`__init__` 只是将传入的参数来初始化该实例.`__new__` 在创建一个实例的过程中必定会被调用,但 `__init__` 就不一定,比如通过 pickle.load 的方式反序列化一个实例时就不会调用 `__init__` 方法。 -![Python类创建的过程](http://upload-images.jianshu.io/upload_images/2136918-a2b39b078cc81841?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-Python%E7%B1%BB%E5%88%9B%E5%BB%BA%E7%9A%84%E8%BF%87%E7%A8%8B.png) `def __new__(cls)` 是在 `def __init__(self)` 方法之前调用的,作用是返回一个实例对象。还有一点需要注意的是:`__new__` 方法总是需要返回该类的一个实例,而 `__init__` 不能返回除了 `None` 的任何值 @@ -57,3 +61,5 @@ if __name__ == '__main__': 其实在实际开发中,很少会用到 `__new__` 方法,除非你希望能够控制类的创建。通常讲到 `__new__` ,都是牵扯到 `metaclass`(元类)的。 当然当一个对象的生命周期结束的时候,析构函数 `__del__` 方法会被调用。但是这个方法是 Python 自己对对象进行垃圾回收的。 + + diff --git a/python10/3.md b/Article/PythonBasis/python10/3.md similarity index 100% rename from python10/3.md rename to Article/PythonBasis/python10/3.md diff --git a/python10/4.md b/Article/PythonBasis/python10/4.md similarity index 74% rename from python10/4.md rename to Article/PythonBasis/python10/4.md index bf45a9d6..49eb1b00 100644 --- a/python10/4.md +++ b/Article/PythonBasis/python10/4.md @@ -1,10 +1,20 @@ # 四、对象的描述器 # -一般来说,一个描述器是一个有“绑定行为”的对象属性 (object attribute),它的访问控制被描述器协议方法重写。这些方法是 `__get__()`, `__set__()` , 和 `__delete__()` 。有这些方法的对象叫做描述器。 +一般来说,一个描述器是一个有“绑定行为”的对象属性 (object attribute),它的访问控制被描述器协议方法重写。 -默认对属性的访问控制是从对象的字典里面 (`__dict__`) 中获取 (get) , 设置 (set) 和删除 (delete) 。举例来说, `a.x` 的查找顺序是, `a.__dict__['x']` , 然后 `type(a).__dict__['x']` , 然后找 `type(a)` 的父类 ( 不包括元类 (metaclass) ).如果查找到的值是一个描述器, Python 就会调用描述器的方法来重写默认的控制行为。这个重写发生在这个查找环节的哪里取决于定义了哪个描述器方法。注意, 只有在新式类中时描述器才会起作用。在之前的篇节中已经提到新式类和旧式类的,有兴趣可以查看之前的篇节来看看,至于新式类最大的特点就是所有类都继承自 type 或者 object 的类。 +这些方法是 `__get__()`, `__set__()` , 和 `__delete__()` 。 -在面向对象编程时,如果一个类的属性有相互依赖的关系时,使用描述器来编写代码可以很巧妙的组织逻辑。在 Django 的 ORM 中,models.Model中的 InterField 等字段, 就是通过描述器来实现功能的。 +有这些方法的对象叫做描述器。 + +默认对属性的访问控制是从对象的字典里面 (`__dict__`) 中获取 (get) , 设置 (set) 和删除 (delete) 。 + +举例来说, `a.x` 的查找顺序是, `a.__dict__['x']` , 然后 `type(a).__dict__['x']` , 然后找 `type(a)` 的父类 ( 不包括元类 (metaclass) ).如果查找到的值是一个描述器, Python 就会调用描述器的方法来重写默认的控制行为。 + +这个重写发生在这个查找环节的哪里取决于定义了哪个描述器方法。 + +注意, 只有在新式类中时描述器才会起作用。在之前的篇节中已经提到新式类和旧式类的,有兴趣可以查看之前的篇节来看看,至于新式类最大的特点就是所有类都继承自 type 或者 object 的类。 + +在面向对象编程时,如果一个类的属性有相互依赖的关系时,使用描述器来编写代码可以很巧妙的组织逻辑。在 Django 的 ORM 中,models.Model 中的 InterField 等字段, 就是通过描述器来实现功能的。 我们先看下下面的例子: @@ -129,3 +139,5 @@ if __name__ == '__main__': 我们只是修改了 meter ,并且将其赋值成为 int ,但 foot 也修改了。这是 `__set__` 发挥了作用. 描述器对象 (Meter、Foot) 不能独立存在, 它需要被另一个所有者类 (Distance) 所持有。描述器对象可以访问到其拥有者实例的属性,比如例子中 Foot 的 `instance.meter` 。 + + diff --git a/python10/5.md b/Article/PythonBasis/python10/5.md similarity index 87% rename from python10/5.md rename to Article/PythonBasis/python10/5.md index 64f03124..90cf5251 100644 --- a/python10/5.md +++ b/Article/PythonBasis/python10/5.md @@ -1,8 +1,12 @@ # 五、自定义容器(Container) # -经过之前编章的介绍,我们知道在 Python 中,常见的容器类型有: dict, tuple, list, string。其中也提到过可容器和不可变容器的概念。其中 tuple, string 是不可变容器,dict, list 是可变容器。 可变容器和不可变容器的区别在于,不可变容器一旦赋值后,不可对其中的某个元素进行修改。当然具体的介绍,可以看回之前的文章,有图文介绍。 +经过之前编章的介绍,我们知道在 Python 中,常见的容器类型有: dict, tuple, list, string。其中也提到过可容器和不可变容器的概念。其中 tuple, string 是不可变容器,dict, list 是可变容器。 -那么这里先提出一个问题,这些数据结构就够我们开发使用吗?不够的时候,或者说有些特殊的需求不能单单只使用这些基本的容器解决的时候,该怎么办呢? +可变容器和不可变容器的区别在于,不可变容器一旦赋值后,不可对其中的某个元素进行修改。当然具体的介绍,可以看回之前的文章,有图文介绍。 + +那么这里先提出一个问题,这些数据结构就够我们开发使用吗? + +不够的时候,或者说有些特殊的需求不能单单只使用这些基本的容器解决的时候,该怎么办呢? 这个时候就需要自定义容器了,那么具体我们该怎么做呢? @@ -78,3 +82,5 @@ class FunctionalList: return self.values[:n] ``` + + diff --git a/python10/6.md b/Article/PythonBasis/python10/6.md similarity index 93% rename from python10/6.md rename to Article/PythonBasis/python10/6.md index 1af49bd8..22ab4b42 100644 --- a/python10/6.md +++ b/Article/PythonBasis/python10/6.md @@ -107,6 +107,10 @@ num1 >= num2 ? --------> False |`__xor__(self, other)`|实现了位操作 `^`| -最后,如果对本文感兴趣的,可以关注下公众号: +可以关注下公众号: + +这个公号可能很少更新,但是一更新,就是把整理的一系列文章更新上去。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-WechatIMG697.jpeg) + -![公众号](http://twowater.com.cn/images/20171204192251900.gif) diff --git a/Article/PythonBasis/python10/Preface.md b/Article/PythonBasis/python10/Preface.md new file mode 100644 index 00000000..a1cd4e08 --- /dev/null +++ b/Article/PythonBasis/python10/Preface.md @@ -0,0 +1,11 @@ +# 前言 # + +有时候修改文章,真的修改到想死。真的很耗时间,很烦的。 + +好吧,每次都是安慰自己,快完结了,快更新完了。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-Python%20%E7%9A%84%20Magic%20Method.png) + + diff --git a/python11/1.md b/Article/PythonBasis/python11/1.md similarity index 51% rename from python11/1.md rename to Article/PythonBasis/python11/1.md index 49d3528c..0ebc3eeb 100644 --- a/python11/1.md +++ b/Article/PythonBasis/python11/1.md @@ -15,7 +15,9 @@ DEC = 12 那有没有什么好的方法呢? -这时候我们定义一个 class 类型,每个常量都是 class 里面唯一的实例。正好 Python 提供了 Enum 类来实现这个功能如下: +这时候我们定义一个 class 类型,每个常量都是 class 里面唯一的实例。 + +正好 Python 提供了 Enum 类来实现这个功能如下: ```python #!/usr/bin/env python3 @@ -37,6 +39,14 @@ print('\n', Month.Jan) 输出的结果如下: -![Python3 枚举类型的使用](http://p1ceh5usj.bkt.clouddn.com/Python3%20%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8B%E7%9A%84%E4%BD%BF%E7%94%A8.png) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-Python3%20%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8B%E7%9A%84%E4%BD%BF%E7%94%A8.png) + +我们使用 `Enum` 来定义了一个枚举类。 + +上面的代码,我们创建了一个有关月份的枚举类型 Month ,这里要注意的是构造参数,第一个参数 Month 表示的是该枚举类的类名,第二个 tuple 参数,表示的是枚举类的值;当然,枚举类通过 `__members__` 遍历它的所有成员的方法。 + +注意的一点是 , `member.value` 是自动赋给成员的 `int` 类型的常量,默认是从 1 开始的。 + +**而且 Enum 的成员均为单例(Singleton),并且不可实例化,不可更改** + -可见,我们可以直接使用 `Enum` 来定义一个枚举类。上面的代码,我们创建了一个有关月份的枚举类型 Month ,这里要注意的是构造参数,第一个参数 Month 表示的是该枚举类的类名,第二个 tuple 参数,表示的是枚举类的值;当然,枚举类通过 `__members__` 遍历它的所有成员的方法。注意的一点是 , `member.value` 是自动赋给成员的 `int`类型的常量,默认是从 1 开始的。而且 Enum 的成员均为单例(Singleton),并且不可实例化,不可更改 diff --git a/python11/2.md b/Article/PythonBasis/python11/2.md similarity index 73% rename from python11/2.md rename to Article/PythonBasis/python11/2.md index 14f36d6a..105cff44 100644 --- a/python11/2.md +++ b/Article/PythonBasis/python11/2.md @@ -1,8 +1,15 @@ # 二、Enum 的源码 # -通过上面的实例可以知道通过 `__members__` 可以遍历枚举类的所有成员。那为什么呢? +通过上面的实例可以知道通过 `__members__` 可以遍历枚举类的所有成员。 -我们可以先来大致看看 Enum 的源码是如何实现的;Enum 在模块 enum.py 中,先来看看 Enum 类的片段 +那有没有想过为什么呢? + +当你看到那段代码的时候,有没有想过为什么通过 `__members__` 就能遍历枚举类型的所有成员出来? + + +我们可以先来大致看看 Enum 的源码是如何实现的; + +Enum 在模块 enum.py 中,先来看看 Enum 类的片段 ```python class Enum(metaclass=EnumMeta): @@ -25,4 +32,5 @@ class EnumMeta(type): return MappingProxyType(cls._member_map_) ``` -首先 `__members__` 方法返回的是一个包含一个 Dict 既 Map 的 MappingProxyType,并且通过 @property 将方法 `__members__(cls)` 的访问方式改变为了变量的的形式,既可以直接通过 `__members__` 来进行访问了 \ No newline at end of file +首先 `__members__` 方法返回的是一个包含一个 Dict 既 Map 的 MappingProxyType,并且通过 @property 将方法 `__members__(cls)` 的访问方式改变为了变量的的形式,那么就可以直接通过 `__members__` 来进行访问了 + diff --git a/python11/3.md b/Article/PythonBasis/python11/3.md similarity index 87% rename from python11/3.md rename to Article/PythonBasis/python11/3.md index c61a6ee3..ea4a78da 100644 --- a/python11/3.md +++ b/Article/PythonBasis/python11/3.md @@ -38,8 +38,10 @@ if __name__ == '__main__': 输出的结果如下: -![Python3 自定义类型的枚举类](http://p1ceh5usj.bkt.clouddn.com/Python3%20%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%9E%9A%E4%B8%BE%E7%B1%BB.png) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-Python3%20%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%9E%8B%E7%9A%84%E6%9E%9A%E4%B8%BE%E7%B1%BB.png) 通过上面的例子,可以知道枚举模块定义了具有迭代 (interator) 和比较(comparison) 功能的枚举类型。 它可以用来为值创建明确定义的符号,而不是使用具体的整数或字符串。 + + diff --git a/python11/4.md b/Article/PythonBasis/python11/4.md similarity index 100% rename from python11/4.md rename to Article/PythonBasis/python11/4.md diff --git a/Article/PythonBasis/python11/Preface.md b/Article/PythonBasis/python11/Preface.md new file mode 100644 index 00000000..3d40a7ea --- /dev/null +++ b/Article/PythonBasis/python11/Preface.md @@ -0,0 +1,11 @@ +# 前言 # + +2019年10月14日16:59:38 看了一下,还有五个章节就修改完基础部分了。 + +干就完事了。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-%E6%9E%9A%E4%B8%BE%E7%B1%BB.png) + + diff --git a/python12/1.md b/Article/PythonBasis/python12/1.md similarity index 88% rename from python12/1.md rename to Article/PythonBasis/python12/1.md index f29f4b7b..782a61a7 100644 --- a/python12/1.md +++ b/Article/PythonBasis/python12/1.md @@ -2,6 +2,8 @@ 在了解元类之前,我们先进一步理解 Python 中的类,在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段。在 Python 中这一点也是一样的。 +这点在学习类的章节也强调过了,下面可以通过例子回忆一下: + ```python class ObjectCreator(object): pass @@ -30,7 +32,9 @@ class ObjectCreator(object): pass ``` -当程序运行这段代码的时候,就会在内存中创建一个对象,名字就是ObjectCreator。这个对象(类)自身拥有创建对象(类实例)的能力,而这就是为什么它是一个类的原因。但是,它的本质仍然是一个对象,于是我们可以对它做如下的操作: +当程序运行这段代码的时候,就会在内存中创建一个对象,名字就是ObjectCreator。这个对象(类)自身拥有创建对象(类实例)的能力,而这就是为什么它是一个类的原因。 + +但是,它的本质仍然是一个对象,于是我们可以对它做如下的操作: ```python class ObjectCreator(object): @@ -61,3 +65,5 @@ print(objectCreator) ``` + + diff --git a/python12/2.md b/Article/PythonBasis/python12/2.md similarity index 58% rename from python12/2.md rename to Article/PythonBasis/python12/2.md index df5019c3..fa5715c3 100644 --- a/python12/2.md +++ b/Article/PythonBasis/python12/2.md @@ -1,6 +1,12 @@ # 二、使用 `type()` 动态创建类 # -因为类也是对象,所以我们可以在程序运行的时候创建类。Python 是动态语言。动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。在之前,我们先了了解下 `type()` 函数。 +因为类也是对象,所以我们可以在程序运行的时候创建类。 + +Python 是动态语言。 + +**动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。** + +在之前,我们先了了解下 `type()` 函数。 首先我们新建一个 `hello.py` 的模块,然后定义一个 Hello 的 class , @@ -11,7 +17,9 @@ class Hello(object): print('Hello,', name) ``` -然后在另一个模块中引用 hello 模块,并输出相应的信息。其中 `type()` 函数的作用是可以查看一个类型和变量的类型。 +然后在另一个模块中引用 hello 模块,并输出相应的信息。 + +其中 `type()` 函数的作用是可以查看一个类型和变量的类型。 ```python #!/usr/bin/env python3 @@ -35,9 +43,19 @@ Hello, Py ``` -上面也提到过,`type()` 函数可以查看一个类型或变量的类型,`Hello` 是一个 `class` ,它的类型就是 `type` ,而 `h` 是一个实例,它的类型就是 `com.twowater.hello.Hello`。前面的 `com.twowater` 是我的包名,`hello` 模块在该包名下。 +上面也提到过,`type()` 函数可以查看一个类型或变量的类型,`Hello` 是一个 `class` ,它的类型就是 `type` ,而 `h` 是一个实例,它的类型就是 `com.twowater.hello.Hello`。 + +前面的 `com.twowater` 是我的包名,`hello` 模块在该包名下。 + +在这里还要细想一下,上面的例子中,我们使用 `type()` 函数查看一个类型或者变量的类型。 + +其中查看了一个 `Hello` class 的类型,打印的结果是: `` 。 -在这里还要细想一下,上面的例子中,我们使用 `type()` 函数查看一个类型或者变量的类型。其中查看了一个 `Hello` class 的类型,打印的结果是: `` 。其实 `type()` 函数不仅可以返回一个对象的类型,也可以创建出新的类型。class 的定义是运行时动态创建的,而创建 class 的方法就是使用 `type()` 函数。比如我们可以通过 `type()` 函数创建出上面例子中的 `Hello` 类,具体看下面的代码: +**其实 `type()` 函数不仅可以返回一个对象的类型,也可以创建出新的类型。** + +class 的定义是运行时动态创建的,而创建 class 的方法就是使用 `type()` 函数。 + +比如我们可以通过 `type()` 函数创建出上面例子中的 `Hello` 类,具体看下面的代码: ```python # -*- coding: UTF-8 -*- @@ -83,8 +101,15 @@ Hello, Py type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值)) ``` -好了,了解完具体的参数使用之外,我们看看输出的结果,可以看到,通过 `type()` 函数创建的类和直接写 class 是完全一样的,因为Python 解释器遇到 class 定义时,仅仅是扫描一下 class 定义的语法,然后调用 `type()` 函数创建出 class 的 。 +好了,了解完具体的参数使用之外,我们看看输出的结果,可以看到,通过 `type()` 函数创建的类和直接写 class 是完全一样的。 + +这是因为Python 解释器遇到 class 定义时,仅仅是扫描一下 class 定义的语法,然后调用 `type()` 函数创建出 class 的。 + +不过一般的情况下,我们都是使用 `class ***...` 的方法来定义类的,不过 `type()` 函数也可以让我们创建出类来。 + +也就是说,动态语言本身支持运行期动态创建类,这和静态语言有非常大的不同,要在静态语言运行期创建类,必须构造源代码字符串再调用编译器,或者借助一些工具生成字节码实现,本质上都是动态编译,会非常复杂。 + +**可以看到,在 Python 中,类也是对象,你可以动态的创建类。** -不过一般的情况下,我们都是使用 `class ***...` 的方法来定义类的,不过 `type()` 函数也可以让我们创建出类来。也就是说,动态语言本身支持运行期动态创建类,这和静态语言有非常大的不同,要在静态语言运行期创建类,必须构造源代码字符串再调用编译器,或者借助一些工具生成字节码实现,本质上都是动态编译,会非常复杂。 +其实这也就是当你使用关键字 class 时 Python 在幕后做的事情,而这就是通过元类来实现的。 -可以看到,在 Python 中,类也是对象,你可以动态的创建类。其实这也就是当你使用关键字 class 时 Python 在幕后做的事情,而这就是通过元类来实现的。 \ No newline at end of file diff --git a/python12/3.md b/Article/PythonBasis/python12/3.md similarity index 56% rename from python12/3.md rename to Article/PythonBasis/python12/3.md index f1c66b4a..0db692d4 100644 --- a/python12/3.md +++ b/Article/PythonBasis/python12/3.md @@ -1,8 +1,12 @@ # 三、什么是元类 # -通过上面的介绍,终于模模糊糊的带到元类这里来了。可是我们到现在还不知道元类是什么东东。 +通过上面的介绍,终于模模糊糊的带到元类这里来了。可是我们到现在还不知道元类是什么鬼东西。 -我们创建类的时候,大多数是为了创建类的实例对象。那么元类呢?元类就是用来创建类的。也可以换个理解方式就是:元类就是类的类。 +我们创建类的时候,大多数是为了创建类的实例对象。 + +那么元类呢? + +**元类就是用来创建类的。也可以换个理解方式就是:元类就是类的类。** 通过上面 `type()` 函数的介绍,我们知道可以通过 `type()` 函数创建类: @@ -10,11 +14,21 @@ MyClass = type('MyClass', (), {}) ``` -实际上 `type()` 函数是一个元类。`type()` 就是 Python 在背后用来创建所有类的元类。 +**实际上 `type()` 函数是一个元类。** + +`type()` 就是 Python 在背后用来创建所有类的元类。 那么现在我们也可以猜到一下为什么 `type()` 函数是 type 而不是 Type呢? -这可能是为了和 str 保持一致性,str 是用来创建字符串对象的类,而 int 是用来创建整数对象的类。type 就是创建类对象的类。你可以通过检查 `__class__` 属性来看到这一点。Python 中所有的东西,注意喔,这里是说所有的东西,他们都是对象。这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来。 +这可能是为了和 str 保持一致性,str 是用来创建字符串对象的类,而 int 是用来创建整数对象的类。 + +type 就是创建类对象的类。 + +你可以通过检查 `__class__` 属性来看到这一点。 + +Python 中所有的东西,注意喔,这里是说所有的东西,他们都是对象。 + +这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来。 ```python # 整形 @@ -52,7 +66,9 @@ print(mEat.__class__) ``` -可以看到,上面的所有东西,也就是所有对象都是通过类来创建的,那么我们可能会好奇,`__class__` 的 `__class__` 会是什么呢?换个说法就是,创建这些类的类是什么呢? +可以看到,上面的所有东西,也就是所有对象都是通过类来创建的,那么我们可能会好奇,`__class__` 的 `__class__` 会是什么呢? + +**换个说法就是,创建这些类的类是什么呢?** 我们可以继续在上面的代码基础上新增下面的代码: @@ -72,6 +88,15 @@ print(mEat.__class__.__class__) ``` -认真观察,再理清一下,上面输出的结果是我们把整形 `age` ,字符创 `name` ,函数 `fu` 和对象实例 `mEat` 里 `__class__` 的 `__class__` 打印出来的结果。也可以说是他们类的类打印结果。发现打印出来的 class 都是 type 。 +认真观察,再理清一下,上面输出的结果是我们把整形 `age` ,字符创 `name` ,函数 `fu` 和对象实例 `mEat` 里 `__class__` 的 `__class__` 打印出来的结果。 + +也可以说是他们类的类打印结果。发现打印出来的 class 都是 type 。 + +一开始也提到了,元类就是类的类。 + +也就是元类就是负责创建类的一种东西。 + +你也可以理解为,元类就是负责生成类的。 + +**而 type 就是内建的元类。也就是 Python 自带的元类。** -一开始也提到了,元类就是类的类。也就是元类就是负责创建类的一种东西。你也可以理解为,元类就是负责生成类的。而 type 就是内建的元类。也就是 Python 自带的元类。 \ No newline at end of file diff --git a/python12/4.md b/Article/PythonBasis/python12/4.md similarity index 80% rename from python12/4.md rename to Article/PythonBasis/python12/4.md index a98f6d6d..2376a9b6 100644 --- a/python12/4.md +++ b/Article/PythonBasis/python12/4.md @@ -1,6 +1,14 @@ # 四、自定义元类 # -到现在,我们已经知道元类是什么东东了。那么,从始至终我们还不知道元类到底有啥用。只是了解了一下元类。在了解它有啥用的时候,我们先来了解下怎么自定义元类。因为只有了解了怎么自定义才能更好的理解它的作用。 +到现在,我们已经知道元类是什么鬼东西了。 + +那么,从始至终我们还不知道元类到底有啥用。 + +只是了解了一下元类。 + +在了解它有啥用的时候,我们先来了解下怎么自定义元类。 + +因为只有了解了怎么自定义才能更好的理解它的作用。 首先我们来了解下 `__metaclass__` 属性 @@ -8,11 +16,15 @@ metaclass,直译为元类,简单的解释就是: 当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。 -但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。 +但是如果我们想创建出类呢? + +那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。 连接起来就是:先定义metaclass,就可以创建类,最后创建实例。 -所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。 +所以,metaclass 允许你创建类或者修改类。 + +换句话说,你可以把类看成是 metaclass 创建出来的“实例”。 ```python class MyObject(object): @@ -20,7 +32,11 @@ class MyObject(object): […] ``` -如果是这样写的话,Python 就会用元类来创建类 MyObject。当你写下 `class MyObject(object)`,但是类对象 MyObject 还没有在内存中创建。Python 会在类的定义中寻找 `__metaclass__` 属性,如果找到了,Python 就会用它来创建类 MyObject,如果没有找到,就会用内建的 type 函数来创建这个类。如果还不怎么理解,看下下面的流程图: +如果是这样写的话,Python 就会用元类来创建类 MyObject。 + +当你写下 `class MyObject(object)`,但是类对象 MyObject 还没有在内存中创建。P + +ython 会在类的定义中寻找 `__metaclass__` 属性,如果找到了,Python 就会用它来创建类 MyObject,如果没有找到,就会用内建的 type 函数来创建这个类。如果还不怎么理解,看下下面的流程图: ![__metaclass__的介绍](https://user-gold-cdn.xitu.io/2017/9/6/06c5a4390887abd3d79401848742f5ce) @@ -43,7 +59,9 @@ class Foo(Bar): 答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到 type 或者子类化 type 的东东都可以。 -元类的主要目的就是为了当创建类时能够自动地改变类。通常,你会为API 做这样的事情,你希望可以创建符合当前上下文的类。假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。有好几种方法可以办到,但其中一种就是通过在模块级别设定`__metaclass__` 。采用这种方法,这个模块中的所有类都会通过这个元类来创建,我们只需要告诉元类把所有的属性都改成大写形式就万事大吉了。 +**元类的主要目的就是为了当创建类时能够自动地改变类。** + +通常,你会为API 做这样的事情,你希望可以创建符合当前上下文的类。假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。有好几种方法可以办到,但其中一种就是通过在模块级别设定`__metaclass__` 。采用这种方法,这个模块中的所有类都会通过这个元类来创建,我们只需要告诉元类把所有的属性都改成大写形式就万事大吉了。 幸运的是,`__metaclass__` 实际上可以被任意调用,它并不需要是一个正式的类。所以,我们这里就先以一个简单的函数作为例子开始。 @@ -141,4 +159,5 @@ class UpperAttrMetaclass(type): * 拦截类的创建 * 修改类 -* 返回修改之后的类 \ No newline at end of file +* 返回修改之后的类 + diff --git a/python12/5.md b/Article/PythonBasis/python12/5.md similarity index 69% rename from python12/5.md rename to Article/PythonBasis/python12/5.md index 3feaa97c..c6a0ad7a 100644 --- a/python12/5.md +++ b/Article/PythonBasis/python12/5.md @@ -19,7 +19,11 @@ guy = Person(name='bob', age='35') print guy.age ``` -这并不会返回一个 IntegerField 对象,而是会返回一个 int,甚至可以直接从数据库中取出数据。这是有可能的,因为 models.Model 定义了 `__metaclass__` , 并且使用了一些魔法能够将你刚刚定义的简单的Person类转变成对数据库的一个复杂 hook。Django 框架将这些看起来很复杂的东西通过暴露出一个简单的使用元类的 API 将其化简,通过这个 API 重新创建代码,在背后完成真正的工作。 +这并不会返回一个 IntegerField 对象,而是会返回一个 int,甚至可以直接从数据库中取出数据。 + +这是有可能的,因为 models.Model 定义了 `__metaclass__` , 并且使用了一些魔法能够将你刚刚定义的简单的Person类转变成对数据库的一个复杂 hook。 + +Django 框架将这些看起来很复杂的东西通过暴露出一个简单的使用元类的 API 将其化简,通过这个 API 重新创建代码,在背后完成真正的工作。 Python 中的一切都是对象,它们要么是类的实例,要么是元类的实例,除了 type。type 实际上是它自己的元类,在纯 Python 环境中这可不是你能够做到的,这是通过在实现层面耍一些小手段做到的。 @@ -28,6 +32,6 @@ Python 中的一切都是对象,它们要么是类的实例,要么是元类 [https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python](https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python) -最后如果对本文有兴趣,可以关注公众号: -![公众号](http://twowater.com.cn/images/20171204192251900.gif) + + diff --git a/Article/PythonBasis/python12/Preface.md b/Article/PythonBasis/python12/Preface.md new file mode 100644 index 00000000..327c0790 --- /dev/null +++ b/Article/PythonBasis/python12/Preface.md @@ -0,0 +1,13 @@ +# 前言 # + +Python 界的领袖 Tim Peters 说的: + +> 元类就是深度的魔法,99% 的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类。 + + +所以,这篇文章,认真阅读一遍就好了。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-%E5%85%83%E7%B1%BB.png) + diff --git a/python13/1.md b/Article/PythonBasis/python13/1.md similarity index 55% rename from python13/1.md rename to Article/PythonBasis/python13/1.md index 15f15744..65392887 100644 --- a/python13/1.md +++ b/Article/PythonBasis/python13/1.md @@ -2,20 +2,34 @@ 线程与进程是操作系统里面的术语,简单来讲,每一个应用程序都有一个自己的进程。 -操作系统会为这些进程分配一些执行资源,例如内存空间等。在进程中,又可以创建一些线程,他们共享这些内存空间,并由操作系统调用,以便并行计算。 +操作系统会为这些进程分配一些执行资源,例如内存空间等。 -我们都知道现代操作系统比如 Mac OS X,UNIX,Linux,Windows 等可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听敲代码,一边用 Markdown 写博客,这就是多任务,至少同时有 3 个任务正在运行。当然还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开 PyCharm 就是一个启动了一个 PtCharm 进程,打开 Markdown 就是启动了一个 Md 的进程。 +在进程中,又可以创建一些线程,他们共享这些内存空间,并由操作系统调用,以便并行计算。 -虽然现在多核 CPU 已经非常普及了。可是由于 CPU 执行代码都是顺序执行的,这时候我们就会有疑问,单核 CPU 是怎么执行多任务的呢? +我们都知道现代操作系统比如 Mac OS X,UNIX,Linux,Windows 等可以同时运行多个任务。 -其实就是操作系统轮流让各个任务交替执行,任务 1 执行 0.01 秒,切换到任务 2 ,任务 2 执行 0.01 秒,再切换到任务 3 ,执行 0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于 CPU的执行速度实在是太快了,我们肉眼和感觉上没法识别出来,就像所有任务都在同时执行一样。 +打个比方,你一边在用浏览器上网,一边在听敲代码,一边用 Markdown 写博客,这就是多任务,至少同时有 3 个任务正在运行。 + +当然还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。 + +对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开 PyCharm 就是一个启动了一个 PtCharm 进程,打开 Markdown 就是启动了一个 Md 的进程。 + +虽然现在多核 CPU 已经非常普及了。 + +可是由于 CPU 执行代码都是顺序执行的,这时候我们就会有疑问,单核 CPU 是怎么执行多任务的呢? + +其实就是操作系统轮流让各个任务交替执行,任务 1 执行 0.01 秒,切换到任务 2 ,任务 2 执行 0.01 秒,再切换到任务 3 ,执行 0.01秒……这样反复执行下去。 + +表面上看,每个任务都是交替执行的,但是,由于 CPU的执行速度实在是太快了,我们肉眼和感觉上没法识别出来,就像所有任务都在同时执行一样。 真正的并行执行多任务只能在多核 CPU 上实现,但是,由于任务数量远远多于 CPU 的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。 有些进程不仅仅只是干一件事的啊,比如浏览器,我们可以播放时视频,播放音频,看文章,编辑文章等等,其实这些都是在浏览器进程中的子任务。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。 -由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,一个进程也可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。 +由于每个进程至少要干一件事,所以,一个进程至少有一个线程。 + +当然,一个进程也可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。 那么在 Python 中我们要同时执行多个任务怎么办? @@ -35,4 +49,9 @@ 同时执行多个任务通常各个任务之间并不是没有关联的,而是需要相互通信和协调,有时,任务 1 必须暂停等待任务 2 完成后才能继续执行,有时,任务 3 和任务 4 又不能同时执行,所以,多进程和多线程的程序的复杂度要远远高于我们前面写的单进程单线程的程序。 -因为复杂度高,调试困难,所以,不是迫不得已,我们也不想编写多任务。但是,有很多时候,没有多任务还真不行。想想在电脑上看电影,就必须由一个线程播放视频,另一个线程播放音频,否则,单线程实现的话就只能先把视频播放完再播放音频,或者先把音频播放完再播放视频,这显然是不行的。 \ No newline at end of file +因为复杂度高,调试困难,所以,不是迫不得已,我们也不想编写多任务。 + +但是,有很多时候,没有多任务还真不行。 + +想想在电脑上看电影,就必须由一个线程播放视频,另一个线程播放音频,否则,单线程实现的话就只能先把视频播放完再播放音频,或者先把音频播放完再播放视频,这显然是不行的。 + diff --git a/python13/2.md b/Article/PythonBasis/python13/2.md similarity index 93% rename from python13/2.md rename to Article/PythonBasis/python13/2.md index 28add5af..19b1d413 100644 --- a/python13/2.md +++ b/Article/PythonBasis/python13/2.md @@ -23,6 +23,8 @@ Python 提供两个模块进行多线程的操作,分别是 `thread` 和 `thre 前者是比较低级的模块,用于更底层的操作,一般应用级别的开发不常用。 +因此,我们使用 `threading` 来举个例子: + ```python #!/usr/bin/env python3 # -*- coding: UTF-8 -*- @@ -178,11 +180,17 @@ r_lock = threading.RLock() ## 4、Condition 条件变量 ## -实用锁可以达到线程同步,但是在更复杂的环境,需要针对锁进行一些条件判断。Python 提供了 Condition 对象。使用 Condition 对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition 除了具有 Lock 对象的 acquire 方法和 release 方法外,还提供了 wait 和 notify 方法。线程首先 acquire 一个条件变量锁。如果条件不足,则该线程 wait,如果满足就执行线程,甚至可以 notify 其他线程。其他处于 wait 状态的线程接到通知后会重新判断条件。 +实用锁可以达到线程同步,但是在更复杂的环境,需要针对锁进行一些条件判断。 + +Python 提供了 Condition 对象。 + +**使用 Condition 对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition 除了具有 Lock 对象的 acquire 方法和 release 方法外,还提供了 wait 和 notify 方法。** -其中条件变量可以看成不同的线程先后 acquire 获得锁,如果不满足条件,可以理解为被扔到一个( Lock 或 RLock )的 waiting 池。直达其他线程 notify 之后再重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。 +线程首先 acquire 一个条件变量锁。如果条件不足,则该线程 wait,如果满足就执行线程,甚至可以 notify 其他线程。其他处于 wait 状态的线程接到通知后会重新判断条件。 -![Condition](http://p1ceh5usj.bkt.clouddn.com/Condition.png) +其中条件变量可以看成不同的线程先后 acquire 获得锁,如果不满足条件,可以理解为被扔到一个( Lock 或 RLock )的 waiting 池。直到其他线程 notify 之后再重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-Condition.png) 该模式常用于生产者消费者模式,具体看看下面在线购物买家和卖家的示例: @@ -382,3 +390,5 @@ for i in t1: ## 6、后台线程 ## 默认情况下,主线程退出之后,即使子线程没有 join。那么主线程结束后,子线程也依然会继续执行。如果希望主线程退出后,其子线程也退出而不再执行,则需要设置子线程为后台线程。Python 提供了 `setDeamon` 方法。 + + diff --git a/python13/3.md b/Article/PythonBasis/python13/3.md similarity index 92% rename from python13/3.md rename to Article/PythonBasis/python13/3.md index 88fc1ec8..eddfdce5 100644 --- a/python13/3.md +++ b/Article/PythonBasis/python13/3.md @@ -1,6 +1,10 @@ # 进程 # -Python 中的多线程其实并不是真正的多线程,如果想要充分地使用多核 CPU 的资源,在 Python 中大部分情况需要使用多进程。Python 提供了非常好用的多进程包 multiprocessing,只需要定义一个函数,Python 会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing 支持子进程、通信和共享数据、执行不同形式的同步,提供了 Process、Queue、Pipe、Lock 等组件。 +Python 中的多线程其实并不是真正的多线程,如果想要充分地使用多核 CPU 的资源,在 Python 中大部分情况需要使用多进程。 + +Python 提供了非常好用的多进程包 multiprocessing,只需要定义一个函数,Python 会完成其他所有事情。 + +借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing 支持子进程、通信和共享数据、执行不同形式的同步,提供了 Process、Queue、Pipe、Lock 等组件。 ## 1、类 Process ## @@ -47,7 +51,7 @@ if __name__ == "__main__": 输出的结果: -![多进程输出结果](http://p1ceh5usj.bkt.clouddn.com/%E5%A4%9A%E8%BF%9B%E7%A8%8B%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C.gif) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-%E5%A4%9A%E8%BF%9B%E7%A8%8B%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C.gif) ## 2、把进程创建成类 ## @@ -83,7 +87,7 @@ if __name__ == '__main__': 输出结果如下: -![创建进程类](http://p1ceh5usj.bkt.clouddn.com/%E5%88%9B%E5%BB%BA%E8%BF%9B%E7%A8%8B%E7%B1%BB.gif) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-%E5%88%9B%E5%BB%BA%E8%BF%9B%E7%A8%8B%E7%B1%BB.gif) ## 3、daemon 属性 ## @@ -309,3 +313,5 @@ if __name__ == '__main__': 写进 Queue 的值为:四点水 从 Queue 读取的值为:四点水 ``` + + diff --git a/Article/PythonBasis/python13/Preface.md b/Article/PythonBasis/python13/Preface.md new file mode 100644 index 00000000..c5cc5c9e --- /dev/null +++ b/Article/PythonBasis/python13/Preface.md @@ -0,0 +1,9 @@ +# 前言 # + +学编程,谁没有为线程折腾过啊。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-%E8%8D%89%E6%A0%B9%E5%AD%A6Python%EF%BC%88%E5%8D%81%E4%B8%89%EF%BC%89%20%E7%BA%BF%E7%A8%8B%E5%92%8C%E8%BF%9B%E7%A8%8B.png) + + diff --git a/python14/1.md b/Article/PythonBasis/python14/1.md similarity index 100% rename from python14/1.md rename to Article/PythonBasis/python14/1.md diff --git a/python14/2.md b/Article/PythonBasis/python14/2.md similarity index 97% rename from python14/2.md rename to Article/PythonBasis/python14/2.md index 65c018a0..8f8e8d59 100644 --- a/python14/2.md +++ b/Article/PythonBasis/python14/2.md @@ -9,7 +9,7 @@ 举个例子,比如你使用 `C[ET]O` 匹配到的是 CEO 或 CTO ,也就是说 `[ET]` 代表的是一个 E 或者一个 T 。像上面提到的 `[a-z]` ,就是所有小写字母中的其中一个,这里使用了连字符 “-” 定义一个连续字符的字符范围。当然,像这种写法,里面可以包含多个字符范围的,比如:`[0-9a-fA-F]` ,匹配单个的十六进制数字,且不分大小写。注意了,字符和范围定义的先后顺序对匹配的结果是没有任何影响的。 -其实说了那么多,只是想证明,字符集一对方括号 “[]” 里面的字符关系是或关系,下面看一个例子: +其实说了那么多,只是想证明,字符集一对方括号 “[]” 里面的字符关系是"或(OR)"关系,下面看一个例子: ```Python diff --git a/python14/3.md b/Article/PythonBasis/python14/3.md similarity index 100% rename from python14/3.md rename to Article/PythonBasis/python14/3.md diff --git a/python14/4.md b/Article/PythonBasis/python14/4.md similarity index 100% rename from python14/4.md rename to Article/PythonBasis/python14/4.md diff --git a/python14/5.md b/Article/PythonBasis/python14/5.md similarity index 100% rename from python14/5.md rename to Article/PythonBasis/python14/5.md diff --git a/python14/6.md b/Article/PythonBasis/python14/6.md similarity index 100% rename from python14/6.md rename to Article/PythonBasis/python14/6.md diff --git a/Article/PythonBasis/python14/Preface.md b/Article/PythonBasis/python14/Preface.md new file mode 100644 index 00000000..1d7b6d6c --- /dev/null +++ b/Article/PythonBasis/python14/Preface.md @@ -0,0 +1,5 @@ +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%BA%86%E8%A7%A3%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.png) + + diff --git "a/python14/\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" "b/Article/PythonBasis/python14/\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" similarity index 100% rename from "python14/\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" rename to "Article/PythonBasis/python14/\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" diff --git "a/python14/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" "b/Article/PythonBasis/python14/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" similarity index 100% rename from "python14/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" rename to "Article/PythonBasis/python14/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" diff --git "a/python14/\350\215\211\346\240\271\345\255\246Python\357\274\210\345\215\201\345\233\233\357\274\211 \344\270\200\346\255\245\344\270\200\346\255\245\344\272\206\350\247\243\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" "b/Article/PythonBasis/python14/\350\215\211\346\240\271\345\255\246Python\357\274\210\345\215\201\345\233\233\357\274\211 \344\270\200\346\255\245\344\270\200\346\255\245\344\272\206\350\247\243\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" similarity index 100% rename from "python14/\350\215\211\346\240\271\345\255\246Python\357\274\210\345\215\201\345\233\233\357\274\211 \344\270\200\346\255\245\344\270\200\346\255\245\344\272\206\350\247\243\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" rename to "Article/PythonBasis/python14/\350\215\211\346\240\271\345\255\246Python\357\274\210\345\215\201\345\233\233\357\274\211 \344\270\200\346\255\245\344\270\200\346\255\245\344\272\206\350\247\243\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.png" diff --git a/python15/1.md b/Article/PythonBasis/python15/1.md similarity index 95% rename from python15/1.md rename to Article/PythonBasis/python15/1.md index 6ce644d5..8809f64f 100644 --- a/python15/1.md +++ b/Article/PythonBasis/python15/1.md @@ -91,7 +91,7 @@ print(time) 这里最直接的表现就是全局变量 `time` 至此至终都没有修改过,这里还是用了 `nonlocal` 关键字,表示在函数或其他作用域中使用外层(非全局)变量。那么上面那段代码具体的运行流程是怎样的。我们可以看下下图: -![Python 闭包解决](http://p1ceh5usj.bkt.clouddn.com/python15/Python%20%E9%97%AD%E5%8C%85%E8%A7%A3%E5%86%B3.png) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-Python%20%E9%97%AD%E5%8C%85%E8%A7%A3%E5%86%B3.png) 这种内部函数的局部作用域中可以访问外部函数局部作用域中变量的行为,我们称为: 闭包。更加直接的表达方式就是,当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。k @@ -146,6 +146,5 @@ print(f.__closure__[0].cell_contents) 闭包的过程其实好比类(父函数)生成实例(闭包),不同的是父函数只在调用时执行,执行完毕后其环境就会释放,而类则在文件执行时创建,一般程序执行完毕后作用域才释放,因此对一些需要重用的功能且不足以定义为类的行为,使用闭包会比使用类占用更少的资源,且更轻巧灵活。 -欢迎打开微信扫一扫,关注微信公众号: -![微信公众号](http://twowater.com.cn/images/20171204192251900.gif) + diff --git a/python16/1.md b/Article/PythonBasis/python16/1.md similarity index 95% rename from python16/1.md rename to Article/PythonBasis/python16/1.md index 3a0b8e5c..8316e9d6 100644 --- a/python16/1.md +++ b/Article/PythonBasis/python16/1.md @@ -210,6 +210,4 @@ print_args('两点水', sex='男', age=99) ``` -至此,[草根学 Python](https://github.com/TwoWater/Python) 入门系列文章结束了。如果感兴趣的话,可以关注微信公众号,回复 “Python” 获取更多的 Python 学习资料。 -![微信公众号](http://twowater.com.cn/images/20171204192251900.gif) diff --git a/Article/PythonBasis/python2/Grammar.md b/Article/PythonBasis/python2/Grammar.md new file mode 100644 index 00000000..44b5fa8e --- /dev/null +++ b/Article/PythonBasis/python2/Grammar.md @@ -0,0 +1,16 @@ +# 一、Python 语法的简要说明 # + +每种语言都有自己的语法,不管是自然语言(英语,中文)还是计算机编程语言。 + +Python 也不例外,它也有自己的语法规则,然后编辑器或者解析器根据符合语法的程序代码转换成 CPU 能够执行的机器码,然后执行。 + +Python 的语法比较简单,采用缩进方式。 + +![Python语法.png](http://upload-images.jianshu.io/upload_images/2136918-b9b072c2587cc89e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + +如上面的代码截图,以 # 开头的语句是注释,其他每一行都是一个语句,当语句以冒号 : 结尾时,缩进的语句视为代码块。 + +要注意的是 Python 程序是大小写敏感的,如果写错了大小写,程序会报错。 + +更多的说明可以看看之前的文章:[Python代码规范中的简明概述](https://www.readwithu.com/codeSpecification/codeSpecification_first.html) + diff --git a/Article/PythonBasis/python2/Preface.md b/Article/PythonBasis/python2/Preface.md new file mode 100644 index 00000000..50339701 --- /dev/null +++ b/Article/PythonBasis/python2/Preface.md @@ -0,0 +1,10 @@ +# 前言 # + +最近要开始新的项目,工作又开始忙起来了,不过还是每天要抽时间来写博客,但不可能做到日更,因为一篇博客,写的时间还是挺长的。[Gitbook](https://www.readwithu.com/) 同时更新喔。 + +注:看到以前矫情的话语,一下子就想把它给删掉。可以刚刚按了删除键才发现,删了之后,不知道写什么了。就瞬间撤销了。这一章节中改动了挺多东西的,也新增了很多例子。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%8F%98%E9%87%8F.png) + diff --git a/Article/PythonBasis/python2/StringCoding.md b/Article/PythonBasis/python2/StringCoding.md new file mode 100644 index 00000000..e7e301b8 --- /dev/null +++ b/Article/PythonBasis/python2/StringCoding.md @@ -0,0 +1,30 @@ +# 四、 字符串的编码问题 # + +我们都知道计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),0 - 255被用来表示大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母 A 的编码是 65,小写字母 z 的编码是 122。 + +如果要表示中文,显然一个字节是不够的,至少需要两个字节,而且还不能和 ASCII 编码冲突,所以,中国制定了 GB2312 编码,用来把中文编进去。 + +类似的,日文和韩文等其他语言也有这个问题。为了统一所有文字的编码,Unicode 应运而生。Unicode 把所有语言都统一到一套编码里,这样就不会再有乱码问题了。 + +Unicode 通常用两个字节表示一个字符,原有的英文编码从单字节变成双字节,只需要把高字节全部填为 0 就可以。 + +因为 Python 的诞生比 Unicode 标准发布的时间还要早,所以最早的Python 只支持 ASCII 编码,普通的字符串 'ABC' 在 Python 内部都是 ASCII 编码的。 + +Python 在后来添加了对 Unicode 的支持,以 Unicode 表示的字符串用`u'...'`表示。 + +不过在最新的 Python 3 版本中,字符串是以 Unicode 编码的,也就是说,Python 的字符串支持多语言。就像上面的例子一样,我的代码中没有加`u'...'`,也能正常显示。 + +不过由于 Python 源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为 UTF-8 编码。当Python 解释器读取源代码时,为了让它按 UTF-8 编码读取,我们通常在文件开头写上这两行: + +```python +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +``` + +第一行注释是为了告诉 Linux/OS X 系统,这是一个 Python 可执行程序,Windows 系统会忽略这个注释; + +第二行注释是为了告诉 Python 解释器,按照 UTF-8 编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。 + +申明了 UTF-8 编码并不意味着你的 .py 文件就是 UTF-8 编码的,必须并且要确保文本编辑器正在使用 UTF-8 without BOM 编码 + + diff --git a/Article/PythonBasis/python2/Type_conversion.md b/Article/PythonBasis/python2/Type_conversion.md new file mode 100644 index 00000000..3717efc5 --- /dev/null +++ b/Article/PythonBasis/python2/Type_conversion.md @@ -0,0 +1,69 @@ +# 五、基本数据类型转换 # + +Python 中基本数据类型转换的方法有下面几个。 + +|方法|说明| +|-----|------| +|int(x [,base ]) | 将x转换为一个整数 | +|float(x ) | 将x转换到一个浮点数 | +|complex(real [,imag ])| 创建一个复数 | +|str(x ) | 将对象 x 转换为字符串 | +|repr(x ) | 将对象 x 转换为表达式字符串 | +|eval(str ) | 用来计算在字符串中的有效 Python 表达式,并返回一个对象 | +|tuple(s ) | 将序列 s 转换为一个元组 | +|list(s ) | 将序列 s 转换为一个列表 | +|chr(x ) | 将一个整数转换为一个字符 | +|unichr(x ) | 将一个整数转换为 Unicode 字符 | +|ord(x ) | 将一个字符转换为它的整数值 | +|hex(x ) | 将一个整数转换为一个十六进制字符串 | +|oct(x ) | 将一个整数转换为一个八进制字符串 | + +注:在 Python 3 里,只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。 + +这里我们可以尝试一下这些函数方法。 + +比如 `int()` 函数,将符合规则的字符串类型转化为整数 。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-30-091547.png) + +输出结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-30-091648.png) + +注意这里是符合规则的字符串类型,如果是文字形式等字符串是不可以被 `int()` 函数强制转换的。 + +还有小数形式的字符串也是不能用 `int()` 函数转换的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-064739.png) + +这样转换会报错。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-064811.png) + +但这并不是意味着浮点数不能转化为整数,而是小数形式的字符串不能强转为字符串。 + +浮点数还是可以通过 `int()` 函数转换的。 + +比如: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-065336.png) + +输出结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-065407.png) + +但是你会发现,结果是 88 ,后面小数点的 0.88 被去掉了。 + +这是因为 `int()` 函数是将数据转为整数。如果是浮点数转为整数,那么 `int()` 函数就会做取整处理,只取整数部分。所以输出的结果为 88 。 + +其余的方法就不一一列举了,只要多用,多试,这些方法都会慢慢熟悉的。还有如果是初学者,完全可以每个方法都玩一下,写一下,随便写,然后运行看结果,反正你的电脑又不会因为这样而玩坏的。 + + + + + + + + + + diff --git a/Article/PythonBasis/python2/Type_of_data.md b/Article/PythonBasis/python2/Type_of_data.md new file mode 100644 index 00000000..3b4d826e --- /dev/null +++ b/Article/PythonBasis/python2/Type_of_data.md @@ -0,0 +1,180 @@ +# 三、Python 的基本数据类型 # + +## 1、字符串 ## + +字符串英文 string ,是 python 中随处可见的数据类型,字符串的识别也非常的简单,就是用「引号」括起来的。 + +引号包括单引号 `' '` ,双引号 `" "` 和 三引号 `''' '''` ,比如 `'abc'` ,`"123"` 等等。 + +这里请注意,单引号 `''` 或双引号 `""` 本身只是一种表示方式,不是字符串的一部分,因此,字符串 `'abc'` 只有 a,b,c 这 3 个字符。 + +如果善于思考的你,一定会问? + +为什么要有单引号 `' '` ,双引号 `" "` 和 三引号 `''' '''` 啊,直接定死一个不就好了,搞那么麻烦,那么多规则表达同一个东西干嘛? + +对,一般来说一种语法只用一个规则来表示是最好的,竟然现在字符串有三种不同的表示,证明是有原因的。 + +那么我们先来看下这三种方式,来定义同样内容的字符串,再把它打印出来,看看是怎样的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-071320.png) + +打印出来的结果是一样的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-071403.png) + +那如果我们的字符串不是 `两点水`,是 `两'点'水` 这样呢? + +这样就直接报错了。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-071800.png) + +但是要注意,用单引号 `' '` 不行,用双引号 `" "` 是可以的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-072459.png) + +打印的结果也跟预想的一样: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-072523.png) + +至于三引号,也是一样的,如果字符串内容里面含有双引号,也是会报同样的错误的。那么这时候你就可以用三引号了。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-072701.png) + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-072829.png) + +那么用单引号,双引号定义的字符串就不能表示这样的内容吗? + +并不是的,你可以使用转义字符。 + +比如单引号,你可以使用 `\'` 来表示,双引号可以使用 `\"` 来表示。 + +注意,这里的是反斜杠 `\`, 不是斜杆 `/` 。 + +了解了之后,直接程序测试一下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-073544.png) + +运行结果如下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-073601.png) + +最后,也提一下, 三引号 `''' '''` 是直接可以分行的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-074157.png) + +运行结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-074209.png) + + + + + + +## 2、整数 ## + +整数英文为 integer 。代码中的整数跟我们平常认识的整数一样,包括正整数、负整数和零,是没有小数点的数字。 + +Python 可以处理任意大小的整数,例如:`1`,`100`,`-8080`,`0`,等等。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-075017.png) + +运行结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-075046.png) + +当然,要注意了,如果数字你用引号括起来了,那就属于字符串,而不属于整数。比如 `'100'` , 这 100 是字符串,不是整数。 + +在现实世界中,整数我们通常会做计算,因此代码世界也是一样,整数可以直接加减乘除。 + +比如: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-075748.png) + +程序运行结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-29-075806.png) + +这里提示下大家,看看上面的例子,有没有发现什么? + +看下 `int4` 打印出来的结果,是 `0.5` , 是一个小数。 + +而我们上面对整数的定义是什么? + +是没有小数点的数字。 + +因此 `int4` 肯定不是整数。 + +这里我们可以使用 `type()` 函数来查看下类型。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-30-032745.png) + +结果如下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-30-032826.png) + +可以看到 `int4` 是 float 类型,而 `int1` ,`int2`,`int3` 都是 int 整数类型。 + +那么 float 是什么类型呢? + +float 是浮点数类型,是我们下面会说到的。 + +在说浮点数之前,各位可以看下 Python 的算术运算符有哪些,有个印象。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-30-034538.png) + + + + + +## 3、浮点数 ## + +浮点数的英文名是 float ,是指带小数的数字。 + +浮点数跟整数有很多类似的地方,但是浮点数是最折磨人的,也是最难让人捉摸透的。 + +就好比世界级的大佬 Herb Sutter 说的:「世上的人可以分为3类:一种是知道自己不懂浮点运算的;一种是以为自己懂浮点运算的;最后一种是极少的专家级人物,他们想知道自己是否有可能,最终完全理解浮点运算。」 + +为什么这么说呢? + +看下面的例子 ,像整数一样,只是基本的浮点数加法运算。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-30-081702.png) + +可是运算结果,对于初学者来说,可能会接受不了。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-30-081922.png) + +对于第一个还好,`0.55+0.41` 等于 0.96 ,运算结果完全一致。可是后面两个,你会发现怎么出现了那么多个零。 + +这是因为计算机对浮点数的表达本身是不精确的。保存在计算机中的是二进制数,二进制对有些数字不能准确表达,只能非常接近这个数。 + +所以我们在对浮点数做运算和比较大小的时候要小心。 + + + + +## 4、布尔值 ## + +布尔值和布尔代数的表示完全一致,一个布尔值只有 `True` 、 `False `两种值,要么是 `True`,要么是 `False`,在 Python 中,可以直接用 True、False 表示布尔值(请注意大小写),也可以通过布尔运算计算出来。 + +布尔值可以用 `and`、`or` 和 `not` 运算。 + +`and` 运算是与运算,只有所有都为 True,and 运算结果才是 True。 + +`or` 运算是或运算,只要其中有一个为 True,or 运算结果就是 True。 + +`not` 运算是非运算,它是一个单目运算符,把 True 变成 False,False 变成 True。 + + + +## 5、空值 ## + +基本上每种编程语言都有自己的特殊值——空值,在 Python 中,用 None 来表示 + + + + + + + diff --git a/python2/Variable.md b/Article/PythonBasis/python2/Variable.md similarity index 90% rename from python2/Variable.md rename to Article/PythonBasis/python2/Variable.md index 5027acd7..06e66d01 100644 --- a/python2/Variable.md +++ b/Article/PythonBasis/python2/Variable.md @@ -1,4 +1,4 @@ -# 四、Python 中的变量 # +# 六、Python 中的变量 # ## 1、变量的创建和赋值 ## @@ -23,7 +23,9 @@ a=88 这主要是变量 a 一开始是指向了字符串 `Hello Python` ,`b=a` 创建了变量 b ,变量 b 也指向了a 指向的字符串 `Hello Python`,最后 `a=123`,把 变量 a 重新指向了 `123`,所以最后输出变量 b 是 `Hello Python` -![变量的指向](https://dn-mhke0kuv.qbox.me/91ef196a3875cb12abeb.png) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-%E5%8F%98%E9%87%8F%E7%9A%84%E6%8C%87%E5%90%91.png) + + ## 3、多个变量赋值 ## @@ -41,4 +43,5 @@ a = b = c = 1 a, b, c = 1, 2, "liangdianshui" ``` -以上实例,两个整型对象 1 和 2 的分配给变量 a 和 b,字符串对象 "liangdianshui" 分配给变量 c。 \ No newline at end of file +以上实例,两个整型对象 1 和 2 的分配给变量 a 和 b,字符串对象 "liangdianshui" 分配给变量 c。 + diff --git a/Article/PythonBasis/python2/print.md b/Article/PythonBasis/python2/print.md new file mode 100644 index 00000000..91817543 --- /dev/null +++ b/Article/PythonBasis/python2/print.md @@ -0,0 +1,52 @@ +# 二、print() 函数 # + +这里先说一下 `print()` 函数,如果你是新手,可能对函数不太了解,没关系,在这里你只要了解它的组成部分和作用就可以了,后面函数这一块会详细说明的。 + +`print()` 函数由两部分构成 : + +1. 指令:print +2. 指令的执行对象,在 print 后面的括号里的内容 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-17-074454.png) + +而 `print()` 函数的作用是让计算机把你给它的指令结果,显示在屏幕的终端上。这里的指令就是你在 `print()` 函数里的内容。 + +比如在上一章节中,我们的第一个 Python 程序,打印 `print('Hello Python')` + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-17-080241.png) + +它的执行流程如下: + +1. 向解释器发出指令,打印 'Hello Python' +2. 解析器把代码解释为计算器能读懂的机器语言 +3. 计算机执行完后就打印结果 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-17-083751.png) + +可能这里有人会问,为什么要加单引号,直接 `print(Hello Python)` 不行吗? + +如果你写代码过程中,有这样的疑问,直接写一下代码,自己验证一下是最好的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-17-094034.png) + +显然,去掉单引号后,运行结果标红了(报错),证明这是不可以的。 + +主要是因为这不符合 Python 的语法规则,去掉单引号后, Python 解释器根本没法看懂你写的是什么。 + +所以就报 ` SyntaxError: invalid syntax` 的错误,意思是:语法错误。说明你的语句不合规则。 + + + + + + + + + + + + + + + + diff --git a/Article/PythonBasis/python3/List.md b/Article/PythonBasis/python3/List.md new file mode 100644 index 00000000..059adb86 --- /dev/null +++ b/Article/PythonBasis/python3/List.md @@ -0,0 +1,268 @@ +# 一、List(列表) # + +## 1、什么是 List (列表) + +List (列表)是 Python 内置的一种数据类型。 它是一种有序的集合,可以随时添加和删除其中的元素。 + +那为什么要有 List (列表)呢? + +我们用一个例子来说明。 + +现在有一个团队要出去玩,要先报名。如果用我们之前学过的知识,那么就是用一个字符串变量把他们都记录起来。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-080527.png) + +但是这样太麻烦了,而且也不美观。 + +在编程中,一定要学会偷懒,避免「重复性工作」。如果有一百个成员,那么你及时是复制粘贴,也会把你写烦。 + +这时候就可以使用列表了。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-080835.png) + +就这样,一行代码就可以存放 N 多个名字了。 + + +## 2、怎么创建 List(列表) ## + +从上面的例子可以分析出,列表的格式是这样的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-081342.png) + +其实列表就是用中括号 `[]` 括起来的数据,里面的每一个数据就叫做元素。每个元素之间使用逗号分隔。 + +而且列表的数据元素不一定是相同的数据类型。 + +比如: + +```python +list1=['两点水','twowter','liangdianshui',123] +``` + +这里有字符串类型,还有整数类型。 + +我们尝试把他打印出来,看看打印的结果是怎样的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-081912.png) + +结果如下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-081951.png) + + +## 3、如何访问 List(列表)中的值 ## + +就像一开始的例子,我们有时候不需要把全部人员的姓名都打印出来,有时候我们需要知道第 3 个报名的人是谁?前两名报名的是谁? + +那么怎么从列表中取出来呢? + +换种问法就是,怎么去访问列表中的值? + +这时候我们可以通过列表的下标索引来访问列表中的值,同样你也可以使用方括号的形式截取字符。 + +例如: + +```python +name = ['一点水', '两点水', '三点水', '四点水', '五点水'] + +# 通过索引来访问列表 +print(name[2]) +# 通过方括号的形式来截取列表中的数据 +print(name[0:2]) +``` + +输出的结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-090321.png) + +可见,我们需要知道知道 `name` 这个列表中第三个报名的是谁?只需要用 `name[2]` 就可以了。 + +这里你会问,为什么是 2 ,不是 3 呢? + +这是因为在编程世界中,都是从 0 开始的,而不是我们生活习惯中从 1 开始。 + +所以需要知道第三个是谁? + +那就是 `name[2]` 就可以了。 + +从例子来看,我们还把 `name[0:2]` 的结果打印出来了。 + +从打印结果来看,只打印了第一,第二个元素内容。 + +这里可能会有疑问? + +为什么不是打印前三个啊,不是说 2 就是第 3 个吗? + +那是因为这是**左闭右开**区间的。 + +所以 `name[0:2]` 的意思就是从第 0 个开始取,取到第 2 个,但是不包含第 2 个。 + +还是那句话,为了更好的理解,可以多去尝试,多去玩编程。 + +所以你可以尝试下下面的各种方式: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-091524.png) + +看看输出的结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-091624.png) + +根据输出的结果和上面讲到的知识,就很容易理解其中的一些用法了。 + + + + + ## 4、怎么去更新 List(列表) ## + +还是一开始的例子,我们用代码记录了报名人的名字,那后面可能会有新人加入,也有可能会发现一开始写错名字了,想要修改。 + +这时候怎么办呢? + +这时候可以通过索引对列表的数据项进行修改或更新,也可以使用 append() 方法来添加列表项。 + +```python +name = ['一点水', '两点水', '三点水', '四点水', '五点水'] + + +# 通过索引对列表的数据项进行修改或更新 +name[1]='2点水' +print(name) + +# 使用 append() 方法来添加列表项 +name.append('六点水') +print(name) +``` + +输出的结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-092406.png) + + + + + +## 5、怎么删除 List(列表) 里面的元素 ## + +那既然这样,肯定会有人中途退出的。 + +那么我们就需要在列表中,把他的名字去掉。 + +这时候使用 del 语句来删除列表的的元素 + +```python +name = ['一点水', '两点水', '三点水', '四点水', '五点水'] + +print(name) + +# 使用 del 语句来删除列表的的元素 +del name[3] +print(name) +``` + +输出的结果: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-092705.png) + +你看输出的结果,列表中已经没有了 `四点水` 这个数据了。证明已经删除成功了。 + + + + + + +## 6、List(列表)运算符 ## + +列表对 `+` 和 `*` 的操作符与字符串相似。`+` 号用于组合列表,`*` 号用于重复列表。 + +|Python 表达式|结果|描述| +|-----------|-----|-----| +|len([1, 2, 3])|3|计算元素个数| +|[1, 2, 3] + [4, 5, 6]| [1, 2, 3, 4, 5, 6]| 组合| +|['Hi!'] * 4|['Hi!', 'Hi!', 'Hi!', 'Hi!']|复制| +|3 in [1, 2, 3]|True|元素是否存在于列表中| +|for x in [1, 2, 3]: print x,|1 2 3|迭代| + + +## 7、List (列表)函数&方法 ## + +|函数&方法|描述| +|----|----| +|len(list)|列表元素个数| +|max(list)|返回列表元素最大值| +|min(list)|返回列表元素最小值| +|list(seq)|将元组转换为列表| +|list.append(obj)|在列表末尾添加新的对象| +|list.count(obj)|统计某个元素在列表中出现的次数| +|list.extend(seq)|在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)| +|list.index(obj)|从列表中找出某个值第一个匹配项的索引位置| +|list.insert(index, obj)|将对象插入列表| +|list.pop(obj=list[-1])|移除列表中的一个元素(默认最后一个元素),并且返回该元素的值| +|list.remove(obj)|移除列表中的一个元素(参数是列表中元素),并且不返回任何值| +|list.reverse()|反向列表中元素| +|list.sort([func])|对原列表进行排序| + + +## 8、实例 ## + + +最后通过一个例子来熟悉了解 List 的操作 + +例子: + +```python +#-*-coding:utf-8-*- +#-----------------------list的使用---------------------------------- + +# 1.一个产品,需要列出产品的用户,这时候就可以使用一个 list 来表示 +user=['liangdianshui','twowater','两点水'] +print('1.产品用户') +print(user) + +# 2.如果需要统计有多少个用户,这时候 len() 函数可以获的 list 里元素的个数 +len(user) +print('\n2.统计有多少个用户') +print(len(user)) + +# 3.此时,如果需要知道具体的用户呢?可以用过索引来访问 list 中每一个位置的元素,索引是0从开始的 +print('\n3.查看具体的用户') +print(user[0]+','+user[1]+','+user[2]) + +# 4.突然来了一个新的用户,这时我们需要在原有的 list 末尾加一个用户 +user.append('茵茵') +print('\n4.在末尾添加新用户') +print(user) + +# 5.又新增了一个用户,可是这个用户是 VIP 级别的学生,需要放在第一位,可以通过 insert 方法插入到指定的位置 +# 注意:插入数据的时候注意是否越界,索引不能超过 len(user)-1 +user.insert(0,'VIP用户') +print('\n5.指定位置添加用户') +print(user) + +# 6.突然发现之前弄错了,“茵茵”就是'VIP用户',因此,需要删除“茵茵”;pop() 删除 list 末尾的元素 +user.pop() +print('\n6.删除末尾用户') +print(user) + +# 7.过了一段时间,用户“liangdianshui”不玩这个产品,删除了账号 +# 因此需要要删除指定位置的元素,用pop(i)方法,其中i是索引位置 +user.pop(1) +print('\n7.删除指定位置的list元素') +print(user) + +# 8.用户“两点水”想修改自己的昵称了 +user[2]='三点水' +print('\n8.把某个元素替换成别的元素') +print(user) + +# 9.单单保存用户昵称好像不够好,最好把账号也放进去 +# 这里账号是整数类型,跟昵称的字符串类型不同,不过 list 里面的元素的数据类型是可以不同的 +# 而且 list 元素也可以是另一个 list +newUser=[['VIP用户',11111],['twowater',22222],['三点水',33333]] +print('\n9.不同元素类型的list数据') +print(newUser) + +``` + +![list的使用](http://upload-images.jianshu.io/upload_images/2136918-65d31cae9f8bb34d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + + diff --git a/Article/PythonBasis/python3/Preface.md b/Article/PythonBasis/python3/Preface.md new file mode 100644 index 00000000..08afe8d4 --- /dev/null +++ b/Article/PythonBasis/python3/Preface.md @@ -0,0 +1,12 @@ +# 前言 # + +之前我们学习了字符串,整数,浮点数几种基本数据类型,现在我们接着学习两种新的数据类型,列表(List)和元组(tuple)。 + +注: [https://www.readwithu.com/](https://www.readwithu.com/) 同步更新。 + + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-01-List%20%E5%92%8C%20Tuple.png) + + diff --git a/Article/PythonBasis/python3/tuple.md b/Article/PythonBasis/python3/tuple.md new file mode 100644 index 00000000..d5b842a6 --- /dev/null +++ b/Article/PythonBasis/python3/tuple.md @@ -0,0 +1,196 @@ +# 二、tuple(元组) # + +## 1、什么是元组 (tuple) ## + +上一节刚说了一个有序列表 List ,现在说另一种有序列表叫元组:tuple 。 + +tuple 和 List 非常类似,但是 tuple 一旦初始化就不能修改。 +也就是说元组(tuple)是不可变的,那么不可变是指什么意思呢? + +元组(tuple) 不可变是指当你创建了 tuple 时候,它就不能改变了,也就是说它也没有 append(),insert() 这样的方法,但它也有获取某个索引值的方法,但是不能赋值。 + +那么为什么要有 tuple 呢? + +那是因为 tuple 是不可变的,所以代码更安全。 + +所以建议能用 tuple 代替 list 就尽量用 tuple 。 + + + +## 2、怎样创建元组(tuple) ## + +元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。 + +```python +tuple1=('两点水','twowter','liangdianshui',123,456) +tuple2='两点水','twowter','liangdianshui',123,456 +``` + +创建空元组 + +```python +tuple3=() +``` + +元组中只包含一个元素时,需要在元素后面添加逗号 + +```python +tuple4=(123,) +``` + +如果不加逗号,创建出来的就不是 元组(tuple),而是指 ```123``` 这个数了。 + + +这是因为括号 () 既可以表示元组(tuple),又可以表示数学公式中的小括号,这就产生了歧义。 + +所以如果只有一个元素时,你不加逗号,计算机就根本没法识别你是要进行整数或者小数运算还是表示元组。 + +因此,Python 规定,这种情况下,按小括号进行计算,计算结果自然是 ```123``` ,而如果你要表示元组的时候,就需要加个逗号。 + +具体看下图 tuple4 和 tuple5 的输出值 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-093847.jpg) + + + + + + + +## 3、如何访问元组(tuple) ## + +元组下标索引也是从 0 开始,元组(tuple)可以使用下标索引来访问元组中的值。 + +```python +#-*-coding:utf-8-*- + +tuple1=('两点水','twowter','liangdianshui',123,456) +tuple2='两点水','twowter','liangdianshui',123,456 + +print(tuple1[1]) +print(tuple2[0]) +``` + +输出的结果: + +![访问 tuple](http://upload-images.jianshu.io/upload_images/2136918-edfb7c9ebc7d5ab0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + + + + + +## 4、修改元组 (tuple) ## + +可能看到这个小标题有人会疑问,上面不是花了一大段来说 tuple 是不可变的吗? + +这里怎么又来修改 tuple (元组) 了。 + +那是因为元组中的元素值是不允许修改的,但我们可以对元组进行连接组合,还有通过修改其他列表的值从而影响 tuple 的值。 + +具体看下面的这个例子: + +```python +#-*-coding:utf-8-*- +list1=[123,456] +tuple1=('两点水','twowater','liangdianshui',list1) +print(tuple1) +list1[0]=789 +list1[1]=100 +print(tuple1) +``` + +输出的结果: +``` +('两点水', 'twowater', 'liangdianshui', [123, 456]) +('两点水', 'twowater', 'liangdianshui', [789, 100]) +``` + + +可以看到,两次输出的 tuple 值是变了的。我们看看 tuple1 的存储是怎样的。 + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-%E4%BF%AE%E6%94%B9tuple%E6%B5%81%E7%A8%8B%E5%9B%BE.png) + + +可以看到,tuple1 有四个元素,最后一个元素是一个 List ,List 列表里有两个元素。 + +当我们把 List 列表中的两个元素 `124` 和 `456` 修改为 `789` 和 `100` 的时候,从输出来的 tuple1 的值来看,好像确实是改变了。 + +但其实变的不是 tuple 的元素,而是 list 的元素。 + +tuple 一开始指向的 list 并没有改成别的 list,所以,tuple 所谓的“不变”是说,tuple 的每个元素,指向永远不变。注意是 tupe1 中的第四个元素还是指向原来的 list ,是没有变的,我们修改的只是列表 List 里面的元素。 + + + +## 5、删除 tuple (元组) ## + +tuple 元组中的元素值是不允许删除的,但我们可以使用 del 语句来删除整个元组 + +```python +#-*-coding:utf-8-*- + +tuple1=('两点水','twowter','liangdianshui',[123,456]) +print(tuple1) +del tuple1 +``` + +## 6、tuple (元组)运算符 ## + +与字符串一样,元组之间可以使用 `+` 号和 `*` 号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的元组。 + +|Python 表达式|结果|描述| +|-----------|-----|-----| +|len((1, 2, 3))|3|计算元素个数| +|(1, 2, 3) + (4, 5, 6)|(1, 2, 3, 4, 5, 6)|连接| +|('Hi!',) * 4|('Hi!', 'Hi!', 'Hi!', 'Hi!')|复制| +|3 in (1, 2, 3)|True|元素是否存在| +|for x in (1, 2, 3): print(x)|1 2 3|迭代| + +## 7、元组内置函数 ## + +|方法|描述| +|----|----| +|len(tuple)|计算元组元素个数| +|max(tuple)|返回元组中元素最大值| +|min(tuple)|返回元组中元素最小值| +|tuple(seq)|将列表转换为元组| + + +## 8、实例 ## + +最后跟列表一样,来一个实例,大家也可以多尝试,去把元组的各种玩法玩一遍。 + +```python +name1 = ('一点水', '两点水', '三点水', '四点水', '五点水') + +name2 = ('1点水', '2点水', '3点水', '4点水', '5点水') + +list1 = [1, 2, 3, 4, 5] + +# 计算元素个数 +print(len(name1)) +# 连接,两个元组相加 +print(name1 + name2) +# 复制元组 +print(name1 * 2) +# 元素是否存在 (name1 这个元组中是否含有一点水这个元素) +print('一点水' in name1) +# 元素的最大值 +print(max(name2)) +# 元素的最小值 +print(min(name2)) +# 将列表转换为元组 +print(tuple(list1)) +``` + +输出的结果如下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-08-31-101523.png) + + + + + + + + diff --git a/python4/Dict.md b/Article/PythonBasis/python4/Dict.md similarity index 66% rename from python4/Dict.md rename to Article/PythonBasis/python4/Dict.md index c8f7699c..706fecb4 100644 --- a/python4/Dict.md +++ b/Article/PythonBasis/python4/Dict.md @@ -1,27 +1,36 @@ # 一、字典(Dictionary) # -经过之前的学习,我们可以知道 list 和 tuple 可以用来表示有序集合,之前我们那个例子是用 list 来存储了用户的昵称 +## 1、什么是 dict(字典) ## + +上一章节,我们学习了列表(List) 和 元组(tuple) 来表示有序集合。 + +而我们在讲列表(list)的时候,我们用了列表(list) 来存储用户的姓名。 ```python -user=['liangdianshui','twowater','两点水'] +name = ['一点水', '两点水', '三点水', '四点水', '五点水'] ``` -如果我们需要把用户的账号也记录进去呢? +那么如果我们为了方便联系这些童鞋,要把电话号码也添加进去,该怎么做呢? 用 list 可以这样子解决: ```python -user=[['liangdianshui','111111'],['twowater','222222'],['两点水','333333']] +name = [['一点水', '131456780001'], ['两点水', '131456780002'], ['三点水', '131456780003'], ['四点水', '131456780004'], ['五点水', '131456780005']] ``` -可是这样表示也不方便,而且很难根据昵称找到对应的昵称,且 list 越长,耗时越长;这时候就可以用 dict (字典)来表示了,Python 内置了 字典(dict),dict 全称dictionary,相当于 JAVA 中的 map,使用键-值(key-value)存储,具有极快的查找速度。 +但是这样很不方便,我们把电话号码记录下来,就是为了有什么事能及时联系上这些童鞋。 + +如果用列表来存储这些,列表越长,我们查找起来耗时就越长。 + +这时候就可以用 dict (字典)来表示了,Python 内置了 字典(dict),dict 全称 dictionary,如果学过 Java ,字典就相当于 JAVA 中的 map,使用键-值(key-value)存储,具有极快的查找速度。 ```python -user={'liangdianshui':'111111' ,'twowater':'222222' ,'两点水':'333333'} +name = {'一点水': '131456780001', '两点水': '131456780002', '三点水': '131456780003', '四点水': '131456780004', '五点水': '131456780005'} ``` -## 1、dict (字典)的创建 ## + +## 2、dict (字典)的创建 ## 字典是另一种可变容器模型,且可存储任意类型对象。 @@ -40,24 +49,34 @@ dict1={'liangdianshui':'111111' ,'twowater':'222222' ,'两点水':'333333'} dict2={'abc':1234,1234:'abc'} ``` -## 2、访问 dict (字典) ## + + +## 3、访问 dict (字典) ## + +我们知道了怎么创建列表了,回归到一开始提出到的问题,为什么使用字典能让我们很快的找出某个童鞋的电话呢? + + ```python -#-*-coding:utf-8-*- -dict1={'liangdianshui':'111111' ,'twowater':'222222' ,'两点水':'333333'} -print(dict1) +name = {'一点水': '131456780001', '两点水': '131456780002', '三点水': '131456780003', '四点水': '131456780004', '五点水': '131456780005'} +print(name['两点水']) ``` + 输出的结果: ``` -{'liangdianshui': '111111', 'twowater': '222222', '两点水': '333333'} +131456780002 ``` +可以看到,如果你知道某个人的名字,也就是 key 值, 就能很快的查找到他对应的电话号码,也就是 Value 。 + 这里需要注意的一点是:如果字典中没有这个键,是会报错的。 -## 3、修改 dict (字典) ## + + +## 4、修改 dict (字典) ## 向字典添加新内容的方法是增加新的键/值对,修改或删除已有键/值对 @@ -81,7 +100,7 @@ print(dict1) {'liangdianshui': '555555', 'twowater': '222222', '两点水': '333333', 'jack': '444444'} ``` -## 4、删除 dict (字典) ## +## 5、删除 dict (字典) ## 通过 `del` 可以删除 dict (字典)中的某个元素,也能删除 dict (字典) @@ -109,7 +128,7 @@ del dict1 {} ``` -## 5、 dict (字典)使用时注意的事项 ## +## 6、 dict (字典)使用时注意的事项 ## (1) dict (字典)是不允许一个键创建两次的,但是在创建 dict (字典)的时候如果出现了一个键值赋予了两次,会以最后一次赋予的值为准 @@ -161,11 +180,10 @@ print(dict1) * 占用空间小,浪费内存很少 -## 6、dict (字典) 的函数和方法 ## +## 7、dict (字典) 的函数和方法 ## |方法和函数|描述| |---------|--------| -|cmp(dict1, dict2)|比较两个字典元素| |len(dict)|计算字典元素个数| |str(dict)|输出字典可打印的字符串表示| |type(variable)|返回输入的变量类型,如果变量是字典就返回字典类型| @@ -174,3 +192,10 @@ print(dict1) |dict.values()|以列表返回字典中的所有值| |popitem()|随机返回并删除字典中的一对键和值| |dict.items()|以列表返回可遍历的(键, 值) 元组数组| + + + + + + + diff --git a/Article/PythonBasis/python4/Preface.md b/Article/PythonBasis/python4/Preface.md new file mode 100644 index 00000000..318dc462 --- /dev/null +++ b/Article/PythonBasis/python4/Preface.md @@ -0,0 +1,15 @@ +# 前言 # + +上一篇文章出现了个明显的知识点错误,不过感谢有个网友的提出,及时进行了修改。也希望各位多多包涵。 + +>注:(2019年09月01日15:28:00) 在修改文章的时候,发现自己两年前写的像屎一样, 忍不住还在群里吐槽一番。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-01-072923.png) + + +# 目录 # + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-01-Dict%20%E5%92%8C%20Set.png) + + diff --git a/python4/Set.md b/Article/PythonBasis/python4/Set.md similarity index 95% rename from python4/Set.md rename to Article/PythonBasis/python4/Set.md index a07cf47a..9fa62591 100644 --- a/python4/Set.md +++ b/Article/PythonBasis/python4/Set.md @@ -1,6 +1,8 @@ # 二、set # -python 的 set 和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素。set 和 dict 类似,但是 set 不存储 value 值的。 +python 的 set 和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素。 + +set 和 dict 类似,但是 set 不存储 value 值的。 ## 1、set 的创建 ## @@ -135,3 +137,5 @@ print(set7) 去除列表里重复元素 set7: {555, 333, 111, 666, 444, 222} ``` + + diff --git a/Article/PythonBasis/python5/Cycle.md b/Article/PythonBasis/python5/Cycle.md new file mode 100644 index 00000000..d8567c35 --- /dev/null +++ b/Article/PythonBasis/python5/Cycle.md @@ -0,0 +1,313 @@ +# 二、循环语句 # + + + +## 1、什么是循环语句 ## + +一般编程语言都有循环语句,为什么呢? + +那就问一下自己,我们弄程序是为了干什么? + +那肯定是为了方便我们工作,优化我们的工作效率啊。 + +而计算机和人类不同,计算机不怕苦也不怕累,也不需要休息,可以一直做。 + +你要知道,计算机最擅长就是做重复的事情。 + +所以这时候需要用到循环语句,循环语句允许我们执行一个语句或语句组多次。 + +循环语句的一般形式如下: + +![python循环语句](http://upload-images.jianshu.io/upload_images/2136918-eaaae2fbfec3330f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + + +在 Python 提供了 for 循环和 while 循环。 + +这里又有一个问题了,如果我想让他运行了一百次之后停止,那该怎么做呢? + +这时候需要用到一些控制循环的语句: + +|循环控制语句|描述| +|------|------| +|break|在语句块执行过程中终止循环,并且跳出整个循环| +|continue|在语句块执行过程中终止当前循环,跳出该次循环,执行下一次循环| +|pass|pass 是空语句,是为了保持程序结构的完整性| + +这些控制语句是为了让我们告诉程序什么时候停止,什么时候不运行这次循环。 + + + + +## 2、 for 循环语句 ## + +我们先来看下 for 循环语句。 + +它的流程图基本如下: + + +![for循环的流程图](http://upload-images.jianshu.io/upload_images/2136918-a0728c1c488238af?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + + +基本的语法格式: + +```python +for iterating_var in sequence: + statements(s) +``` + +那么我们根据他的基本语法格式,随便写个例子测试一下: + + +```python +for letter in 'Hello 两点水': + print(letter) +``` + +输出的结果如下: + +```txt +H +e +l +l +o + +两 +点 +水 +``` + +从打印结果来看,它就是把字符串 `Hello 两点水` 一个一个字符的打印出来。 + +那如果我们把字符串换为字典 dict 呢? + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-094741.png) + +你会发现只打印了字典 dict 中的每一个 key 值。 + +很多时候,我都是建议大家学到一个新的知识点,都多去尝试。 + +你尝试一遍,自己观察出来的结论,好过别人说十遍。 + +如果你不知道怎么去试? + +可以根据我们的例子举一反三,比如上面的 for 循环,试了字符串,字典,那我们之前学的基本数据类型还有什么呢? + +不记得可以再返回去看看,可以把所有的基本类型都拿去尝试一下。 + +比如,你试了之后,会发现整数和浮点数是不可以直接放在 for 循环里面的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-095313.png) + + + + + + +## 3、 range() 函数 ## + +for 循环还常常和 range() 函数搭配使用的。 + +如果不知道 range() 函数 , 我们直接通过一段程序来理解。 + +```python +for i in range(3): + print(i) +``` + +打印的结果为: + +``` +0 +1 +2 +``` + +可见,打印了 0 到 3 。 + +使用 range(x) 函数,就可以生成一个从 0 到 x-1 的整数序列。 + +如果是 `range(a,b)` 函数,你可以生成了一个左闭右开的整数序列。 + +其实例子中的 `range(3)` 可以写成 `range(0,3)`, 结果是一样的。 + +其实使用 range() 函数,我们更多是为了把一段代码重复运行 n 次。 + +这里提个问题,你仔细观察 range() 函数,上面说到的不管是 1 个参数的,还是 2 个参数的都有什么共同的特点? + +不知道你们有没有发现,他都是每次递增 1 的。 + +`range(3)` 就是 0 ,1,2 ,每次递增 1 。 + +`range(3,6)` 就是 3 ,4 ,5 ,也是每次递增 1 的。 + +那能不能每次不递增 1 呢? + +比如我想递增 2 呢? + +在程序的编写中,肯定会遇到这样的需求的。而 python 发展至今,range 函数肯定也会有这种功能。 + +所以 range 函数还有一个三个参数的。 + +比如 `range(0,10,2) ` , 它的意思是:从 0 数到 10(不取 10 ),每次间隔为 2 。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-09-065854.png) + + + + + + +## 4、While 循环语句 ## + +While 循环和 for 循环的作用是一样的。 + +我们先来看看 While 循环语句的样子。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-083137.png) + +程序输出的结果是: + +```txt +5050 +``` + +这个例子是计算 1 到 100 所有整数的和。 + + + +## 5、for 循环和 whlie 循环的区别 ## + +之前也提到过了,如果一种语法能表示一个功能,那没必要弄两种语法来表示。 + +竟然都是循环,for 循环和 while 循环肯定有他们的区别的。 + +那什么时候才使用 for 循环和 while 循环呢? + +* for 循环主要用在迭代可迭代对象的情况。 + +* while 循环主要用在需要满足一定条件为真,反复执行的情况。 +(死循环+break 退出等情况。) + +* 部分情况下,for 循环和 while 循环可以互换使用。 + +例如: + +```python +for i in range(0, 10): + print(i) + + +i = 0 +while i < 10: + print(i) + i = i + 1 +``` + +虽然打印的结果是一样的,但是细细品味你会发现,他们执行的顺序和知道的条件是不同的。 + + + +## 6、嵌套循环 ## + +循环语句和条件语句一样,都是可以嵌套的。 + +具体的语法如下: + +**for 循环嵌套语法** + +```python +for iterating_var in sequence: + for iterating_var in sequence: + statements(s) + statements(s) +``` + +**while 循环嵌套语法** + +```python +while expression: + while expression: + statement(s) + statement(s) +``` + +除此之外,你也可以在循环体内嵌入其他的循环体,如在 while 循环中可以嵌入 for 循环, 反之,你可以在 for 循环中嵌入 while 循环 + +比如: + +当我们需要判断 sum 大于 1000 的时候,不在相加时,可以用到 break ,退出整个循环。 + +```python +count = 1 +sum = 0 +while (count <= 100): + sum = sum + count + if ( sum > 1000): #当 sum 大于 1000 的时候退出循环 + break + count = count + 1 +print(sum) +``` + +输出的结果: + +```txt +1035 +``` + +有时候,我们只想统计 1 到 100 之间的奇数和,那么也就是说当 count 是偶数,也就是双数的时候,我们需要跳出当次的循环,不想加,这时候可以用到 break + +```python +count = 1 +sum = 0 +while (count <= 100): + if ( count % 2 == 0): # 双数时跳过输出 + count = count + 1 + continue + sum = sum + count + count = count + 1 +print(sum) +``` + +输出的语句: + +```txt +2500 +``` + +还有: + +```python +for num in range(10,20): # 迭代 10 到 20 之间的数字 + for i in range(2,num): # 根据因子迭代 + if num%i == 0: # 确定第一个因子 + j=num/i # 计算第二个因子 + print ('%d 是一个合数' % num) + break # 跳出当前循环 + else: # 循环的 else 部分 + print ('%d 是一个质数' % num) +``` + +输出的结果: + +```txt +10 是一个合数 +11 是一个质数 +12 是一个合数 +13 是一个质数 +14 是一个合数 +15 是一个合数 +16 是一个合数 +17 是一个质数 +18 是一个合数 +19 是一个质数 +``` + + +当然,这里还用到了 `for … else` 语句。 + +其实 for 循环中的语句和普通的没有区别,else 中的语句会在循环正常执行完(即 for 不是通过 break 跳出而中断的)的情况下执行。 + +当然有 `for … else` ,也会有 `while … else` 。他们的意思都是一样的。 + + diff --git a/python5/Example.md b/Article/PythonBasis/python5/Example.md similarity index 100% rename from python5/Example.md rename to Article/PythonBasis/python5/Example.md diff --git a/python5/If.md b/Article/PythonBasis/python5/If.md similarity index 50% rename from python5/If.md rename to Article/PythonBasis/python5/If.md index caa2246a..d113f597 100644 --- a/python5/If.md +++ b/Article/PythonBasis/python5/If.md @@ -1,14 +1,19 @@ # 一、条件语句 # + +## 1、什么是条件语句 ## + + Python 条件语句跟其他语言基本一致的,都是通过一条或多条语句的执行结果( True 或者 False )来决定执行的代码块。 -Python 程序语言指定任何非 0 和非空(null)值为 True,0 或者 null为 False。 +Python 程序语言指定任何非 0 和非空(null)值为 True,0 或者 null 为 False。 执行的流程图如下: ![if语句流程图](http://upload-images.jianshu.io/upload_images/2136918-4ee2486190450a1a?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) -## 1、if 语句的基本形式 ## + +## 2、if 语句的基本形式 ## Python 中,if 语句的基本形式如下: @@ -19,7 +24,7 @@ else: 执行语句…… ``` -前面也提到过,Python 语言有着严格的缩进要求,因此这里也需要注意缩进,也不要少写了冒号 `:` 。 +之前的章节也提到过,Python 语言有着严格的缩进要求,因此这里也需要注意缩进,也不要少写了冒号 `:` 。 if 语句的判断条件可以用>(大于)、<(小于)、==(等于)、>=(大于等于)、<=(小于等于)来表示其关系。 @@ -43,7 +48,7 @@ else : 不及格 ``` -上面也说道,非零数值、非空字符串、非空 list 等,判断为True,否则为False。因此也可以这样写: +上面也说到,非零数值、非空字符串、非空 list 等,判断为 True,否则为 False。因此也可以这样写: ```python num = 6 @@ -51,7 +56,27 @@ if num : print('Hello Python') ``` -## 2、if 语句多个判断条件的形式 ## +输出的结果如下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-072713.png) + +可见,把结果打印出来了。 + +那如果我们把 `num ` 改为空字符串呢? + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-072941.png) + +很明显,空字符串是为 False 的,不符合条件语句,因此不会执行到 `print('Hello Python')` 这段代码。 + +还有再啰嗦一点,提醒一下,在条件判断代码中的冒号 `:` 后、下一行内容是一定要缩进的。不缩进是会报错的。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-073432.png) + +冒号和缩进是一种语法。它会帮助 Python 区分代码之间的层次,理解条件执行的逻辑及先后顺序。 + + + +## 3、if 语句多个判断条件的形式 ## 有些时候,我们的判断语句不可能只有两个,有些时候需要多个,比如上面的例子中大于 60 的为及格,那我们还要判断大于 90 的为优秀,在 80 到 90 之间的良好呢? @@ -94,9 +119,21 @@ else : 良好 ``` -## 3、if 语句多个条件同时判断 ## -Python 不像 Java 有 switch 语句,所以多个条件判断,只能用 elif 来实现,但是有时候需要多个条件需同时判断时,可以使用 or (或),表示两个条件有一个成立时判断条件成功;使用 and (与)时,表示只有两个条件同时成立的情况下,判断条件才成功。 + +## 4、if 语句多个条件同时判断 ## + +有时候我们会遇到多个条件的时候该怎么操作呢? + +比如说要求 java 和 python 的考试成绩要大于 80 分的时候才算优秀,这时候该怎么做? + +这时候我们可以结合 `or` 和 `and` 来使用。 + +or (或)表示两个条件有一个成立时判断条件成功 + +and (与)表示只有两个条件同时成立的情况下,判断条件才成功。 + +例如: ```python # -*-coding:utf-8-*- @@ -122,3 +159,20 @@ if ( java >= 80 and java < 90 ) or ( python >= 80 and python < 90): ``` 注意:if 有多个条件时可使用括号来区分判断的先后顺序,括号中的判断优先执行,此外 and 和 or 的优先级低于 >(大于)、<(小于)等判断符号,即大于和小于在没有括号的情况下会比与或要优先判断。 + +## 5、if 嵌套 ## + +if 嵌套是指什么呢? + +就跟字面意思差不多,指 if 语句中可以嵌套 if 语句。 + +比如上面说到的例子,也可以用 if 嵌套来写。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-07-080557.png) + +当然这只是为了说明 if 条件语句是可以嵌套的。如果是这个需求,我个人还是不太建议这样使用 if 嵌套的,因为这样代码量多了,而且嵌套太多,也不方便阅读代码。 + + + + + diff --git a/Article/PythonBasis/python5/Preface.md b/Article/PythonBasis/python5/Preface.md new file mode 100644 index 00000000..34b1d5cc --- /dev/null +++ b/Article/PythonBasis/python5/Preface.md @@ -0,0 +1,16 @@ +# 前言 # + +通常都听到别人说,计算机很牛逼,很聪明,其实计算机一点都不聪明,光是你要跟他沟通,都会气 shi 你,聪明的是在写程序的你。 + +写程序就是跟计算机沟通,告诉它要做什么。 + +竟然是这样,那么肯定缺少不了一些沟通逻辑。比如你要告诉计算机在什么情况下做什么?或者在哪个时间点做什么? + +这都需要用到逻辑判断。这一章节,主要就是说这个。 + + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-09-09-%E6%9D%A1%E4%BB%B6%E8%AF%AD%E5%8F%A5%E5%92%8C%E5%BE%AA%E7%8E%AF%E8%AF%AD%E5%8F%A5.png) + + diff --git a/Article/PythonBasis/python6/1.md b/Article/PythonBasis/python6/1.md new file mode 100644 index 00000000..332f72e5 --- /dev/null +++ b/Article/PythonBasis/python6/1.md @@ -0,0 +1,101 @@ +# 一、Python 自定义函数的基本步骤 # + + + + +## 1、什么是函数 ## + +函数,其实我们一开始学 Python 的时候就接触过。 + +不过我们使用的大多数都是 Python 的内置函数。 + +比如基本每个章节都会出现的 `print()` 函数。 + +而现在,我们主要学习的是自定义函数。 + +**各位有没有想过为什么需要函数呢?** + +如果要想回答这个问题,我们需要先了解函数是什么? + +函数就是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 + +没错,函数其实就是把代码抽象出来的代码段。 + +那为什么要抽象出来呢? + +**方便我们使用,方便我们重复使用。** + +**函数的本质就是我们把一些数据喂给函数,让他内部消化,然后吐出你想要的东西,至于他怎么消化的,我们不需要知道,它内部解决。** + +怎么理解这句话呢? + +举个例子,好比每次用到的 print 函数,我们都知道这个函数的作用是可以把我们的数据输出到控制台,让我们看到。所以 `print('两点水')` , 我们想打印 `两点水` 出来,就把 `两点水` 这个数据喂给 `print` 函数,然后他就直接把结果打印到控制台上了。 + + + + + + + +## 2、怎么自定义函数 ## + +怎么自定义函数? + +要知道怎么定义函数,就要知道函数的组成部分是怎样的。 + +```python +def 函数名(参数1,参数2....参数n): + 函数体 + return 语句 +``` + +这就是 Python 函数的组成部分。 + +所以自定义函数,基本有以下规则步骤: + +* 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号() +* 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数 +* 函数的第一行语句可以选择性地使用文档字符串(用于存放函数说明) +* 函数内容以冒号起始,并且缩进 +* return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的 return 相当于返回 None。 + +语法示例: + +```python +def functionname( parameters ): + "函数_文档字符串" + function_suite + return [expression] +``` + +实例: + +1. def 定义一个函数,给定一个函数名 sum +2. 声明两个参数 num1 和 num2 +3. 函数的第一行语句进行函数说明:两数之和 +4. 最终 return 语句结束函数,并返回两数之和 + +```python +def sum(num1,num2): + "两数之和" + return num1+num2 + +# 调用函数 +print(sum(5,6)) +``` + +输出结果: + +```python +11 +``` + + + + + + + + + + diff --git a/python6/3.md b/Article/PythonBasis/python6/2.md similarity index 61% rename from python6/3.md rename to Article/PythonBasis/python6/2.md index fdc17b9e..bc3e8361 100644 --- a/python6/3.md +++ b/Article/PythonBasis/python6/2.md @@ -1,6 +1,8 @@ -# 三、函数返回值 # +# 二、函数返回值 # -通过上面的学习,可以知道通过 return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。 +通过上面的学习,可以知道通过 return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。 + +**不带参数值的 return 语句返回 None。** 具体示例: @@ -9,7 +11,7 @@ def sum(num1,num2): # 两数之和 - if not (isinstance (num1,(int ,float)) or isinstance (num2,(int ,float))): + if not (isinstance (num1,(int ,float)) and isinstance (num2,(int ,float))): raise TypeError('参数类型错误') return num1+num2 @@ -51,4 +53,16 @@ print (tuple1) (2.0, 1) ``` -认真观察就可以发现,尽管从第一个输出值来看,返回了多个值,实际上是先创建了一个元组然后返回的。回忆一下,元组是可以直接用逗号来创建的,观察例子中的 ruturn ,可以发现实际上我们使用的是逗号来生成一个元组。 +认真观察就可以发现,尽管从第一个输出值来看,返回了多个值,实际上是先创建了一个元组然后返回的。 + +回忆一下,元组是可以直接用逗号来创建的,观察例子中的 ruturn ,可以发现实际上我们使用的是逗号来生成一个元组。 + +Python 语言中的函数返回值可以是多个,而其他语言都不行,这是Python 相比其他语言的简便和灵活之处。 + +**Python 一次接受多个返回值的数据类型就是元组。** + +不知道此刻你还记不记得元组的相关知识,如果不记得,建议现在立刻写几个例子回忆一下,比如如何获取元组的第一个元素出来。 + + + + diff --git a/python6/4.md b/Article/PythonBasis/python6/3.md similarity index 56% rename from python6/4.md rename to Article/PythonBasis/python6/3.md index e807b771..2d3b8ccd 100644 --- a/python6/4.md +++ b/Article/PythonBasis/python6/3.md @@ -1,9 +1,28 @@ -# 四、函数的参数 # +# 三、函数的参数 # -## 1、默认值参数 ## + + + +## 1、函数的参数类型 ## + +设置与传递参数是函数的重点,而 Python 的函数对参数的支持非常的灵活。 + +主要的参数类型有:默认参数、关键字参数(位置参数)、不定长参数。 + +下面我们将一一了解这几种参数。 + + + + +## 2、默认参数 ## 有时候,我们自定义的函数中,如果调用的时候没有设置参数,需要给个默认值,这时候就需要用到默认值参数了。 +默认参数,只要在构造函数参数的时候,给参数赋值就可以了 + +例如: + + ```python # -*- coding: UTF-8 -*- @@ -27,9 +46,17 @@ print_user_info( '三点水' , 25 ) 昵称:三点水 年龄:25 性别:男 ``` -可以看到,当你设置了默认参数的时候,在调用函数的时候,不传该参数,就会使用默认值。但是这里需要注意的一点是:**只有在形参表末尾的那些参数可以有默认参数值**,也就是说你不能在声明函数形参的时候,先声明有默认值的形参而后声明没有默认值的形参。这是因为赋给形参的值是根据位置而赋值的。例如,def func(a, b=1) 是有效的,但是 def func(a=1, b) 是 无效 的。 +从输出结果可以看到,当你设置了默认参数的时候,在调用函数的时候,不传该参数,就会使用默认值。 + +但是这里需要注意的一点是:**只有在形参表末尾的那些参数可以有默认参数值**,也就是说你不能在声明函数形参的时候,先声明有默认值的形参而后声明没有默认值的形参。 -默认值参数就这样结束了吗?还没有的,细想一下,如果参数中是一个可修改的容器比如一个 lsit (列表)或者 dict (字典),那么我们使用什么来作为默认值呢?我们可以使用 None 作为默认值。就像下面这个例子一样: +这是因为赋给形参的值是根据位置而赋值的。例如,def func(a, b=1) 是有效的,但是 def func(a=1, b) 是 无效 的。 + +默认值参数就这样结束了吗? + +还没有的,细想一下,如果参数中是一个可修改的容器比如一个 lsit (列表)或者 dict (字典),那么我们使用什么来作为默认值呢? + +我们可以使用 None 作为默认值。就像下面这个例子一样: ```python # 如果 b 是一个 list ,可以使用 None 作为默认值 @@ -39,13 +66,21 @@ def print_info( a , b = None ): return; ``` -认真看下例子,会不会有这样的疑问呢?在参数中我们直接 `b=[]` 不就行了吗?也就是写成下面这个样子: +认真看下例子,会不会有这样的疑问呢?在参数中我们直接 `b=[]` 不就行了吗? + +也就是写成下面这个样子: ```python def print_info( a , b = [] ): return; ``` -对不对呢?运行一下也没发现错误啊,可以这样写吗?这里需要特别注意的一点:**默认参数的值是不可变的对象,比如None、True、False、数字或字符串**,如果你像上面的那样操作,当默认值在其他地方被修改后你将会遇到各种麻烦。这些修改会影响到下次调用这个函数时的默认值。 +对不对呢? + +运行一下也没发现错误啊,可以这样写吗? + +这里需要特别注意的一点:**默认参数的值是不可变的对象,比如None、True、False、数字或字符串**,如果你像上面的那样操作,当默认值在其他地方被修改后你将会遇到各种麻烦。 + +这些修改会影响到下次调用这个函数时的默认值。 示例如下: @@ -73,7 +108,9 @@ print_info(2) 认真观察,你会发现第二次输出的值根本不是你想要的,因此切忌不能这样操作。 -还有一点,有时候我就是不想要默认值啊,只是想单单判断默认参数有没有值传递进来,那该怎么办?我们可以这样做: +还有一点,有时候我就是不想要默认值啊,只是想单单判断默认参数有没有值传递进来,那该怎么办? + +我们可以这样做: ```python _no_value =object() @@ -83,15 +120,25 @@ def print_info( a , b = _no_value ): print('b 没有赋值') return; ``` -这里的 `object` 是python中所有类的基类。 你可以创建 `object` 类的实例,但是这些实例没什么实际用处,因为它并没有任何有用的方法, 也没有任何实例数据(因为它没有任何的实例字典,你甚至都不能设置任何属性值)。 你唯一能做的就是测试同一性。也正好利用这个特性,来判断是否有值输入。 -## 2、关键字参数 ## +这里的 `object` 是 python 中所有类的基类。 你可以创建 `object` 类的实例,但是这些实例没什么实际用处,因为它并没有任何有用的方法, 也没有任何实例数据(因为它没有任何的实例字典,你甚至都不能设置任何属性值)。 你唯一能做的就是测试同一性。也正好利用这个特性,来判断是否有值输入。 + + + + +## 3、关键字参数(位置参数) ## + +一般情况下,我们需要给函数传参的时候,是要按顺序来的,如果不对应顺序,就会传错值。 + +不过在 Python 中,可以通过参数名来给函数传递参数,而不用关心参数列表定义时的顺序,这被称之为关键字参数。 + +使用关键参数有两个优势 : -在 Python 中,可以通过参数名来给函数传递参数,而不用关心参数列表定义时的顺序,这被称之为关键字参数。使用关键参数有两个优势 : +* 由于我们不必担心参数的顺序,使用函数变得更加简单了。 -一、由于我们不必担心参数的顺序,使用函数变得更加简单了。 +* 假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值 -二、假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值 +具体看例子: ```python # -*- coding: UTF-8 -*- @@ -117,10 +164,19 @@ print_user_info( name = '两点水' ,sex = '女', age = 18 ) 昵称:两点水 年龄:18 性别:女 ``` -## 3、不定长参数 ## -有时我们在设计函数接口的时候,可会需要可变长的参数。也就是说,我们事先无法确定传入的参数个数。Python 提供了一种元组的方式来接受没有直接定义的参数。这种方式在参数前边加星号 `*` 。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。 + + +## 4、不定长参数 ## + +或许有些时候,我们在设计函数的时候,我们有时候无法确定传入的参数个数。 + +那么我们就可以使用不定长参数。 + +Python 提供了一种元组的方式来接受没有直接定义的参数。这种方式在参数前边加星号 `*` 。 + +如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。 例如: @@ -146,10 +202,12 @@ print_user_info( '两点水' ,18 , '女', '打篮球','打羽毛球','跑步') 昵称:两点水 年龄:18 性别:女 爱好:('打篮球', '打羽毛球', '跑步') ``` -通过输出的结果可以知道,`*hobby`是可变参数,且 hobby其实就是一个 tuple (元祖) +通过输出的结果可以知道,`*hobby`是可变参数,且 hobby 其实就是一个 tuple (元祖) + +可变长参数也支持关键字参数(位置参数),没有被定义的关键参数会被放到一个字典里。 -可变长参数也支持关键参数,没有被定义的关键参数会被放到一个字典里。这种方式即是在参数前边加 `**`,更改上面的示例如下: +这种方式即是在参数前边加 `**`,更改上面的示例如下: ```python @@ -177,7 +235,8 @@ print_user_info( name = '两点水' , age = 18 , sex = '女', hobby = ('打篮 通过对比上面的例子和这个例子,可以知道,`*hobby`是可变参数,且 hobby其实就是一个 tuple (元祖),`**hobby`是关键字参数,且 hobby 就是一个 dict (字典) -## 4、只接受关键字参数 ## + +## 5、只接受关键字参数 ## 关键字参数使用起来简单,不容易参数出错,那么有些时候,我们定义的函数希望某些参数强制使用关键字参数传递,这时候该怎么办呢? @@ -201,6 +260,7 @@ print_user_info( name = '两点水' ,age = 18 , sex = '女' ) print_user_info('两点水',age='22',sex='男') ``` -通过例子可以看,如果 `age` , `sex` 不适用关键字参数是会报错的。 +通过例子可以看,如果 `age` , `sex` 不使用关键字参数是会报错的。 + +很多情况下,使用强制关键字参数会比使用位置参数表意更加清晰,程序也更加具有可读性。使用强制关键字参数也会比使用 `**kw` 参数更好且强制关键字参数在一些更高级场合同样也很有用。 -很多情况下,使用强制关键字参数会比使用位置参数表意更加清晰,程序也更加具有可读性。使用强制关键字参数也会比使用 `**kw` 参数更好且强制关键字参数在一些更高级场合同样也很有用。 \ No newline at end of file diff --git a/python6/2.md b/Article/PythonBasis/python6/4.md similarity index 87% rename from python6/2.md rename to Article/PythonBasis/python6/4.md index 76ba52c2..e9b7b6e4 100644 --- a/python6/2.md +++ b/Article/PythonBasis/python6/4.md @@ -1,4 +1,4 @@ -# 二、函数传值问题 # +# 四、函数传值问题 # 先看一个例子: @@ -18,12 +18,17 @@ print( b ) 1 ``` -这里可能有些人会有疑问,为啥不是通过函数`chagne_number`更改了 b -的值吗?为啥没有变化,输出的结果还是 1 ,这个问题很多编程语言都会讲到,原理解释也是差不多的。 +先看看运行的结果? + +想一下为什么打印的结果是 1 ,而不是 1000 ? + +其实把问题归根结底就是,为什么通过函数 `chagne_number` 没有更改到 b 的值? + +这个问题很多编程语言都会讲到,原理解释也是差不多的。 这里主要是函数参数的传递中,传递的是类型对象,之前也介绍了 Python 中基本的数据类型等。而这些类型对象可以分为可更改类型和不可更改的类型 -在 Python 中,字符串,整形,浮点型,tuple 是不可更改的对象,而 list , dict 等是可以更改的对象。 +**在 Python 中,字符串,整形,浮点型,tuple 是不可更改的对象,而 list , dict 等是可以更改的对象。** 例如: @@ -78,7 +83,6 @@ def chagne_list( b ): b = [1,2,3,4,5] chagne_list( b ) print( '最后输出 b 的值:{}' .format( b ) ) - ``` 输出的结果: @@ -88,3 +92,5 @@ print( '最后输出 b 的值:{}' .format( b ) ) 函数中 b 赋值后的值:[1, 2, 3, 4, 5, 1000] 最后输出 b 的值:[1, 2, 3, 4, 5, 1000] ``` + + diff --git a/python6/5.md b/Article/PythonBasis/python6/5.md similarity index 84% rename from python6/5.md rename to Article/PythonBasis/python6/5.md index 34982e9f..4da7b8ab 100644 --- a/python6/5.md +++ b/Article/PythonBasis/python6/5.md @@ -1,6 +1,8 @@ # 五、匿名函数 # -有没有想过定义一个很短的回调函数,但又不想用 `def` 的形式去写一个那么长的函数,那么有没有快捷方式呢?答案是有的。 +有没有想过定义一个很短的回调函数,但又不想用 `def` 的形式去写一个那么长的函数,那么有没有快捷方式呢? + +答案是有的。 python 使用 lambda 来创建匿名函数,也就是不再使用 def 语句这样标准的形式定义一个函数。 @@ -57,4 +59,5 @@ print( sum2( 1 ) ) 10001 ``` -这主要在于 lambda 表达式中的 num2 是一个自由变量,在运行时绑定值,而不是定义时就绑定,这跟函数的默认值参数定义是不同的。所以建议还是遇到这种情况还是使用第一种解法。 \ No newline at end of file +**这主要在于 lambda 表达式中的 num2 是一个自由变量,在运行时绑定值,而不是定义时就绑定,这跟函数的默认值参数定义是不同的。所以建议还是遇到这种情况还是使用第一种解法。** + diff --git a/Article/PythonBasis/python6/Preface.md b/Article/PythonBasis/python6/Preface.md new file mode 100644 index 00000000..8b6f2210 --- /dev/null +++ b/Article/PythonBasis/python6/Preface.md @@ -0,0 +1,13 @@ +# 前言 # + +函数这个章节内容有点多,对于新手,也有些不好理解。建议各位多看几篇,多敲几次代码。 + +最后这是我的个人微信号,大家可以添加一下,交个朋友,一起讨论。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-070041.jpg) + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-%E5%87%BD%E6%95%B0.png) + + diff --git a/python7/1.md b/Article/PythonBasis/python7/1.md similarity index 91% rename from python7/1.md rename to Article/PythonBasis/python7/1.md index b9f9df2c..61bbff4b 100644 --- a/python7/1.md +++ b/Article/PythonBasis/python7/1.md @@ -4,7 +4,9 @@ 比如在 Java 中,我们通过 List 集合的下标来遍历 List 集合中的元素,在 Python 中,给定一个 list 或 tuple,我们可以通过 for 循环来遍历这个 list 或 tuple ,这种遍历就是迭代。 -可是,Python 的 `for` 循环抽象程度要高于 Java 的 `for` 循环的,为什么这么说呢?因为 Python 的 `for` 循环不仅可以用在 list 或tuple 上,还可以作用在其他可迭代对象上。也就是说,只要是可迭代的对象,无论有没有下标,都是可以迭代的。 +可是,Python 的 `for` 循环抽象程度要高于 Java 的 `for` 循环的,为什么这么说呢?因为 Python 的 `for` 循环不仅可以用在 list 或tuple 上,还可以作用在其他可迭代对象上。 + +也就是说,只要是可迭代的对象,无论有没有下标,都是可以迭代的。 比如: @@ -59,3 +61,5 @@ name age sex 2 b 3 c ``` + + diff --git a/python7/2.md b/Article/PythonBasis/python7/2.md similarity index 100% rename from python7/2.md rename to Article/PythonBasis/python7/2.md diff --git a/python7/3.md b/Article/PythonBasis/python7/3.md similarity index 84% rename from python7/3.md rename to Article/PythonBasis/python7/3.md index 126edbcd..177ba14d 100644 --- a/python7/3.md +++ b/Article/PythonBasis/python7/3.md @@ -1,4 +1,4 @@ -# 三、lsit 生成式(列表生成式) # +# 三、list 生成式(列表生成式) # ## 1、创建 list 的方式 ## @@ -18,9 +18,13 @@ print(list1) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] ``` -这个其实在之前也有提到过:比如有个例子,打印九九乘法表,用这个方法其实就几句代码就可以了,具体可以看之前的这个章节:[条件语句和循环语句综合实例](https://www.readwithu.com/python5/Example.html) +这个其实在之前也有提到过,打印九九乘法表,用这个方法其实就几句代码就可以了,具体可以看之前的这个章节:[条件语句和循环语句综合实例](../python5/Example.md) -但是,如果用到 list 生成式,可以一句代码就生成九九乘法表了。具体看代码: +但是,如果用到 list 生成式,可以一句代码就生成九九乘法表了。 + +你没听错,就是一句代码。 + +具体实现: ```python print('\n'.join([' '.join ('%dx%d=%2d' % (x,y,x*y) for x in range(1,y+1)) for y in range(1,10)])) @@ -44,7 +48,7 @@ print('\n'.join([' '.join ('%dx%d=%2d' % (x,y,x*y) for x in range(1,y+1)) for y ## 2、list 生成式的创建 ## -首先,lsit 生成式的语法为: +首先,list 生成式的语法为: ```python [expr for iter_var in iterable] @@ -61,8 +65,8 @@ print('\n'.join([' '.join ('%dx%d=%2d' % (x,y,x*y) for x in range(1,y+1)) for y ```python # -*- coding: UTF-8 -*- -lsit1=[x * x for x in range(1, 11)] -print(lsit1) +list1=[x * x for x in range(1, 11)] +print(list1) ``` 输出的结果: @@ -75,8 +79,8 @@ print(lsit1) ```python # -*- coding: UTF-8 -*- -lsit1= [x * x for x in range(1, 11) if x % 2 == 0] -print(lsit1) +list1= [x * x for x in range(1, 11) if x % 2 == 0] +print(list1) ``` 输出的结果: @@ -91,8 +95,8 @@ print(lsit1) ```python # -*- coding: UTF-8 -*- -lsit1= [(x+1,y+1) for x in range(3) for y in range(5)] -print(lsit1) +list1= [(x+1,y+1) for x in range(3) for y in range(5)] +print(list1) ``` 输出的结果: @@ -102,3 +106,5 @@ print(lsit1) ``` 其实知道了 list 生成式是怎样组合的,就不难理解这个东西了。因为 list 生成式只是把之前学习的知识点进行了组合,换成了一种更简洁的写法而已。 + + diff --git a/python7/4.md b/Article/PythonBasis/python7/4.md similarity index 70% rename from python7/4.md rename to Article/PythonBasis/python7/4.md index 684c0e96..fe95fe1e 100644 --- a/python7/4.md +++ b/Article/PythonBasis/python7/4.md @@ -2,15 +2,21 @@ ## 1、为什么需要生成器 ## -通过上面的学习,可以知道列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 1000 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 +通过上面的学习,可以知道列表生成式,我们可以直接创建一个列表。 -所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的 list,从而节省大量的空间。在 Python 中,这种一边循环一边计算的机制,称为生成器:generator。 +但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 1000 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 + +**所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?** + +这样就不必创建完整的 list,从而节省大量的空间。 + +**在 Python 中,这种一边循环一边计算的机制,称为生成器:generator。** 在 Python 中,使用了 yield 的函数被称为生成器(generator)。 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 -在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。 +在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值。并在下一次执行 next()方法时从当前位置继续运行。 那么如何创建一个生成器呢? @@ -31,7 +37,11 @@ print(gen) at 0x0000000002734A40> ``` -创建 List 和 generator 的区别仅在于最外层的 `[]` 和 `()` 。但是生成器并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生” ( yield ) 出来。 生成器表达式使用了“惰性计算” ( lazy evaluation,也有翻译为“延迟求值”,我以为这种按需调用 call by need 的方式翻译为惰性更好一些),只有在检索时才被赋值( evaluated ),所以在列表比较长的情况下使用内存上更有效。 +创建 List 和 generator 的区别仅在于最外层的 `[]` 和 `()` 。 + +但是生成器并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生” ( yield ) 出来。 + +生成器表达式使用了“惰性计算” ( lazy evaluation,也有翻译为“延迟求值”,我以为这种按需调用 call by need 的方式翻译为惰性更好一些),只有在检索时才被赋值( evaluated ),所以在列表比较长的情况下使用内存上更有效。 那么竟然知道了如何创建一个生成器,那么怎么查看里面的元素呢? @@ -55,7 +65,11 @@ for num in gen : 上面也提到,创建生成器最简单最简单的方法就是把一个列表生成式的 `[]` 改成 `()`。为啥突然来个以函数的形式来创建呢? -其实生成器也是一种迭代器,但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中,而是在运行时生成值。你通过遍历来使用它们,要么用一个“for”循环,要么将它们传递给任意可以进行迭代的函数和结构。而且实际运用中,大多数的生成器都是通过函数来实现的。那么我们该如何通过函数来创建呢? +其实生成器也是一种迭代器,但是你只能对其迭代一次。 + +这是因为它们并没有把所有的值存在内存中,而是在运行时生成值。你通过遍历来使用它们,要么用一个“for”循环,要么将它们传递给任意可以进行迭代的函数和结构。 + +而且实际运用中,大多数的生成器都是通过函数来实现的。那么我们该如何通过函数来创建呢? 先不急,来看下这个例子: @@ -119,9 +133,9 @@ for x in fibon(1000000): 运行的效果: -![计算斐波那契数列的生成器](http://upload-images.jianshu.io/upload_images/2136918-304e50af22b787ce?imageMogr2/auto-orient/strip) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-%E8%AE%A1%E7%AE%97%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97%E7%9A%84%E7%94%9F%E6%88%90%E5%99%A8.gif) -你看,运行一个这么打的参数,也不会说有卡死的状态,因为这种方式不会使用太大的资源。这里,最难理解的就是 generator 和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next() 的时候执行,遇到 yield语句返回,再次执行时从上次返回的 yield 语句处继续执行。 +你看,运行一个这么大的参数,也不会说有卡死的状态,因为这种方式不会使用太大的资源。这里,最难理解的就是 generator 和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next() 的时候执行,遇到 yield语句返回,再次执行时从上次返回的 yield 语句处继续执行。 比如这个例子: @@ -189,3 +203,5 @@ for t in triangles( 10 ): # 直接修改函数名即可运行 [1, 8, 28, 56, 70, 56, 28, 8, 1] [1, 9, 36, 84, 126, 126, 84, 36, 9, 1] ``` + + diff --git a/python7/5.md b/Article/PythonBasis/python7/5.md similarity index 100% rename from python7/5.md rename to Article/PythonBasis/python7/5.md diff --git a/Article/PythonBasis/python7/Preface.md b/Article/PythonBasis/python7/Preface.md new file mode 100644 index 00000000..1646e388 --- /dev/null +++ b/Article/PythonBasis/python7/Preface.md @@ -0,0 +1,11 @@ +# 前言 # + +这篇内容挺多的,而且比内容不好理解。或许新手看完后,还会一脸懵逼,不过这是正常的,如果你看完后,是迷糊的,那么建议你继续学习后面的内容,等学完,再回来看几次。 + +注:这也是我第二次修改内容没有改过的章节。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-07-%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%92%8C%E7%94%9F%E6%88%90%E5%99%A8.png) + + diff --git a/python9/1.md b/Article/PythonBasis/python8/1.md similarity index 54% rename from python9/1.md rename to Article/PythonBasis/python8/1.md index e40cb10d..13fd9e0d 100644 --- a/python9/1.md +++ b/Article/PythonBasis/python8/1.md @@ -1,11 +1,23 @@ # 一、面向对象的概念 # -Python 是一门面向对象的语言, 面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。 用 JAVA 的编程思想来说就是:万事万物皆对象。也就是说在面向对象中,把构成问题事务分解成各个对象。 -面向对象有三大特性,封装、继承和多态。 ## 1、面向对象的两个基本概念 ## +编程语言中,一般有两种编程思维,面向过程和面向对象。 + +面向过程,看重的是解决问题的过程。 + +这好比我们解决日常生活问题差不多,分析解决问题的步骤,然后一步一步的解决。 + +而面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。 + +Python 就是一门面向对象的语言, + +如果你学过 Java ,就知道 Java 的编程思想就是:万事万物皆对象。Python 也不例外,在解决实际问题的过程中,可以把构成问题事务分解成各个对象。 + +面向对象都有两个基本的概念,分别是类和对象。 + * **类** 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 @@ -15,8 +27,13 @@ Python 是一门面向对象的语言, 面向对象是一种抽象,抽象是 通过类定义的数据结构实例 + + + ## 2、面向对象的三大特性 ## +面向对象的编程语言,也有三大特性,继承,多态和封装性。 + * **继承** 即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。 @@ -30,3 +47,8 @@ Python 是一门面向对象的语言, 面向对象是一种抽象,抽象是 * **封装性** “封装”就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体(即类);封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。 + + +**如果你是初次接触面向对象的编程语言,看到这里还一脸懵逼,不要紧,这是正常的。下面我们会通过大量的例子逐步了解 Python 的面向对象的知识。** + + diff --git a/Article/PythonBasis/python8/2.md b/Article/PythonBasis/python8/2.md new file mode 100644 index 00000000..67917711 --- /dev/null +++ b/Article/PythonBasis/python8/2.md @@ -0,0 +1,83 @@ +# 二、类的定义和调用 # + + + +## 1、怎么理解类? ## + +类是什么? + +个人认为理解类,最简单的方式就是:类是一个变量和函数的集合。 + +可以看下下面的这张图。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2020-03-09-014706.jpg) + +这张图很好的诠释了类,就是把变量和函数包装在一起。 + +当然我们包装也不是毫无目的的包装,我们会把同性质的包装在一个类里,这样就方便我们重复使用。 + +所以学到现在,你会发现很多编程的设计,都是为了我们能偷懒,重复使用。 + + + + + + +## 2、怎么定义类 ## + +知道了类是什么样子的,我们接下来就要学习怎么去定义类了。 + +类定义语法格式如下: + +```python +class ClassName(): + + . + . + . + +``` + +可以看到,我们是用 `class` 语句来自定义一个类的,其实这就好比我们是用 `def` 语句来定义一个函数一样。 + +竟然说类是变量和方法的集合包,那么我们来创建一个类。 + +```python +class ClassA(): + var1 = 100 + var2 = 0.01 + var3 = '两点水' + + def fun1(): + print('我是 fun1') + + def fun2(): + print('我是 fun1') + + def fun3(): + print('我是 fun1') +``` + +你看,上面我们就定义了一个类,类名叫做 `ClassA` , 类里面的变量我们称之为属性,那么就是这个类里面有 3 个属性,分别是 `var1` , `var2` 和 `var3` 。除此之外,类里面还有 3 个类方法 `fun1()` , `fun2()` 和 `fun3()` 。 + + + + + +## 3、怎么调用类属性和类方法 ## + + +我们定义了类之后,那么我们怎么调用类里面的属性和方法呢? + +直接看下图: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2020-03-09-014728.jpg) + +这里就不文字解释了(注:做图也不容易啊,只有写过技术文章才知道,这系列文章,多耗时) + +好了,知道怎么调用之后,我们尝试一下: + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2020-03-09-014742.jpg) + + diff --git a/Article/PythonBasis/python8/3.md b/Article/PythonBasis/python8/3.md new file mode 100644 index 00000000..82147949 --- /dev/null +++ b/Article/PythonBasis/python8/3.md @@ -0,0 +1,57 @@ +# 三、类方法 # + + +## 1、类方法如何调用类属性 ## + +通过上面我们已经会定义类了,那么这里讲一下在同一个类里,类方法如何调用类属性的。 + +直接看个例子吧: + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-110451.png) + +注意看,在类方法上面多了个 `@classmethod` ,这是干嘛用的呢? + +这是用于声明下面的函数是类函数。其实从名字就很好理解了。 + +class 就是类,method 就是方法。 + +那是不是一定需要注明这个呢? + +答案是是的。 + +如果你没使用,是会报错的。 + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-110822.png) + +如果没有声明是类方法,方法参数中就没有 `cls` , 就没法通过 `cls` 获取到类属性。 + +因此类方法,想要调用类属性,需要以下步骤: + +* 在方法上面,用 `@classmethod` 声明该方法是类方法。只有声明了是类方法,才能使用类属性 +* 类方法想要使用类属性,在第一个参数中,需要写上 `cls` , cls 是 class 的缩写,其实意思就是把这个类作为参数,传给自己,这样就可以使用类属性了。 +* 类属性的使用方式就是 `cls.变量名` + + +记住喔,无论是 `@classmethod` 还是 `cls` ,都是不能省去的。 + +省了都会报错。 + + + + + +## 2、类方法传参 ## + +上面我们学习了类方法如何调用类属性,那么类方法如何传参呢? + +其实很简单,跟普通的函数一样,直接增加参数就好了。 + +这个就直接上例子了: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-113458.png) + + + + diff --git a/Article/PythonBasis/python8/4.md b/Article/PythonBasis/python8/4.md new file mode 100644 index 00000000..2dea4f4b --- /dev/null +++ b/Article/PythonBasis/python8/4.md @@ -0,0 +1,32 @@ +# 四、修改和增加类属性 # + + +## 1、从内部增加和修改类属性 ## + +来,我们先来温习一下类的结构。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-034102.png) + +看着这个结构,提一个问题,如何修改类属性,也就是类里面的变量? + +从类结构来看,我们可以猜测,从类方法来修改,也就是从类内部来修改和增加类属性。 + +看下具体的实例: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-120146.png) + +这里还是强调一下,例子还是要自己多写,不要只看,自己运行, 看效果。多想。 + + + + +## 2、从外部增加和修改类属性 ## + +我们刚刚看了通过类方法来修改类的属性,这时我们看下从外部如何修改和增加类属性。 + +例子如下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-121135.png) + + + diff --git a/Article/PythonBasis/python8/5.md b/Article/PythonBasis/python8/5.md new file mode 100644 index 00000000..1f92bcf0 --- /dev/null +++ b/Article/PythonBasis/python8/5.md @@ -0,0 +1,171 @@ +# 五、类和对象 # + + + + +## 1、类和对象之间的关系 ## + +这部分内容主要讲类和对象,我们先来说说类和对象之间的关系。 + +**类是对象的模板** + +我们得先有了类,才能制作出对象。 + +类就相对于工厂里面的模具,对象就是根据模具制造出来的产品。 + +**从模具变成产品的过程,我们就称为类的实例化。** + +**类实例化之后,就变成对象了。也就是相当于例子中的产品。** + + + + + +## 2、类的实例化 ## + +这里强调一下,类的实例化和直接使用类的格式是不一样的。 + +之前我们就学过,直接使用类格式是这样的: + +```python +class ClassA(): + var1 = '两点水' + + @classmethod + def fun1(cls): + print('var1 值为:' + cls.var1) + + +ClassA.fun1() +``` + +而类的实例化是怎样的呢? + +是这样的,可以仔细对比一下,类的实例化和直接使用类的格式有什么不同? + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-025401.png) + + +主要的不同点有: + +* 类方法里面没有了 `@classmethod` 声明了,不用声明他是类方法 +* 类方法里面的参数 `cls` 改为 `self` +* 类的使用,变成了先通过 `实例名 = 类()` 的方式实例化对象,为类创建一个实例,然后再使用 `实例名.函数()` 的方式调用对应的方法 ,使用 `实例名.变量名` 的方法调用类的属性 + + +这里说明一下,类方法的参数为什么 `cls` 改为 `self` ? + +其实这并不是说一定要写这个,你改为什么字母,什么名字都可以。 + +不妨试一下: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-032030.png) + +你看,把 `self` 改为 `aaaaaaaa` 还是可以一样运行的。 + +只不过使用 `cls` 和 `self` 是我们的编程习惯,这也是我们的编程规范。 + +因为 cls 是 class 的缩写,代表这类 , 而 self 代表这对象的意思。 + +所以啊,这里我们实例化对象的时候,就使用 self 。 + +**而且 self 是所有类方法位于首位、默认的特殊参数。** + +除此之外,在这里,还要强调一个概念,当你把类实例化之后,里面的属性和方法,就不叫类属性和类方法了,改为叫实例属性和实例方法,也可以叫对象属性和对象方法。 + +为什么要这样强调呢? + +**因为一个类是可以创造出多个实例对象出来的。** + +你看下面的例子: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-034453.png) + +我不仅能用这个类创建 a 对象,还能创建 b 对象 + + + + + +## 3、实例属性和类属性 ## + +一个类可以实例化多个对象出来。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-040408.png) + +根据这个图,我们探究一下实例对象的属性和类属性之间有什么关系呢? + +**先提出第一个问题,如果类属性改变了,实例属性会不会跟着改变呢?** + +还是跟以前一样,提出了问题,我们直接用程序来验证就好。 + +看程序: + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-061015.png) + + +从程序运行的结果来看,**类属性改变了,实例属性会跟着改变。** + +这很好理解,因为我们的实例对象就是根据类来复制出来的,类属性改变了,实例对象的属性也会跟着改变。 + +**那么相反,如果实例属性改变了,类属性会改变吗?** + +答案当然是不能啦。因为每个实例都是单独的个体,不能影响到类的。 + +具体我们做下实验: + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-062437.png) + +可以看到,**不管实例对象怎么修改属性值,对类的属性还是没有影响的。** + + + + +## 4、实例方法和类方法 ## + +那这里跟上面一样,还是提出同样的问题。 + +**如果类方法改变了,实例方法会不会跟着改变呢?** + +看下下面的例子: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-063242.png) + +这里建议我的例子,各位都要仔细看一下,自己重新敲一遍。相信为什么要这么做,这么证明。 + +还是那句话多想,多敲。 + +回归正题,从运行的结果来看,类方法改变了,实例方法也是会跟着改变的。 + +在这个例子中,我们需要改变类方法,就用到了**类的重写**。 + +我们使用了 `类.原始函数 = 新函数` 就完了类的重写了。 + +要注意的是,这里的赋值是在替换方法,并不是调用函数。所以是不能加上括号的,也就是 `类.原始函数() = 新函数()` 这个写法是不对的。 + + +**那么如果实例方法改变了,类方法会改变吗?** + +如果这个问题我们需要验证的话,是不是要重写实例的方法,然后观察结果,看看类方法有没有改变,这样就能得出结果了。 + + +可是我们是不能重写实例方法。 + +你看,会直接报错。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-064303.png) + + + + + + + + + + + + + diff --git a/Article/PythonBasis/python8/6.md b/Article/PythonBasis/python8/6.md new file mode 100644 index 00000000..71152336 --- /dev/null +++ b/Article/PythonBasis/python8/6.md @@ -0,0 +1,146 @@ +# 六、初始化函数 # + + + +## 1、什么是初始化函数 ## + +初始化函数的意思是,当你创建一个实例的时候,这个函数就会被调用。 + +比如: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-071102.png) + +当代码在执行 `a = ClassA()` 的语句时,就自动调用了 `__init__(self)` 函数。 + +**而这个 `__init__(self)` 函数就是初始化函数,也叫构造函数。** + +初始化函数的写法是固定的格式:中间是 `init`,意思是初始化,然后前后都要有【两个下划线】,然后 `__init__()` 的括号中,第一个参数一定要写上 `self`,不然会报错。 + +构造函数(初始化函数)格式如下: + +```python +def __init__(self,[...): +``` + + +初始化函数一样可以传递参数的,例如: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-073421.png) + + + + +## 2、析构函数 ## + +竟然一个在创建的时候,会调用构造函数,那么理所当然,这个当一个类销毁的时候,就会调用析构函数。 + +析构函数语法如下: + +```python +def __del__(self,[...): +``` + +看下具体的示例: + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-084417.png) + + + +## 3、Python 定义类的历史遗留问题 ## + +Python 在版本的迭代中,有一个关于类的历史遗留问题,就是新式类和旧式类的问题,具体先看以下的代码: + +```python +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# 旧式类 +class OldClass: + pass + +# 新式类 +class NewClass(object): + pass + +``` + +可以看到,这里使用了两者中不同的方式定义类,可以看到最大的不同就是,新式类继承了`object` 类,在 Python2 中,我们定义类的时候最好定义新式类,当然在 Python3 中不存在这个问题了,因为 Python3 中所有类都是新式类。 + +那么新式类和旧式类有什么区别呢? + +运行下下面的那段代码: + +```python +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# 旧式类 +class OldClass: + def __init__(self, account, name): + self.account = account + self.name = name + + +# 新式类 +class NewClass(object): + def __init__(self, account, name): + self.account = account + self.name = name + + +if __name__ == '__main__': + old_class = OldClass(111111, 'OldClass') + print(old_class) + print(type(old_class)) + print(dir(old_class)) + print('\n') + new_class = NewClass(222222, 'NewClass') + print(new_class) + print(type(new_class)) + print(dir(new_class)) + +``` + +这是 python 2.7 运行的结果: + +``` +/Users/twowater/dev/python/test/venv/bin/python /Users/twowater/dev/python/test/com/twowater/test.py +<__main__.OldClass instance at 0x109a50560> + +['__doc__', '__init__', '__module__', 'account', 'name'] + + +<__main__.NewClass object at 0x109a4b150> + +['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'account', 'name'] + +Process finished with exit code 0 + +``` + +这是 Python 3.6 运行的结果: + +``` +/usr/local/bin/python3.6 /Users/twowater/dev/python/test/com/twowater/test.py +<__main__.OldClass object at 0x1038ba630> + +['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'account', 'name'] + + +<__main__.NewClass object at 0x103e3c9e8> + +['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'account', 'name'] + +Process finished with exit code 0 + +``` + + +仔细观察输出的结果,对比一下,就能观察出来,注意喔,Pyhton3 中输出的结果是一模一样的,因为Python3 中没有新式类旧式类的问题。 + + + + + + diff --git a/python9/5.md b/Article/PythonBasis/python8/7.md similarity index 82% rename from python9/5.md rename to Article/PythonBasis/python8/7.md index d85ab90d..0e95adad 100644 --- a/python9/5.md +++ b/Article/PythonBasis/python8/7.md @@ -1,7 +1,16 @@ -# 五、类的继承 # +# 七、类的继承 # ## 1、定义类的继承 ## +说到继承,你一定会联想到继承你老爸的家产之类的。 + +类的继承也是一样。 + +比如有一个旧类,是可以算平均数的。然后这时候有一个新类,也要用到算平均数,那么这时候我们就可以使用继承的方式。新类继承旧类,这样子新类也就有这个功能了。 + +通常情况下,我们叫旧类为父类,新类为子类。 + + 首先我们来看下类的继承的基本语法: ```python @@ -13,7 +22,7 @@ class ClassName(BaseClassName): ``` -在定义类的时候,可以在括号里写继承的类,一开始也提到过,如果不用继承类的时候,也要写继承 object 类,因为在 Python 中 object 类是一切类的父类。 +在定义类的时候,可以在括号里写继承的类,如果不用继承类的时候,也要写继承 object 类,因为在 Python 中 object 类是一切类的父类。 当然上面的是单继承,Python 也是支持多继承的,具体的语法如下: @@ -112,12 +121,12 @@ if __name__ == '__main__': 最后打印的结果: -![Python 类的继承](http://upload-images.jianshu.io/upload_images/2136918-aa2701fc5913a8a6?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-Python%20%E7%B1%BB%E7%9A%84%E7%BB%A7%E6%89%BF.png) 这里就是重写了父类的构造函数。 -## 3、子类的类型判断 ## +## 4、子类的类型判断 ## 对于 class 的继承关系来说,有些时候我们需要判断 class 的类型,该怎么办呢? @@ -168,3 +177,5 @@ False ``` 可以看到 `isinstance()` 不仅可以告诉我们,一个对象是否是某种类型,也可以用于基本类型的判断。 + + diff --git a/python9/6.md b/Article/PythonBasis/python8/8.md similarity index 92% rename from python9/6.md rename to Article/PythonBasis/python8/8.md index da1b03d4..7a2c9cbb 100644 --- a/python9/6.md +++ b/Article/PythonBasis/python8/8.md @@ -1,4 +1,4 @@ -# 六、类的多态 # +# 八、类的多态 # 多态的概念其实不难理解,它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。 @@ -11,7 +11,9 @@ 'ab' ``` -可以看到,我们对两个整数进行 + 操作,会返回它们的和,对两个字符进行相同的 + 操作,会返回拼接后的字符串。也就是说,不同类型的对象对同一消息会作出不同的响应。 +可以看到,我们对两个整数进行 + 操作,会返回它们的和,对两个字符进行相同的 + 操作,会返回拼接后的字符串。 + +也就是说,不同类型的对象对同一消息会作出不同的响应。 看下面的实例,来了解多态: @@ -64,4 +66,5 @@ Hello ! 尊敬的用户:水水水 -最后,本章的所有代码都可以在 [https://github.com/TwoWater/Python](https://github.com/TwoWater/Python) 上面找到,文章的内容和源文件都放在上面。同步更新到 Gitbooks。 \ No newline at end of file +最后,本章的所有代码都可以在 [https://github.com/TwoWater/Python](https://github.com/TwoWater/Python) 上面找到,文章的内容和源文件都放在上面。同步更新到 Gitbooks。 + diff --git a/python9/4.md b/Article/PythonBasis/python8/9.md similarity index 62% rename from python9/4.md rename to Article/PythonBasis/python8/9.md index 6514b268..68d56fb6 100644 --- a/python9/4.md +++ b/Article/PythonBasis/python8/9.md @@ -1,6 +1,62 @@ -# 四、类的方法 # +# 九、类的访问控制 # -## 1、类专有的方法 ## + +## 1、类属性的访问控制 ## + +在 Java 中,有 public (公共)属性 和 private (私有)属性,这可以对属性进行访问控制。 + +那么在 Python 中有没有属性的访问控制呢? + +一般情况下,我们会使用 `__private_attrs` 两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 `self.__private_attrs`。 + +为什么只能说一般情况下呢? + +因为实际上, Python 中是没有提供私有属性等功能的。 + +但是 Python 对属性的访问控制是靠程序员自觉的。为什么这么说呢? + +看看下面的示例: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-Python%20%E5%B1%9E%E6%80%A7%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6.png) + +仔细看图片,为什么说双下划线不是真正的私有属性呢?我们看下下面的例子,用下面的例子来验证: + +```python + +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +class UserInfo(object): + def __init__(self, name, age, account): + self.name = name + self._age = age + self.__account = account + + def get_account(self): + return self.__account + + +if __name__ == '__main__': + userInfo = UserInfo('两点水', 23, 347073565); + # 打印所有属性 + print(dir(userInfo)) + # 打印构造函数中的属性 + print(userInfo.__dict__) + print(userInfo.get_account()) + # 用于验证双下划线是否是真正的私有属性 + print(userInfo._UserInfo__account) + + +``` + +输出的结果如下图: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-09-Python%E5%8F%8C%E4%B8%8B%E5%88%92%E7%BA%BF%E5%B1%9E%E6%80%A7.png) + + + + +## 2、类专有的方法 ## 一个类创建的时候,就会包含一些方法,主要有以下方法: @@ -32,7 +88,9 @@ * `setattr(obj, attr, value)`:设定该属性/方法的值,类似于 obj.attr=value; * `dir(obj)`:可以获取相应对象的所有属性和方法名的列表: -## 2、方法的访问控制 ## + + +## 3、方法的访问控制 ## 其实我们也可以把方法看成是类的属性的,那么方法的访问控制也是跟属性是一样的,也是没有实质上的私有方法。一切都是靠程序员自觉遵守 Python 的编程规范。 @@ -54,53 +112,7 @@ class User(object): ``` -## 3、方法的装饰器 ## - -* **@classmethod** -调用的时候直接使用类名类调用,而不是某个对象 -* **@property** -可以像访问属性一样调用方法 - -具体的使用看下实例: - -```python -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -class UserInfo(object): - lv = 5 - - def __init__(self, name, age, account): - self.name = name - self._age = age - self.__account = account - - def get_account(self): - return self.__account - - @classmethod - def get_name(cls): - return cls.lv - - @property - def get_age(self): - return self._age - - -if __name__ == '__main__': - userInfo = UserInfo('两点水', 23, 347073565); - # 打印所有属性 - print(dir(userInfo)) - # 打印构造函数中的属性 - print(userInfo.__dict__) - # 直接使用类名类调用,而不是某个对象 - print(UserInfo.lv) - # 像访问属性一样调用方法(注意看get_age是没有括号的) - print(userInfo.get_age) -``` -运行的结果: -![Python 方法的装饰器](http://upload-images.jianshu.io/upload_images/2136918-63dc478a8b2f965f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python8/Preface.md b/Article/PythonBasis/python8/Preface.md similarity index 72% rename from python8/Preface.md rename to Article/PythonBasis/python8/Preface.md index abd89936..a0abeb00 100644 --- a/python8/Preface.md +++ b/Article/PythonBasis/python8/Preface.md @@ -1,7 +1,30 @@ # 前言 # + 之前的文章都是使用[Sublime Text](http://www.sublimetext.com/)来编写 Python 的,主要是为了更好的熟悉和了解 Python ,可是开发效率不高,也不方便,从这章开始,改为使用 Pycharm 了,在之前的篇节[集成开发环境(IDE): PyCharm](https://www.readwithu.com/python1/IDE.html)中介绍了 PyCharm ,如果如要激活软件可以通过授权服务器来激活,具体看这个网址。[JetBrains激活(http://www.imsxm.com/jetbrains-license-server.html)](http://www.imsxm.com/jetbrains-license-server.html)当然你也可以尝试破解, [Pycharm2017.1.1破解方式](http://blog.csdn.net/zyfortirude/article/details/70800681),不过对于软件的升级不方便。 + +这篇内容非常的重要,也是我用了很多时间写的。基本上把以前写的东西都重新改了一遍。里面的代码都是我一个一个的敲的,图片也是我一个一个制作的。 + + + + # 目录 # -![草根学Python(八) 模块与包](http://upload-images.jianshu.io/upload_images/2136918-4434f73dc82c0101?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![面向对象](media/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1.png) + + + + + + + + + + + + + + + + diff --git a/Article/PythonBasis/python9/1.md b/Article/PythonBasis/python9/1.md new file mode 100644 index 00000000..70c912a6 --- /dev/null +++ b/Article/PythonBasis/python9/1.md @@ -0,0 +1,50 @@ +# 一、Python 模块简介 # + +在开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。 + +后面我们学习了函数,知道函数是实现一项或多项功能的一段程序,这样就更方便我们重复使用代码。 + +紧接着,我们有学了类,类可以封装方法和变量(属性)。这样就更方便我们维护代码了。 + +我们之前学过,类的结构是这样的: + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-08-034102.png) + +而我们要学的模块是这样的: + + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-10-175017.png) + +在模块中,我们不但可以直接存放变量,还能存放函数,还能存放类。 + +不知道你们还有没有印象,我们封装函数用的是 `def` , 封装类用的是 `class` 。 + +而我们封装模块,是不需要任何语句的。 + +**在 Python 中,一个 .py 文件就称之为一个模块(Module)。** + +可以看下我之前写的例子,在 pychrome 上 ,这样一个 test.py 文件就是一个模块。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-070013.png) + +其实模块就是函数功能的扩展。为什么这么说呢? + +那是因为模块其实就是实现一项或多项功能的程序块。 + +通过上面的定义,不难发现,函数和模块都是用来实现功能的,只是模块的范围比函数广,在模块中,可以有多个函数。 + +然有了函数,那为啥那需要模块? + +最大的好处是大大提高了代码的可维护性。 + +其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括 Python 内置的模块和来自第三方的模块。 + +使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。 + +Python 本身就内置了很多非常有用的模块,只要安装完毕,这些模块就可以立刻使用。我们可以尝试找下这些模块,比如我的 Python 安装目录是默认的安装目录,在 C:\Users\Administrator\AppData\Local\Programs\Python\Python36 ,然后找到 Lib 目录,就可以发现里面全部都是模块,没错,这些 `.py` 文件就是模块了。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-python36bin%E7%9B%AE%E5%BD%95.png) + +其实模块可以分为标准库模块和自定义模块,而刚刚我们看到的 Lib 目录下的都是标准库模块。 + + diff --git a/python8/2.md b/Article/PythonBasis/python9/2.md similarity index 85% rename from python8/2.md rename to Article/PythonBasis/python9/2.md index 1dafbc97..abf1c87b 100644 --- a/python8/2.md +++ b/Article/PythonBasis/python9/2.md @@ -73,16 +73,24 @@ from modname import name1[, name2[, ... nameN]] `import` 导入 sys 模块,然后使用 version 属性 -![from···import和 import的区别1](http://upload-images.jianshu.io/upload_images/2136918-499dd531d4ce3d72?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-from%C2%B7%C2%B7%C2%B7import%E5%92%8C%20import%E7%9A%84%E5%8C%BA%E5%88%AB1.png) `from···import` 直接导入 version 属性 -![from···import和 import的区别2](http://upload-images.jianshu.io/upload_images/2136918-eea99fc170ed5a07?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![from···import和 import的区别2](media/from%C2%B7%C2%B7%C2%B7import%E5%92%8C%20import%E7%9A%84%E5%8C%BA%E5%88%AB2-2.png) + + ## 3、from ··· import * ## -通过上面的学习,我们知道了 `from sys import version` 可以直接导入 version 属性。但是如果我们想使用其他的属性呢?比如使用 sys 模块中的 `executable` ,难道又要写多一句 `from sys import executable` ,两个还好,如果三个,四个呢?难道要一直这样写下去? +通过上面的学习,我们知道了 `from sys import version` 可以直接导入 version 属性。 + +但是如果我们想使用其他的属性呢? + +比如使用 sys 模块中的 `executable` ,难道又要写多一句 `from sys import executable` ,两个还好,如果三个,四个呢? + +难道要一直这样写下去? 这时候就需要 `from ··· import *` 语句了,这个语句可以把某个模块中的所有方法属性都导入。比如: @@ -105,3 +113,5 @@ C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe ``` 注意:这提供了一个简单的方法来导入一个模块中的所有方法属性。然而这种声明不该被过多地使用。 + + diff --git a/python8/3.md b/Article/PythonBasis/python9/3.md similarity index 85% rename from python8/3.md rename to Article/PythonBasis/python9/3.md index 16505fdb..48947d50 100644 --- a/python8/3.md +++ b/Article/PythonBasis/python9/3.md @@ -14,10 +14,12 @@ 首先创建了模块 lname ,然后判断一下是否是主模块,如果是主模块就输出 `main` 不是,就输出 `not main` ,首先直接运行该模块,由于该模块是直接使用,而没有被人调用,所以是主模块,因此输出了 `main` ,具体看下图: -![name属性区分模块1](http://upload-images.jianshu.io/upload_images/2136918-d892d81a71cda9d6?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-name%E5%B1%9E%E6%80%A7%E5%8C%BA%E5%88%86%E6%A8%A1%E5%9D%971.png) 然后又创建一个 user_lname 模块,里面只是简单的导入了 lname 模块,然后执行,输出的结果是 `not main` ,因为 lname 模块被该模块调用了,所以不是主模块,输出结果如图: -![name属性区分模块2](http://upload-images.jianshu.io/upload_images/2136918-9137cb874588dded?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-name%E5%B1%9E%E6%80%A7%E5%8C%BA%E5%88%86%E6%A8%A1%E5%9D%972.png) + + diff --git a/python8/4.md b/Article/PythonBasis/python9/4.md similarity index 51% rename from python8/4.md rename to Article/PythonBasis/python9/4.md index d90bc947..a98e5376 100644 --- a/python8/4.md +++ b/Article/PythonBasis/python9/4.md @@ -1,11 +1,21 @@ # 四、包 # -包,其实在上面的一些例子中,都创建了不同的包名了,具体可以仔细观察。在一开始模块的简介中提到,使用模块可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。但是这里也有个问题,如果不同的人编写的模块名相同怎么办?为了避免模块名冲突,Python 又引入了按目录来组织模块的方法,称为包(Package)。 +包,其实在上面的一些例子中,都创建了不同的包名了,具体可以仔细观察。 + +在一开始模块的简介中提到,使用模块可以避免函数名和变量名冲突。 + +相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。 + +但是这里也有个问题,如果不同的人编写的模块名相同怎么办? + +为了避免模块名冲突,Python 又引入了按目录来组织模块的方法,称为包(Package)。 比如最开始的例子,就引入了包,这样子做就算有相同的模块名,也不会造成重复,因为包名不同,其实也就是路径不同。如下图,引入了包名后, lname.py 其实变成了 com.Learn.module.nameattributes.lname -![Python 包](http://upload-images.jianshu.io/upload_images/2136918-7f92a0da0bc609d5?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-Python%20%E5%8C%85.png) 仔细观察的人,基本会发现,每一个包目录下面都会有一个 `__init__.py` 的文件,为什么呢? 因为这个文件是必须的,否则,Python 就把这个目录当成普通目录,而不是一个包 。 `__init__.py` 可以是空文件,也可以有Python代码,因为 `__init__.py` 本身就是一个模块,而它对应的模块名就是它的包名。 + + diff --git a/python8/5.md b/Article/PythonBasis/python9/5.md similarity index 53% rename from python8/5.md rename to Article/PythonBasis/python9/5.md index 47179b02..93cc20e9 100644 --- a/python8/5.md +++ b/Article/PythonBasis/python9/5.md @@ -1,10 +1,14 @@ # 五、作用域 # -学习过 Java 的同学都知道,Java 的类里面可以给方法和属性定义公共的( public )或者是私有的 ( private ),这样做主要是为了我们希望有些函数和属性能给别人使用或者只能内部使用。 通过学习 Python 中的模块,其实和 Java 中的类相似,那么我们怎么实现在一个模块中,有的函数和变量给别人使用,有的函数和变量仅仅在模块内部使用呢? +学习过 Java 的同学都知道,Java 的类里面可以给方法和属性定义公共的( public )或者是私有的 ( private ),这样做主要是为了我们希望有些函数和属性能给别人使用或者只能内部使用。 -在 Python 中,是通过 `_` 前缀来实现的。正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,ni12,PI等;类似`__xxx__`这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的 `__name__` 就是特殊变量,还有 `__author__` 也是特殊变量,用来标明作者。注意,我们自己的变量一般不要用这种变量名;类似 `_xxx` 和 `__xxx` 这样的函数或变量就是非公开的(private),不应该被直接引用,比如 `_abc` ,`__abc` 等; + 通过学习 Python 中的模块,其实和 Java 中的类相似,那么我们怎么实现在一个模块中,有的函数和变量给别人使用,有的函数和变量仅仅在模块内部使用呢? -注意,这里是说不应该,而不是不能。因为 Python 种并没有一种方法可以完全限制访问 private 函数或变量,但是,从编程习惯上不应该引用 private 函数或变量。 +在 Python 中,是通过 `_` 前缀来实现的。正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,ni12,PI等;类似`__xxx__`这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的 `__name__` 就是特殊变量,还有 `__author__` 也是特殊变量,用来标明作者。 + +注意,我们自己的变量一般不要用这种变量名;类似 `_xxx` 和 `__xxx` 这样的函数或变量就是非公开的(private),不应该被直接引用,比如 `_abc` ,`__abc` 等; + +**这里是说不应该,而不是不能。因为 Python 种并没有一种方法可以完全限制访问 private 函数或变量,但是,从编程习惯上不应该引用 private 函数或变量。** 比如: @@ -42,10 +46,12 @@ vip_lv_name(2) DiamondVIP2 ``` -在这个模块中,我们公开 `vip_lv_name` 方法函数,而其他内部的逻辑分别在 `vip_lv_name` 和 `vip_lv_name` private 函数中实现,因为是内部实现逻辑,调用者根本不需要关心这个函数方法,它只需关心调用 `vip_lv_name` 的方法函数,所以用 private 是非常有用的代码封装和抽象的方法 +在这个模块中,我们公开 `vip_lv_name` 方法函数,而其他内部的逻辑分别在 `_diamond_vip` 和 `_gold_vip` private 函数中实现,因为是内部实现逻辑,调用者根本不需要关心这个函数方法,它只需关心调用 `vip_lv_name` 的方法函数,所以用 private 是非常有用的代码封装和抽象的方法 一般情况下,外部不需要引用的函数全部定义成 private,只有外部需要引用的函数才定义为 public。 ------------------------ -最后扯淡,欢迎加我微信:`androidwed`,进入微信Python讨论群,一起学习讨论。现在微信群只有50几个人. +最后扯淡,欢迎加我微信:`thinktoday2019`, 进入微信 Python 讨论群。 + + diff --git a/Article/PythonBasis/python9/Preface.md b/Article/PythonBasis/python9/Preface.md new file mode 100644 index 00000000..ba6b2563 --- /dev/null +++ b/Article/PythonBasis/python9/Preface.md @@ -0,0 +1,9 @@ +# 前言 # + +学习到这里,可以说 Python 基础学习基本接近尾声了。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-14-%E6%A8%A1%E5%9D%97%E4%B8%8E%E5%8C%85.png) + + diff --git "a/Article/advanced/Mac\344\270\255\344\275\277\347\224\250virtualenv\345\222\214virtualenvwrapper.md" "b/Article/advanced/Mac\344\270\255\344\275\277\347\224\250virtualenv\345\222\214virtualenvwrapper.md" new file mode 100644 index 00000000..d67f0f71 --- /dev/null +++ "b/Article/advanced/Mac\344\270\255\344\275\277\347\224\250virtualenv\345\222\214virtualenvwrapper.md" @@ -0,0 +1,140 @@ + +## Virtualenv + +### 介绍 + +在使用 `Python` 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题;亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难。 + +因此,我们需要对于不同的工程使用不同的虚拟环境来保持开发环境以及宿主环境的清洁。而 `virtualenv`就是一个可以帮助我们管理不同 `Python` 环境的绝好工具。`virtualenv` 可以在系统中建立多个不同并且相互不干扰的虚拟环境。 + +### 安装 + +``` + pip3 install virtualenv +``` + +这样就成功了 + +### 使用 + +#### 创建 + +假如我们想要用`scrapy`去爬取某个网站的信息,我们不想再宿主环境总安装scrapy以及requests这些包,那我们就可以使用virtualenv了。 + +假设我们把这个虚拟环境放在`~/workspaces/project_env/spider/`目录下 + +``` + virtualenv ~/workspaces/project_env/spider/ +``` + +这样虚拟环境就创建好了,我们可以看到在这个目录下油三个目录被建立 + +* bin:包含一些在这个虚拟环境中可用的命令,以及开启虚拟环境的脚本 `activate` +* include:包含虚拟环境中的头文件,包括 `Python` 的头文件 +* lib:这里面就是一些依赖库 + +#### 激活 + +``` + source ~/workspaces/project_env/spider/bin/activate +``` + +此时我们就已经在虚拟环境中了 + +可以安装一下requests这个模块 + +``` + pip install requests +``` + +可以看到很快就成功 + +#### 退出虚拟环境 + +``` + deactivate +``` + +## virtualenvwrapper + +### 介绍 + +我们刚才了解了`virtualenv`,我觉得比较麻烦,每次开启虚拟环境之前要去虚拟环境所在目录下的 `bin` 目录下 `source`一下 `activate`,这就需要我们记住每个虚拟环境所在的目录。 + +一种可行的解决方案是,将所有的虚拟环境目录全都集中起来,比如放到 `~/virtualenvs/`,并对不同的虚拟环境使用不同的目录来管理。`virtualenvwrapper` 正是这样做的。并且,它还省去了每次开启虚拟环境时候的 `source` 操作,使得虚拟环境更加好用。 + +### 安装 + +``` + pip install virtualwrapper +``` + +这样我们就安装好了可以管理虚拟环境的神器 + +### 使用 + +#### 配置 + +首先需要对`virtualenvwrapper`进行配置: + +* 需要指定一个环境变量,叫做`WORKON_HOME`,它是用来存放各种虚拟环境目录的目录 +* 需要export vitualenvwrapper这个模块存放的位置 +* 需要运行一下它的初始化工具 `virtualenvwrapper.sh`,可通过`which virtualenvwrapper.sh`查看位置,我的在`/usr/local/bin/` + +由于每次都需要执行这两步操作,我们可以将其写入终端的配置文件中。 + +如果使用 `bash`,则添加到 `~/.bashrc` 中 + +如果使用 `zsh`,则添加到 `~/.zshrc` 中 + +这样每次启动终端的时候都会自动运行,终端启动之后 `virtualenvwrapper` 就可以用啦 + +``` + export WORKON_HOME='~/Workspaces/Envs' + + export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3 + + source /usr/local/bin/virtualenvwrapper.sh +``` + + +**创建虚拟机** + +``` +mkvirtualenv env +``` + +创建虚拟环境完成后,会自动切换到创建的虚拟环境中 + +当然也可以指定虚拟机的 python 版本 + +``` +mkvirtualenv env -p C:\python27\python.exe +``` + +**列出虚拟环境列表** + +``` +workon 或者 lsvirtualenv +``` + +**启动/切换虚拟环境** + +使用 workon [virtual-name] 即可切换到对应的虚拟环境 + +``` +workon [虚拟环境名称] +``` + + +**删除虚拟环境** + +``` +rmvirtualenv [虚拟环境名称] +``` + +**离开虚拟环境,和 virutalenv 一样的命令** + +``` +deactivate +``` diff --git "a/Article/advanced/Python\345\256\236\347\216\260\346\224\266\345\217\221\351\202\256\344\273\266.md" "b/Article/advanced/Python\345\256\236\347\216\260\346\224\266\345\217\221\351\202\256\344\273\266.md" new file mode 100644 index 00000000..5945b1e1 --- /dev/null +++ "b/Article/advanced/Python\345\256\236\347\216\260\346\224\266\345\217\221\351\202\256\344\273\266.md" @@ -0,0 +1,66 @@ +在实际开发中,当你收到一个需求的时候,比如要做一个「收发邮件」的功能。 + +如果你完全没有印象,没有思路,可以直接 Google 搜索的。 + +因为我们不可能对每个知识点都了解,不了解不可耻,但要懂得怎么去找资料了解。 + +强调一下, + +用 Google 搜索。 + +用 Google 搜索。 + +用 Google 搜索。 + +恕我直言,百度搜索是真的辣鸡。 + +那我们怎么去找资料呢? + +首先我们可以直接 Google 「Python 收发邮件」,就可以得到这么一个结果。 + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-15-065554.png) + +这种常用的需求,基本只要看前几个就能知道大概的思路了。 + +可以看到,用 Python 实现邮件的收发,主要用到 smtplib 和 email这两个模块。 + + +至于这些模块怎么用,直接看 [Python 官方文档](https://docs.python.org/3.7/library/smtplib.html?highlight=smtplib) + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-15-065957.png) + +真的,没有任何教程比官方文档资料还全。 + +不过我们可以总结一下这些内容。 + +**1、SMTP 发送邮件** + +Python 发送邮件主要步骤如下: + +* `import smtplib` + - 导入 `smtplib` 模块,主要用于构造传输服务的 +* `server = smtplib.SMTP()` + - SMTP 是 smtplib 模块中的一个类(class),实例化这个类,方便我们调用他里面的方法。 + - SMTP (Simple Mail Transfer Protocol)翻译过来是“简单邮件传输协议”的意思,SMTP 协议是由源服务器到目的地服务器传送邮件的一组规则。 +* `server.connect(host, port)` + - 连接(connect)指定的服务器 + - host 是指定连接的邮箱服务器,你可以指定服务器的域名。 + - port 服务器的端口号 + - 这些怎么找到,好比 qq 邮箱,在「设置」那里就有相关的开关和说明。 + - ![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-15-090427.png) + - 点相关的说明,你就能看到对应的服务器地址和端口号了 + - ![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-10-15-090619.png) +* `server.login(username, password)` + - 登录的账号密码 +* `server.sendmail(from_addr, to_addr, msg)` + - 发送邮件,发送邮件一般是谁发给了谁,发送了什么?总结为也就是三个参数,发送者,接受者,发送邮件的内容。 + - from_addr:邮件发送地址 + - to_addr:邮件收件人地址 + - msg : 发送邮件的内容,邮件内容需要用到 `email` 模块。通过 `email` 模块我们可以定义邮件的主题,收件人信息,发件人信息等等。 +* `server.quit()` + - 退出服务 + + 直接看下例子,给 QQ 邮箱发送一个邮件: + + + diff --git a/Article/advanced/advanced.md b/Article/advanced/advanced.md new file mode 100644 index 00000000..37af8d02 --- /dev/null +++ b/Article/advanced/advanced.md @@ -0,0 +1,2 @@ +* [使用Python虚拟环境](/Article/advanced/使用Python虚拟环境.md) +* [Mac中使用virtualenv和virtualenvwrapper](/Article/advanced/Mac中使用virtualenv和virtualenvwrapper.md) diff --git "a/Article/advanced/\344\275\277\347\224\250Python\350\231\232\346\213\237\347\216\257\345\242\203.md" "b/Article/advanced/\344\275\277\347\224\250Python\350\231\232\346\213\237\347\216\257\345\242\203.md" new file mode 100644 index 00000000..c7eddae1 --- /dev/null +++ "b/Article/advanced/\344\275\277\347\224\250Python\350\231\232\346\213\237\347\216\257\345\242\203.md" @@ -0,0 +1,130 @@ +python 的虚拟环境可以为一个 python 项目提供独立的解释环境、依赖包等资源,既能够很好的隔离不同项目使用不同 python 版本带来的冲突,而且还能方便项目的发布。 + +# virtualenv # + +[virtualenv](http://pypi.python.org/pypi/virtualenv)可用于创建独立的 Python 环境,它会创建一个包含项目所必须要的执行文件。 + +**安装 virtualenv** + +``` +$ pip install virtualenv +``` + + +**配置 pip 安装第三方库的镜像源地址** + +我们都知道,国内连接国外的服务器都会比较慢,有时候设置下载经常出现超时的情况。这时可以尝试使用国内优秀的[豆瓣源](https://pypi.douban.com/simple)镜像来安装。 + +使用豆瓣源安装 virtualenv + +``` +pip install -i https://pypi.douban.com/simple virtualenv +``` + +**virtualenv使用方法** + +如下命令表示在当前目录下创建一个名叫 env 的目录(虚拟环境),该目录下包含了独立的 Python 运行程序,以及 pip副本用于安装其他的 packge + +``` +virtualenv env +``` + + +当然在创建 env 的时候可以选择 Python 解释器,例如: + +``` +virtualenv -p /usr/local/bin/python3 venv +``` + +默认情况下,虚拟环境会依赖系统环境中的 site packages,就是说系统中已经安装好的第三方 package 也会安装在虚拟环境中,如果不想依赖这些 package,那么可以加上参数 `--no-site-packages` 建立虚拟环境 + +``` +virtualenv --no-site-packages [虚拟环境名称] +``` + +**启动虚拟环境** + +``` +cd ENV +source ./bin/activate +``` + +注意此时命令行会多一个`(ENV)`,ENV为虚拟环境名称,接下来所有模块都只会安装到这个虚拟的环境中去。 + +**退出虚拟环境** + +``` +deactivate +``` + +如果想删除虚拟环境,那么直接运行`rm -rf venv/`命令即可。 + +**在虚拟环境安装 Python packages** + +Virtualenv 附带有 pip 安装工具,因此需要安装的 packages 可以直接运行: + +``` +pip install [套件名称] +``` + +# Virtualenvwrapper + +Virtualenvwrapper 是一个虚拟环境管理工具,它能够管理创建的虚拟环境的位置,并能够方便地查看虚拟环境的名称以及切换到指定的虚拟环境。 + + +**安装(确保virtualenv已经安装)** + +``` +pip install virtualenvwrapper +``` + +或者使用豆瓣源 + +``` +pip install -i https://pypi.douban.com/simple virtualenvwrapper-win +``` + +注: + +安装需要在非虚拟环境下进行 + +**创建虚拟机** + +``` +mkvirtualenv env +``` + +创建虚拟环境完成后,会自动切换到创建的虚拟环境中 + +当然也可以指定虚拟机的 python 版本 + +``` +mkvirtualenv env -p C:\python27\python.exe +``` + +**列出虚拟环境列表** + +``` +workon 或者 lsvirtualenv +``` + +**启动/切换虚拟环境** + +使用 workon [virtual-name] 即可切换到对应的虚拟环境 + +``` +workon [虚拟环境名称] +``` + + +**删除虚拟环境** + +``` +rmvirtualenv [虚拟环境名称] +``` + +**离开虚拟环境,和 virutalenv 一样的命令** + +``` +deactivate +``` diff --git a/Article/codeSpecification/codeSpecification_Preface.md b/Article/codeSpecification/codeSpecification_Preface.md new file mode 100644 index 00000000..59911c8b --- /dev/null +++ b/Article/codeSpecification/codeSpecification_Preface.md @@ -0,0 +1,10 @@ +# 前言 # + +本来不应该把这个章节放在那面前面的,因为还没进行学习之前,直接看这个章节,会感觉有很多莫名其妙的东西。 + +但是把这个章节放在前面的用意,只是让大家预览一下,有个印象,而且在以后的学习中,也方便大家查阅。 + +# 目录 # + +![](http://twowaterimage.oss-cn-beijing.aliyuncs.com/2019-07-20-Python%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83.png) + diff --git a/codeSpecification/codeSpecification_first.md b/Article/codeSpecification/codeSpecification_first.md similarity index 97% rename from codeSpecification/codeSpecification_first.md rename to Article/codeSpecification/codeSpecification_first.md index 1c44091d..5f3faa6e 100644 --- a/codeSpecification/codeSpecification_first.md +++ b/Article/codeSpecification/codeSpecification_first.md @@ -54,10 +54,6 @@ def main(): * 可以使用多个空行分隔多组相关的函数 * 函数中可以使用空行分隔出逻辑相关的代码 -### 2.5、编码 - -* 文件使用 UTF-8 编码 -* 文件头部加入`#-*-conding:utf-8-*-`标识 ## 3、import 语句 @@ -258,4 +254,4 @@ Optional plotz says to frobnicate the bizbaz first. """ """Oneline docstring""" -``` \ No newline at end of file +``` diff --git a/codeSpecification/codeSpecification_second.md b/Article/codeSpecification/codeSpecification_second.md similarity index 99% rename from codeSpecification/codeSpecification_second.md rename to Article/codeSpecification/codeSpecification_second.md index 31248cb7..ae4af9ec 100644 --- a/codeSpecification/codeSpecification_second.md +++ b/Article/codeSpecification/codeSpecification_second.md @@ -4,6 +4,7 @@ ### 1.1、块注释 “#”号后空一格,段落件用空行分开(同样需要“#”号) + ```python # 块注释 # 块注释 @@ -14,6 +15,7 @@ ### 1.2、行注释 至少使用两个空格和语句分开,注意不要使用无意义的注释 + ```python # 正确的写法 x = x + 1 # 边框加粗一个像素 @@ -122,3 +124,5 @@ def func(arg1, arg2): * 文档注释不是越长越好, 通常一两句话能把情况说清楚即可 * 模块、公有类、公有方法, 能写文档注释的, 应该尽量写文档注释 + + diff --git a/codeSpecification/codeSpecification_third.md b/Article/codeSpecification/codeSpecification_third.md similarity index 100% rename from codeSpecification/codeSpecification_third.md rename to Article/codeSpecification/codeSpecification_third.md diff --git a/Article/django/Django.md b/Article/django/Django.md new file mode 100644 index 00000000..7d79dfd6 --- /dev/null +++ b/Article/django/Django.md @@ -0,0 +1,12 @@ +# Django + +Python 下有许多款不同的 Web 框架。Django 是重量级选手中最有代表性的一位。许多成功的网站和 APP 都基于 Django。 + +如果对自己的基础有点信息的童鞋,可以尝试通过国外的 ![Django 博客从搭建到部署系列教程](https://simpleisbetterthancomplex.com/series/2017/09/04/a-complete-beginners-guide-to-django-part-1.html) 进行入门,这个教程讲的非常的详细,而且还有很多有趣的配图。不过可能因为墙的原因,很多人会访问不到,就算访问到了,也因为是英语的,不会进行耐心的阅读学习。因此我打算翻译这个教程。 + +* [一个完整的初学者指南Django-part1](/Article/django/一个完整的初学者指南Django-part1.md) +* [一个完整的初学者指南Django-part2](/Article/django/一个完整的初学者指南Django-part2.md) + +后面经一个朋友说,这个教程已经有人在翻译了,因此我也不翻译了,不过感觉我的翻译还是挺好的,因为不是直译的,是通过了解后,用自己的语言再次表达出来。 + +这里有上面这个教程翻译计划的 [Github](https://github.com/wzhbingo/django-beginners-guide) 以及 [博客](https://www.cloudcrossing.xyz/post/20/),觉得哪个看得舒服,就选哪个进行学习。 diff --git "a/Article/django/\344\270\200\344\270\252\345\256\214\346\225\264\347\232\204\345\210\235\345\255\246\350\200\205\346\214\207\345\215\227Django-part1.md" "b/Article/django/\344\270\200\344\270\252\345\256\214\346\225\264\347\232\204\345\210\235\345\255\246\350\200\205\346\214\207\345\215\227Django-part1.md" new file mode 100644 index 00000000..8e4c73d4 --- /dev/null +++ "b/Article/django/\344\270\200\344\270\252\345\256\214\346\225\264\347\232\204\345\210\235\345\255\246\350\200\205\346\214\207\345\215\227Django-part1.md" @@ -0,0 +1,472 @@ +>源自:https://simpleisbetterthancomplex.com/series/2017/09/04/a-complete-beginners-guide-to-django-part-1.html + +### 一个完整的初学者指南Django - 第1部分 + + ![一个完整的初学者指南Django - 第1部分](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/featured.jpg) + + + ![Python 3.6.2](https://img.shields.io/badge/python-3.6.2-brightgreen.svg) ![Django 1.11.4](https://img.shields.io/badge/django-1.11.4-brightgreen.svg) + + +#### 介绍 + +![欢迎班](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/Pixton_Comic_Welcome_Class.png) + + +今天我将开始一个关于 Django 基础知识的新系列教程。这是一个完整的 Django 初学者指南。材料分为七个部分。我们将从安装,开发环境准备,模型,视图,模板,URL 到更高级主题(如迁移,测试和部署)来探索所有基本概念。 + + +我想做一些不同的事情。一个教程,易于遵循,信息丰富和有趣的阅读。因此我想出了在文章中创建一些漫画的想法来说明一些概念和场景。希望你喜欢这种阅读方式! + + +但在我们开始之前...... + + +我想通过孔夫子的名言来开始我们的课程: + +> 我听见了,我就忘了 +> +> 我看见了,我就记得了 +> +> 我去做了,我就理解了 + +![孔子名言](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/Pixton_Comic_Confucius_Quote.png) + +所以,一定要动手!不要只阅读教程。让我们一起来实操,这样你将通过做和练会学习到更多的知识。 + +* * * + +#### 为什么选择 Django? + + +Django 是一个用 Python 编写的 Web 框架。这个 Web 框架支持动态网站,应用程序和服务开发。它提供了一组工具和功能,可解决许多与 Web 开发相关的常见问题,例如安全功能,数据库访问,会话,模板处理,URL 路由,国际化,本地化等等。 + + +使用诸如 Django 之类的 Web 框架,能使我们能够以标准化的方式快速开发安全可靠的Web 应用程序,从而无需重新开发。 + + +那么,Django 有什么特别之处呢? + +对于初学者来说,这是一个 Python Web 开源框架,这意味着您可以从各种各样的开源库中受益。在[python软件资料库(pypi)](https://pypi.python.org/pypi) 中托管了超过 **11.6万** 个的包(按照 2017 年 9 月 6 日的数据)。如果你需要解决一个特定问题的时候,可能已经有相关的库给你使用。 + +Django 是用 Python 编写的最流行的 Web 框架之一。它可以提供各种功能,例如用于开发和测试的独立 Web 服务器,缓存,中间件系统,ORM,模板引擎,表单处理,基于 Python 单元测试工具的接口。Django 还附带了电池,提供内置应用程序,如认证系统,具有自动生成`CRUD`(增删改除)操作页面的管理界面,生成订阅文档(RSS / Atom),站点地图等。甚至在 Django 中建立了一个地理信息系统(GIS)框架。 + +而且 Django 的开发得到了 [Django软件基金会的](https://www.djangoproject.com/foundation/)支持,并且由 JetBrains 和 Instagram 等公司赞助。Django 到目前为止,已经持续开发维护超过12年了,这足以证明它是一个成熟,可靠和安全的 Web 框架。 + +##### 谁在使用Django? + +为什么要知道谁在使用 Django 呢? + +因为这能很好的让我们了解和知道它能做些什么? + +在使用 Django 的最大网站中,有:[Instagram](https://instagram.com/), [Disqus](https://disqus.com/),[Mozilla](https://www.mozilla.org/), [Bitbucket](https://bitbucket.org/),[Last.fm](https://www.last.fm/), [National Geographic](http://www.nationalgeographic.com/)。 + +当然,远远不止上面列举的这些,你可以看下 [Django Sites](https://www.djangosites.org/) 数据库,它们提供了超过 **5000** 个 Django 支持的 Web站点的列表。 + +顺便说一下,去年在 Django Under The Hood 2016 大会上,Django 核心开发人员Carl Meyer 和 Instagram 员工就[如何在规模上使用Django](https://www.youtube.com/watch?v=lx5WQjXLlq8) 以及它如何支持其增长展开了一次演讲。这是一个长达一个小时的谈话,如果你有兴趣的话,可以去了解下。 + + +* * * + +#### 安装 + +如果我们想开始使用 Django ,那么我们需要安装一些应用程序,包括安装 **Python**,**Virtualenv** 和 **Django**。 + +![基本设置](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/Pixton_Comic_Basic_Setup.png) + + +一开始,强烈建议使用虚拟环境,虽然不是强制性的,可是这对于初学者来说,是一个很好的开端. + + +在使用 Django 开发 Web 站点或 Web 项目时,必须安装外部库以支持开发是非常常见的。使用虚拟环境,您开发的每个项目都会有其独立的环境。所以依赖关系不会发生冲突。它还允许您维护在不同 Django 版本上运行的本地计算机项目。 + + +##### 安装Python 3.6.2 + +我们想要做的第一件事是安装最新的 Python 发行版,它是 **Python 3.6.2**。至少在我写这篇教程的时候是这样。如果有更新的版本,请与它一起使用。接下来的步骤应该保持大致相同。 + +我们将使用 Python 3,因为最重要的 Python 库已经移植到 Python 3,并且下一个主要的 Django 版本(2.x)不再支持 Python 2。所以 Python 3 是很有必要的。 + +在 Mac 中,最好的安装方法就是 [Homebrew](https://brew.sh/)。如果您还没有在Mac 上安装它,请在 **终端** 运行以下命令: + +``` +/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +``` + +如果您没有安装**命令行工具`(Command Line Tools)`**,则 Homebrew 安装可能需要更长一点时间。但它会自动处理,所以不用担心。请坐下来等到安装完成。 + +当您看到以下消息时,您会知道安装何时完成: + + +``` +==> Installation successful! + +==> Homebrew has enabled anonymous aggregate user behaviour analytics. +Read the analytics documentation (and how to opt-out) here: + https://docs.brew.sh/Analytics.html + +==> Next steps: +- Run `brew help` to get started +- Further documentation: + https://docs.brew.sh +``` + +请运行以下命令来安装Python 3: + +``` +brew install python3 +``` + + +由于 macOS 已经安装了Python 2,所以在安装 Python 3 之后,您将可以使用这两个版本。 + +要运行 Python 2,请使用`python`终端中的命令。对于 Python 3,请`python3`改用。 + +我们可以通过在终端中输入来测试安装: + +``` +python3 --version +Python 3.6.2 +``` + +![macOS测试Python 3](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/mac/test-python.png) + +到此时,Python 已经安装完成了。进入下一步:虚拟环境! + +##### 安装 Virtualenv + +接下来这一步,我们将通过 **pip**(一个管理和安装Python包的工具)来安装**Virtualenv**。 + + +请注意,Homebrew 已经为您的 Python 3.6.2 安装了 `pip3`。 + +在终端中,执行下面的命令: + +``` +sudo pip3 install virtualenv +``` + +![pip3安装virtualenv](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/mac/pip-virtualenv.png) + + +到目前为止,我们执行的操作都是在系统环境下的。不过,从这一刻起,我们安装的所有东西,包括 Django 本身,都将安装在虚拟环境中。 + + +你可以这样想像一下:对于每个 diango 项目,我们都会为它创建一个虚拟环境。这就好比每个 Django 项目都是一个独立的沙盒,你可以在这个沙盒里随意的玩,安装软件包,卸载软件包,不管怎么对系统环境都不会有任何影响,也不会对其他项目有影响。 + + +我个人喜欢在我的电脑上创建一个 **Development** 的文件夹,然后在这个文件夹下存放我的所有项目。当然,你也可以根据下面的步骤来创建你个人的目录。 + + +通常,我会在我的 **Development** 文件夹中创建一个项目名称的新文件夹。竟然这是我们的第一个项目,就直接将项目名称起为 **myproject**。 + +``` +mkdir myproject +cd myproject +``` + +![创建myproject文件夹](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/mac/myproject.png) + + +该文件夹将存储与 Django 项目相关的所有文件,包括其虚拟环境。 + +接下来,我们将开始创建我们第一个虚拟环境和安装 Django。 + +在 **myproject** 文件夹中,我们创建一个基于 python 3 的虚拟环境。 + +``` +virtualenv venv -p python3 +``` + +![VIRTUALENV](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/mac/venv.png) + +如上图所示,我们的虚拟环境已创建完成。那么我们将如何使用它呢? + + +当然,我们先开启虚拟环境啦,可以通过以下命令来激活一下虚拟环境: + + + ``` + source venv/bin/activate + ``` + +如果你在命令行的前面看到 **(venv)**,就说明,虚拟环境激活成功,现在已经进入到虚拟环境里面了。如下图所示: + + +![Virtualenv激活](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/mac/activate.png) + + +那么这里面到底发生了什么呢? + + +其实这里我们首先创建了名为 **venv** 的特殊文件夹,这个文件夹里面有 python 的副本,当我们激活 **venv** 环境之后,运行 `Python` 命令时,它使用的是存储在 **venv** 里面 `Python` 环境 ,而不是我们装在操作系统上的。 + + +如果在该环境下,我们使用 **PIP** 安装 python 软件包,比如 Django ,那么它是被安装在 **venv** 的虚拟环境上的。 + + +这里有一点需要注意的,当我们启动了 **venv** 这个虚拟环境后,我们使用命令 `python` 就能调用 python 3.6.2 ,而且也仅仅使用 `pip`(而不是`pip3`)来安装软件包。 + + +那么如果我们想退出 **venv** 虚拟环境,该如何操作呢? + +只要运行以下命令就可以: + +``` +deactivate +``` + +不过,现在我们先不退出虚拟环境 **venv** ,保持着虚拟环境的激活状态,开始下一步操作。 + + + + +##### 安装Django 1.11.4 + +现在我们来安装以下 Django 1.11.4 ,因为我们已经开启了虚拟环境 **venv** ,因此,这操作会非常的简单。我们将运行下面的命令来安装 Django : + +``` +pip install django +``` + +![pip安装django](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/mac/pip-django.png) + + +安装成功了,现在一切都准备就绪了! + + +![结束安装](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/Pixton_Comic_End_Installation.png) + +* * * + +#### 开始一个新项目 + +要开始一个新的 Django项目,运行下面的命令: + +到目前为止,我们终于可以开始一个新的 Django 项目了,运行下面的命令,创建一个 Django 项目: + +``` +django-admin startproject myproject +``` + +命令行工具 **django-admin** 会在安装 Django 的时候一起安装的。 + + +当我们运行了上面的命令之后,系统就会自动的为 Django 项目生成基础的文件。 + + +我们可以打开 **myproject** 目录,可以看到具体的文件结构如下所示: + + +``` +myproject/ <-- higher level folder + |-- myproject/ <-- django project folder + | |-- myproject/ + | | |-- __init__.py + | | |-- settings.py + | | |-- urls.py + | | |-- wsgi.py + | +-- manage.py + +-- venv/ <-- virtual environment folder +``` + + +可以看到,一个初始 Django 的项目由五个文件组成: + + +* **manage.py**:**django-admin** 是命令行工具的快捷方式。它用于运行与我们项目相关的管理命令。我们将使用它来运行开发服务器,运行测试,创建迁移等等。 +* **__init__.py**:这个空文件告诉 Python 这个文件夹是一个 Python 包。 +* **settings.py**:这个文件包含了所有的项目配置。我们会一直使用到这个文件。 +* **urls.py**:这个文件负责映射我们项目中的路由和路径。例如,如果您想在 URL `/about/` 中显示某些内容,则必须先将其映射到此处。 +* **wsgi.py**:该文件是用于部署简单的网关接口。现在我们暂时不用关心它的内容。 + + + +Django 自带有一个简单的 Web 服务器。在开发过程中非常方便,所以我们不需要安装其他任何软件即可以在本地运行项目。我们可以通过执行命令来运行它: + +``` +python manage.py runserver +``` + + +现在在 Web 浏览器中打开以下 URL:**http://127.0.0.1:8000**,您应该看到以下页面: + + +![有效!](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/it-worked.png) + + +这里提醒一点,如果你需要停止服务器,可以 `Control + C` 点击停止开发服务器。 + +* * * + +#### Django 的应用 + + +在 Django 哲学中,我们有两个重要的概念: + +* **app**:是一个可以执行某些操作的 Web 应用程序。一个应用程序通常由一组 models(数据库表),views(视图),templates(模板),tests(测试) 组成。 +* **project**:是配置和应用程序的集合。一个项目可以由多个应用程序或一个应用程序组成。 + +请注意,如果没有一个 project,你就无法运行 Django 应用程序。像博客这样的简单网站可以完全在单个应用程序中编写,例如可以将其命名为 blog或 weblog。 + +![Django应用程序](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/Pixton_Comic_Django_Apps.png) + + +当然这是组织源代码的一种方式,现在刚入门,判断确定什么是不是应用程序这些还不太重要。包括如何组织代码等,现在都不是担心这些问题的时候。现在,首先让我们先熟悉了解 Django 的 API 和基础知识。 + +好了,为了更好的了解,我们先来创建一个简单的论坛项目,那么我们要创建一个应用程序,首先要进入到 **manage.py** 文件所在的目录并执行以下命令: + +``` +django-admin startapp boards +``` + + +请注意,这次我们使用了命令 **startapp**。 + +这会给我们以下的目录结构: + +``` +myproject/ + |-- myproject/ + | |-- boards/ <-- our new django app! + | | |-- migrations/ + | | | +-- __init__.py + | | |-- __init__.py + | | |-- admin.py + | | |-- apps.py + | | |-- models.py + | | |-- tests.py + | | +-- views.py + | |-- myproject/ + | | |-- __init__.py + | | |-- settings.py + | | |-- urls.py + | | |-- wsgi.py + | +-- manage.py + +-- venv/ +``` + + +所以,我们先来看看每个文件的功能: + +* **migrations /**:在这个文件夹中,Django 会存储一些文件以跟踪您在 **models.py** 文件中创建的更改,目的是为了保持数据库和 **models.py** 同步。 +* **admin.py**:这是 Django应用程序一个名为 **Django Admin** 的内置配置文件。 +* **apps.py**:这是应用程序本身的配置文件。 +* **models.py**:这里是我们定义 Web 应用程序实体的地方。models 由 Django 自动转换为数据库表。 +* **tests.py**:该文件用于为应用程序编写单元测试。 +* **views.py**:这是我们处理Web应用程序请求(request)/响应(resopnse)周期的文件。 + +现在我们创建了我们的第一个应用程序,让我们来配置一下项目以便启用这个应用程序。 + + +为此,请打开**settings.py**并尝试查找`INSTALLED_APPS`变量: + +**settings.py** + +``` +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] +``` + +正如你所看到的,Django 已经安装了6个内置的应用程序。它们提供大多数Web应用程序所需的常用功能,如身份验证,会话,静态文件管理(图像,JavaScript,CSS等)等。 + +我们将会在本系列教程中探索这些应用程序。但现在,先不管它们,只需将我们的应用程序 boards 添加到 `INSTALLED_APPS` 列表即可: + +``` +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'boards', +] +``` + +使用上个漫画中的正方形和圆形的比喻,黄色圆圈将成为我们的 **boards** 应用程序,而 **django.contrib.admin**,**django.contrib.auth** 等将成为红色圆圈。 + +* * * + +#### Hello, World! + + +现在我们先来写一个我们的第一个 **视图(view)** ,那么,现在我们来看看该如何使用 Django 来创建一个新的页面吧。 + + +打开 **boards** 应用程序中的 **views.py** 文件,并添加下面的代码: + +**views.py** + +```python +from django.http import HttpResponse + +def home(request): + return HttpResponse('Hello, World!') +``` + +**视图(view)** 是接收 `HttpRequest` 对象并返回 `HttpResponse`对象的 Python 函数。接收 request 作为参数并返回 response 作为结果。这个过程是需要我们记住的。 + + +因此,就像我们上面的代码,我们定义了一个简单的视图,命名为 `home` ,然后我们简单的返回了一个字符串 **Hello,World!** + + +那么我们直接运行就可以了吗? + +并不是的,我们还没有告诉 Django 什么时候调用这个 **视图(view)** 呢?这就需要我们在 **urls.py** 文件中完成: + + +**urls.py** + +```Python +from django.conf.urls import url +from django.contrib import admin + +from boards import views + +urlpatterns = [ + url(http://github.com/r'%5E/code%3E,%20views.home,%20name='home'), + url(http://github.com/r'%5Eadmin/',%20admin.site.urls), +] +``` + + +如果您将上面的代码段与您的 **urls.py** 文件进行比较,您会注意到我添加了以下的代码:`url(http://github.com/r'%5E'),%20views.home,%20name='home')` 并使用我们的应用程序 **boards** 中导入了 **views** 模块。`from boards import views` + +可能这里大家还是会有很多疑问,不过先这样做,在后面我们会详细探讨这些概念。 + +但是现在,Django 使用**正则表达式**来匹配请求的URL。对于我们的 **home** 视图,我使用的是`^$`正则表达式,它将匹配空白路径,这是主页(此URL:**http://127.0.0.1:8000**)。如果我想匹配URL **http://127.0.0.1:8000/homepage/**,那么我们 url 的正则表达式就应该这样写:`url(http://github.com/r'%5Ehomepage/'),%20views.home,%20name='home')`。 + +运行项目,让我们看看会发生什么: + +``` +python manage.py runserver +``` + + +在 Web 浏览器中,打开 http://127.0.0.1:8000 : + + +![你好,世界!](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-1/hello-world.png) + + +这样我们就看到了我们刚刚创建的第一个界面了。 + +* * * + +#### 总结 + +这是本系列教程的第一部分。在本教程中,我们学习了如何安装最新的 Python 版本以及如何设置开发环境。我们还介绍了虚拟环境,并开始了我们第一个 Django 项目,并已创建了我们的初始应用程序。 + +我希望你喜欢第一部分!第二部将涉及模型,视图,模板和网址。我们将一起探索所有的Django 基础知识! + +就这样我们可以保持在同一页面上,我在 GitHub 上提供了源代码。项目的当前状态可以在发布**release tag v0.1-lw**下找到。下面的链接将带你到正确的地方: + +[https://github.com/sibtc/django-beginners-guide/tree/v0.1-lw](https://github.com/sibtc/django-beginners-guide/tree/v0.1-lw) diff --git "a/Article/django/\344\270\200\344\270\252\345\256\214\346\225\264\347\232\204\345\210\235\345\255\246\350\200\205\346\214\207\345\215\227Django-part2.md" "b/Article/django/\344\270\200\344\270\252\345\256\214\346\225\264\347\232\204\345\210\235\345\255\246\350\200\205\346\214\207\345\215\227Django-part2.md" new file mode 100644 index 00000000..f3d83c33 --- /dev/null +++ "b/Article/django/\344\270\200\344\270\252\345\256\214\346\225\264\347\232\204\345\210\235\345\255\246\350\200\205\346\214\207\345\215\227Django-part2.md" @@ -0,0 +1,1182 @@ + ![一个完整的初学者指南Django - 第2部分](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/featured.jpg) + + + ![Python 3.6.2](https://img.shields.io/badge/python-3.6.2-brightgreen.svg) ![Django 1.11.4](https://img.shields.io/badge/django-1.11.4-brightgreen.svg) + + +#### 介绍 + + +欢迎来到 Django 教程的第二部分!在上一课中,我们安装了项目所需要的一切软件,希望你们在学习这篇文章之前,安装了 Python 3.6,并且在虚拟环境中运行Django 1.11。因为,在本篇文章中,我们将继续在这个项目中编写我们的代码。 + + +在这一篇文章中,可能不会有太多的代码操作,主要是讨论分析项目。在下一篇中,我们就开始学习 Django 的基础知识,包括模型(models),管理后台(admin),视图(views),模板(templates)和 路由(URL)。 + + +在这里,还是跟第一篇一样,建议大家多动手。 + +* * * + +#### 论坛项目 + + +每个人的学习习惯都是不同的,不知道你们是怎样的,就我个人而言,通过看实例和一些代码片段,可以让我学的更多,学的更快。但是,有些时候当我们看到 `Class A`和`Class B` ,或者是 `foo(bar)` 这样的例子的时候,我们是很难理解这些概念的。 + + +所以在我们进入模型(models),创建视图(views) 这些有趣的代码实操之前,我们还是需要花点时间,简单的讨论一下我们将怎样设计,开发这个项目。 + + +但是如果你已经有 web 开发经验的,而且觉得讲的太细了,那么你可以快速的浏览一下,然后进入到 【模型(models)】那一块中。 + +如果你对 Web 开发并不熟悉,那么我强烈建议你认真阅读下去。这里会介绍 web 应用程序开发的建模和设计,因为对于 web 开发来说,敲代码只是其中的一部分,模型的设计也是很重要的。 + + +![火箭科学](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/Pixton_Comic_Rocket_Science.png) + + +##### 用例图 + + +我们的项目本身是一个论坛系统,整个项目来说就是维护几个【论坛板块(boards)】 ,然后在每个板块里面,用户可以通过创建【主题(Topic)】并且在主题中讨论。 + + +一般情况下,只有管理员才能创建【论坛板块(boards)】,那么在用户这方面,我们就需要分为普通用户和管理员用户了,而且他们拥有的权限是不同的,管理员用户可以创建 【论坛板块(boards)】,【主题(Topic)】以及讨论回复,而普通用户只能发布【主题(Topic)】以及讨论回复。具体每个用户角色的功能分配如下图: + + + +> 图1:Web Board 核心功能的用例图 + + +![用例图](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/use-case-diagram.png) + + + +##### 类图 + + +从上面的用例图中,我们可以开始思考我们项目中的**实体类**有哪些了。这些实体是我们要创建的模型,它与我们的 Django 应用非常密切。 + + +如果要实现上面我们说到的论坛,那么我们至少需要以下的几个模型:**Board**,**Topic**,**Post**和**User**。 + +* **Board** : 版块 +* **Topic** : 主题 +* **Post** : 帖子(用户评论与回复) +* **User** : 用户 + + +> 图2:Web Board 类图 + + +![基本类图](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/basic-class-diagram.png) + + +上面我们只是说了需要有几个模型,并没有提到模型与模型之间是怎么关联的。 + + +通过上面的图片我们可以知道,主题(Topic)与版块(Board) 之间是有关联的,就好比我们需要知道这个主题(Topic) 是属于哪一个版块的(Board),因此我们需要一个字段,也就是可以通过外键爱关联它们。 + + +同样的,一个帖子(Post) 也是需要确定它是那个主题的,当然,用户和主题(Topic)和帖子(Post) 之间也是有联系的,因为我们需要确认是谁发的帖子,是谁回复评论了内容。 + + +竟然知道了模型之间的联系了,那么我们也必须要考虑这些模型应该存放哪些信息。就目前而言,我们的模型可以设计成这样: + + +> 图3:类(模型)之间关系的类图 + + +![类图](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/class-diagram.png) + + + +这个类图强调的是模型之间的关系,当然最后这些线条和箭头都会用字段来进行表示。 + +**Board(版块模型)** :Board 中有 **name** 和 **description** 这两个字段,name 是唯一的,主要是为了避免两个名称重复。description 则是用于描述把这个版块来用干什么的。 + + +**Topic(主题模型)** :subject 表示主题内容,last_update 用来定义话题的排序,starter 用来识别谁发起的话题,board 用于指定它属于哪个版块 + + +**Post(帖子模型)** : message 字段,用于存储回复的内容,created_at 创建的时间,在排序时候用(最先发表的帖子排最前面),updated_at 更新时间,告诉用户是否更新了内容,同时,还需要有对应的 User 模型的引用,Post 由谁创建的和谁更新的。 + + +**User(用户模型)** :这里有 username ,password,email 和 is_superuser 四个字段。 + + +这里值得注意的是,我们在 Django 应用中,不需要创建 User 用户模型,因为在 Django 的 contrib 中已经内置了 User 模型,我们可以直接拿来使用,就没必要重新创建了。 + + +认真观察的童鞋应该看到了,上面的模型关系图中,模型与模型之间的对应关系有数字 1,0..* 等等的字段,这是代表什么意思呢? + + +如下图,`1` 代表一个 Topic 必须与一个 Board 相关联,`0..*` 代表 Board 下面可能会有多个和 0 个 Topic ,也就是一对多的关系。 + + +![类图板和主题协会](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/class-diagram-board-topic.png) + + +这里也是一样,`1` 代表一个 Post 只有一个 Topic ,`1..*` 代表一个 Topic 下面可能会有 1 个和多个个 Post ,也就是说,一个主题最少一个一个帖子。 + + + +![类图主题和帖子关联](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/class-diagram-topic-post.png) + + +`1` 代表一个 Topic 有且至于一个 User ,`0..*` 代表一个 User(用户) 可能拥有多个 Topic ,也可能没有。 + + +![类图主题和用户关联](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/class-diagram-topic-user.png) + + +Post(帖子) 和 User(用户)的关系也是类似,一个 Post 必须有一个 User ,而一个 User 可能没有也可能有多个 Post。这里的 Post ,用户发布了之后是可以进行修改的,也就是更新(updated_by),当然如果又被修改,updated_by 就是为空了。 + + +![类图邮政和用户协会](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/class-diagram-post-user.png)一 + + +当然,如果你觉得上面的图看起来很复杂,那么你也可以不需要强调模型与模型之间的关系,直接强调字段就可以了,如下图: + + +> 图4:强调类(模型)属性(字段)的类图 + + +![类图属性](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/class-diagram-attributes.png) + + +其实这种表达图和前面那个显示箭头和线的表达图,要表达的内容是一样的。不过使用这种表达方式可能更符合 Django Modles API 的设计。 + + +好了,现在已经够 UML 了!为了绘制本节介绍的图表,我使用的是 [StarUML](http://staruml.io/) 工具。 + + +##### 原型图 + + +花了一些时间来设计我们的程序模型,后面我们也需要设计一下我们的网页原型图。只有这样,才能更好的让我们清楚的知道自己将要干什么? + + +![线框漫画](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/Pixton_Comic_Wireframes.png) + + + +首先,是我们的主页,在主页中,我们会显示我们所有的版块: + + +> 图5:主页显示所有的版块信息 + + +![线框板](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/wireframe-boards.png) + + +同样的,当用户点进了版块信息,进入到版块页面,那么版块页面也将显示该版块下的所有主题: + + +>图6:版块下的所有主题信息 + +![线框主题](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/wireframe-topics.png) + + +通过观察图片,细心的你,可能会发现,用户在这个页面有两条可以走的路线。第一条就是点击 “new topic” 来创建新的主题,第二条就是点击已经存在的主题进入相关的主题进行讨论回复。 + + + +“new topic” 的界面如下 : + + +![线框新主题](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/wireframe-new-topic.png) + + +而,进入了相关的主题后,应该显示具体的帖子信息和用户的一些回复信息: + + +![线框帖子](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/wireframe-posts.png) + + + +如果用户点击 “Reply” 的按钮,他们将看到下面的页面,并以相反的顺序(最新的第一个)对帖子进行显示: + +![线框回复](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/wireframe-reply.png) + + +那么这些图是用什么来绘制的呢?你可以使用 [draw.io](https://draw.io/) ,而且他是完全免费的。 + + +* * * + +#### 模型(Models) + + +上一部分,设计了我们 Web 应用的数据库还有界面原型设计。在模型(Models)这一部分中,我们将在 Django 中创建我们数据库的模型类:**Board** ,**Topic** 和 **Post** 。 + + +这里是不是有个疑问,明明我们设计数据库的时候是有 **User** 的,为什么我们不用创建它的模型类呢?是不是写漏了? + + +并不是,那是因为 **User** 这个模型类,已经内置在 Django 应用程序中的,**User** 模型就在 **django.contrib.auth** 中。在 settings.py 中,`INSTALLED_APPS` 就配置了**django.contrib.auth**。 + + +好了,现在我们将根据我们上面设计的数据库模型来完成我们项目 **boards** 下的 models.py 文件中的所有操作。 + + +> **boards/models.py** + +```python +from django.db import models +from django.contrib.auth.models import User + +class Board(models.Model): + name = models.CharField(max_length=30, unique=True) + description = models.CharField(max_length=100) + +class Topic(models.Model): + subject = models.CharField(max_length=255) + last_updated = models.DateTimeField(auto_now_add=True) + board = models.ForeignKey(Board, related_name='topics') + starter = models.ForeignKey(User, related_name='topics') + +class Post(models.Model): + message = models.TextField(max_length=4000) + topic = models.ForeignKey(Topic, related_name='posts') + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(null=True) + created_by = models.ForeignKey(User, related_name='posts') + updated_by = models.ForeignKey(User, null=True, related_name='+') +``` + +可以看到,创建的所有模型类,**Board** , **Topic** 和 **Post** 都是 **django.db.models.Model** 的子类,它们都将会转化成数据表。而 **django.db.models.Field** 的子类(Django 内置的核心类)的实例都会转化为数据表中的列。 + + +上面可以看到的 `CharField`,`DateTimeField` 等,都是 **django.db.models.Field** 的子类,在 Django 项目中都可以直接使用它们。 + + +在这里,我们仅仅使用了 `CharField`,`TextField`,`DateTimeField`,和 `ForeignKey` 字段来定义我们的模型(Models) 。当然,在 Django 中,不仅仅只是提供了这些字段,还提供了更多,更广泛的选择来代表不同类型的数据,比如还有:`IntegerField`,`BooleanField`, `DecimalField`。我们会根据不同的需求来使用它们。 + + +有些字段是需要参数的,就好比 `CharField` ,我们都设定了一个 `max_length` , 设置一个最大长度。当我们设定了这个字段后,就会作用于数据的。 + + +在 `Board` 模型(Model)中,在 `name` 字段中,我们也设置了参数 `unique=True`,顾名思义,这是为了在数据库中,保证该字段的唯一性。 + + +在 `Post` 模型中,`created_at` 字段有一个可选参数,`auto_now_add` 设置为 `True`。这是为了指明 Django 在创建 `Post` 对象的时候,`created_at` 使用的是当前的日期和时间。 + + +创建模型与模型之间关系的其中一种方法就是使用 `ForeignKey` 字段,使用这个字段,会自动创建模型与模型之间的联系,而且会在数据库中也创建它们的关系。使用 `ForeignKey` 会有一个参数,来表明他与那个模型之间的联系。 例如: + + +在 `Topic` 模型中,`models.ForeignKey(Board, related_name='topics')`,第一个参数是代表关联的表格(主表),在默认情况下,外键存储的是主表的主键(Primary Key)。第二个参数 `related_name` 是定义一个名称,用于反向查询的。Django 会自动创建这种反向关系。 虽然 `related_name` 是可选参数,但是如果我们不为它设置一个名称的,Django 会默认生成名称 `(class_name)_set` 。例如,在 `Board` 模型中,`Topic` 实例将在该 `topic_set` 属性下可用。而我们只是将其重新命名为`topics`,使用起来更加自然。 + + +在 `Post` 模型中,`updated_by` 字段设置`related_name='+'`。这指示 Django 我们不需要这种反向关系。 + + +下面这张图可以很好地看到设计图和源码之间的比较,其中绿线就表示了我们是如何处理反向关系的。 + + +![类图模型定义](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/class-diagram-django-models.png) + + +可能到这一步,你会问:“主键呢?”好像我们都没有定义主键啊。对,如果我们没有为模型(Models)指定主键,那么 Django 会自动生成它。 + + +##### 迁移模型(Migrating the Models) + + +到这一步,我们要开始告诉 Django 如何创建数据库,这样方便我们更好的使用。 + + +打开**终端** ,激活虚拟环境,进入到 **manage.py** 文件所在的文件夹,然后运行以下命令: + + +``` +python manage.py makemigrations +``` + +这时,你会看到这样的输出信息: + + +``` +Migrations for 'boards': + boards/migrations/0001_initial.py + - Create model Board + - Create model Post + - Create model Topic + - Add field topic to post + - Add field updated_by to post +``` + + +此时,Django 在 **boards / migrations** 目录内创建了一个名为**0001_initial.py** 的文件。它代表了我们应用程序模型的当前状态。在下一步中,Django 将使用该文件来创建表和列。 + + +迁移文件被翻译成 SQL 语句。如果您熟悉 SQL,则可以运行以下命令来检查将在数据库中执行的 SQL 指令: + +``` +python manage.py sqlmigrate boards 0001 +``` + + +如果你不熟悉 SQL,也不用担心。在本系列教程中,我们不会直接使用 SQL。所有的工作都将使用 Django ORM 来完成,它是一个与数据库进行通信的抽象层。 + +好了,下一步我们将把我们的迁移文件应用到我们的数据库中: + + +``` +python manage.py migrate +``` + + +输出应该是这样的: + +``` +Operations to perform: + Apply all migrations: admin, auth, boards, contenttypes, sessions +Running migrations: + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying boards.0001_initial... OK + Applying sessions.0001_initial... OK +``` + + + +因为这是我们第一次迁移数据库,所以该 `migrate` 命令还应用了 Django contrib 应用中现有的迁移文件,这些文件列于 `settings.py` 中的 `INSTALLED_APPS` 。 + + +而 `Applying boards.0001_initial... OK` 就是指我们在上一步中生成的迁移文件。 + + +好了,此时!我们的数据库已经可以使用了。 + + +![SQLite的](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/Pixton_Comic_SQLite.png) + + +> **注意:** 需要注意的是 **SQLite** 是一个数据库。SQLite 被许多公司用于成千上万的产品,如所有 Android 和 iOS 设备,所有主要的 Web 浏览器,Windows 10,MacOS 等。 +> +> 当然,它也不是适合所有的应用场景。SQLite 不能与 MySQL,PostgreSQL 或 Oracle 等数据库进行比较。大容量网站,密集型的应用程序,大数据集,高并发性,这些使用使用 SQLite 可能会导致很多问题。 +> +> 在我们开发的项目中,我们将使用 SQLite ,因为它很方便,我们不需要安装其他任何东西。当我们将项目部署到生产环境时,我们将切换到 PostgreSQL 。因为这对于简单的网站是不错的选择。但这里有一点要注意,对于复杂的网站,建议在开发和生产中使用相同的数据库。 + + +##### Models API + + +使用 Python 开发的一个重要优点是交互式 shell。我几乎一直都在使用它。这是一个可以快速尝试和测试实验的方法。 + +你可以使用 **manage.py** 加载我们的项目来启动 Python shell : + +启动命令: + +``` +python manage.py shell +``` + +可以看到这样的输出: + +``` +Python 3.6.2 (default, Jul 17 2017, 16:44:45) +[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin +Type "help", "copyright", "credits" or "license" for more information. +(InteractiveConsole) +>>> +``` + + +在我们使用 `python manage.py shell` 之外,我们也可以将项目添加到`sys.path`并加载 Django。这意味着我们可以在项目中导入我们的模型(models) 和任何其他资源。 + +我们从导入 **Board** 类开始: + +``` +from boards.models import Board +``` + +如果我们需要创建 **Board** 对象,我们可以执行以下操作: + +``` +board = Board(name='Django', description='This is a board about Django.') +``` + +此时我们只是创建了这个对象,并没有保存到数据库的,因此我们可以调用 `save` 方法,将这个对象保存在数据库中。 + + +``` +board.save() +``` + +该 `save` 方法 ,在创建对象和更新对象中都可以使用,这里 Django 会创建一个新的对象,因为 **Board** 实例是没有 **id** 这个字段的,因此保存后,Django 会自动设置一个 ID : + + +``` +board.id +1 +``` + + +其他的字段你也可以当作属性来访问就好了,比如: + +``` +board.name +'Django' +``` + +``` +board.description +'This is a board about Django.' +``` + + +要更新一个值,我们可以这样做: + + +``` +board.description = 'Django discussion board.' +board.save() +``` + + +每个 Django 模型 (Models) 都带有一个特殊的属性; 我们称之为 **Model Manager(模型管理器)**。我们可以通过 Python 属性 `objects` 来访问它。它主要用于在数据库中执行查询。例如,我们可以使用它来直接创建一个新的**Board** 对象: + +``` +board = Board.objects.create(name='Python', description='General discussion about Python.') +``` + +``` +board.id +2 +``` + +``` +board.name +'Python' +``` + +所以,结合之前的操作,我们现在有两个 boards 对象。我们可以使用`objects` 列出数据库中所有现有的 boards : + + +``` +Board.objects.all() +, ]> +``` + + +结果是一个 **QuerySet** 。稍后我们会进一步了解它。基本上,它是来自数据库的对象列表。通过输出结果,可以看到我们有两个对象,但我们只能读取 **Board对象** 。这是因为我们没有在 **Board** 模型中定义 `__str__` 方法。 + + +该 `__str__` 方法是一个对象的字符串表示。我们可以使用 Board 的名称来表示它。 + + +首先,退出交互式控制台: + + +``` +exit() +``` + + +现在编辑 **boards** 应用程序中的 **models.py** 文件: + + +``` +class Board(models.Model): + name = models.CharField(max_length=30, unique=True) + description = models.CharField(max_length=100) + + def __str__(self): + return self.name +``` + + +让我们再次尝试查询。再次打开交互式控制台: + + +``` +from boards.models import Board + +Board.objects.all() +, ]> +``` + + +仔细对比上面的,看下区别? + +可以看到上面那个是 object ,而这里是我们定义的字符串。 + + +我们可以将这个 **QuerySet** 看作一个列表。假设我们想遍历它并打印每个 Board(版块) 的描述: + + +``` +boards_list = Board.objects.all() +for board in boards_list: + print(board.description) +``` + + +结果是: + + +``` +Django discussion board. +General discussion about Python. +``` + + +当然,我们也可以使用 **Model Manager(模型管理器)** 来查询数据库,如果查询其中的一个,我们可以使用 `get` 的方法: + + +``` +django_board = Board.objects.get(id=1) + +django_board.name +'Django' +``` + +当然我们要小心这种情况,因为很容易发生内存溢出的。比如我们试图去查询一个不存在的对象,就好比我们数据库只有两个 Board 对象,如果你查询 `id=3`,那么它会引发一个异常: + + +``` +board = Board.objects.get(id=3) + +boards.models.DoesNotExist: Board matching query does not exist. +``` + +当然,在 `get` 方法中,参数可以是该模型下的字段,最好是使用唯一的标识字段。否则会返回多个对象,会导致异常的。 + + +``` +Board.objects.get(name='Django') + +``` + + +请注意,查询是区分大小写的,小写 “django” 是不匹配的: + + +``` +Board.objects.get(name='django') +boards.models.DoesNotExist: Board matching query does not exist. +``` + + +##### 模型操作摘要 + +下面的表格是我们在本章节中学到的方法和操作。代码示例使用 **Board** 模型作为参考示例。大写的 **Board** 代表类,小写的 **board** 是指 **Board** 的实例对象。 + + +| 描述 | 代码示例 | +| --- | --- | +| 创建一个对象并没有保存 | `board = Board()` | +| 保存一个对象(创建或更新) | `board.save()` | +| 在数据库中创建并保存一个对象 | `Board.objects.create(name='...', description='...')` | +| 列出所有对象 | `Board.objects.all()` | +| 获取由字段标识的单个对象 | `Board.objects.get(id=1)` | + + +在下一节中,我们将开始编写视图并在 HTML 页面中显示我们的版块页面。 + + +* * * + +#### Views, Templates 和静态文件 + + +回顾一下,我们之前做的。我们已经可以在应用程序的主页上显示 ”Hello ,World!“ 的界面了。 + + +> **MyProject/urls.py** + +``` +from django.conf.urls import url +from django.contrib import admin + +from boards import views + +urlpatterns = [ + url(http://github.com/r'%5E/code%3E,%20views.home,%20name='home'), + url(http://github.com/r'%5Eadmin/',%20admin.site.urls), +] +``` + +> **boards/views.py** + +``` +from django.http import HttpResponse + +def home(request): + return HttpResponse('Hello, World!') +``` + +好了,现在我们需要修改这个主页,如果你不记得我们的主页要做成什么样子,可以看看之前我们已经设计好的原型界面图。我们在主页上,要做的是在表格中显示一些版块的名单和其他的一些信息。 + + +首先我们要做的是:导入 **Board** 模型,然后获取所有的存在的版块(boards)信息 + + +> **boards/views.py** + + +``` +from django.http import HttpResponse +from .models import Board + +def home(request): + boards = Board.objects.all() + boards_names = list() + + for board in boards: + boards_names.append(board.name) + + response_html = '
'.join(boards_names) + + return HttpResponse(response_html) +``` + + + +然后我们运行,就会看到这个简单的 HTML 页面: + + + +![主页HttpResponse](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/boards-homepage-httpresponse.png) + + +但是,一般情况下,我们是不会通过这种方式去渲染 HTML ,在 **views.py** 中,我们只需要获取 **boards** 的集合,至于 HTML 渲染那部分的代码,我们应该在 Django 的 templates 目录下完成。 + + +##### Django 模板引擎设置 + +竟然我们要将 **views.py** 里渲染 HTML 的代码分离,那么我们首先要在 **baords** 的同目录下,创建一个名为 **templates** 的文件夹。 + + +``` +myproject/ + |-- myproject/ + | |-- boards/ + | |-- myproject/ + | |-- templates/ <-- here! + | +-- manage.py + +-- venv/ +``` + +在我们创建的 **templates** 文件夹中,我们创建一个名为 **home.html** 的 HTML 文件 + +> **templates/home.html** + +```html + + + + + Boards + + +

Boards

+ + {% for board in boards %} + {{ board.name }}
+ {% endfor %} + + + +``` + +**home.html** 的文件内容如上面的一样,是一些原始的 HTML 标签代码和 Django 语言上的代码:`{% for ... in ... %}` ,`{{ variable }}`。上面的代码中展示了如何使用 for 循环遍历 list 对象。 + +到此,我们的 HTML 页面已经完成了,可是我们还没有告诉 Django 在哪里能找到我们应用中的 `templates` 文件夹里的 HTML。 + + +首先,我们在 Django 中绑定一下我们的 `templates` ,打开我们 ** myproject** 项目中的 **settings.py** 文件,搜索 `TEMPLATES` 变量然后在 `DIRS`设置 :`os.path.join(BASE_DIR, 'templates')` + +具体如下: + +```python +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(BASE_DIR, 'templates') + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] +``` + +这样设计就好比相当于在你的项目中的完整路径下,在加上 "/templates" + +那是不是跟我们预想的一样呢?我们可以通过 python shell 进行调试: + +``` +python manage.py shell +``` + +``` +from django.conf import settings + +settings.BASE_DIR +'/Users/vitorfs/Development/myproject' + +import os + +os.path.join(settings.BASE_DIR, 'templates') +'/Users/vitorfs/Development/myproject/templates' +``` + + +可以看到,目录就是指向我们在上面创建的 **templates** 文件夹 + +此时,我们只是绑定了 **templates** 文件夹的路径,Django 并没有绑定我们 **home.html** ,我们可以在 **views.py** 中绑定: + +``` +from django.shortcuts import render +from .models import Board + +def home(request): + boards = Board.objects.all() + return render(request, 'home.html', {'boards': boards}) +``` + + + +运行后,HTML 的页面是这样的: + + +![主板渲染](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/boards-homepage-render.png) + +我们可以改进HTML模板来代替使用表格: + +> **templates/home.html** + +```html + + + + + Boards + + +

Boards

+ + + + + + + + + + + + {% for board in boards %} + + + + + + + {% endfor %} + +
BoardPostsTopicsLast Post
+ {{ board.name }}
+ {{ board.description }} +
00
+ + +``` + + +![主板渲染](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/boards-homepage-render-2.png) + + +##### 测试主页 + + +![测试漫画](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/Pixton_Comic_Testing.png) + +测试这部分会在这系列教程中会不断的重复探讨。 + + +现在让我们来写第一个测试,首先在应用程序 **boards** 中找到 **tests.py** + +> **boards/tests.py** + +``` +from django.core.urlresolvers import reverse +from django.test import TestCase + +class HomeTests(TestCase): + def test_home_view_status_code(self): + url = reverse('home') + response = self.client.get(url) + self.assertEquals(response.status_code, 200) +``` + +这是一个非常简单的测试用例,但非常的有用。我们在测试的是响应状态码,如果是 200 意味着成功。 + + +我们可以在控制台中检查响应码: + +![回应200](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/test-homepage-view-status-code-200.png) + + +如果出现未捕获的异常,语法错误或其他任何情况,Django 会返回状态代码**500**,这意味着**服务器错误**。现在,想象我们的应用程序有 100 个界面(view)。如果我们为所有视图(view)编写了这个简单的测试,只需一个命令,我们就可以测试所有视图是否返回成功代码,这样用户就不会在任何地方看到任何错误消息。如果没有自动化测试,我们需要逐一检查每个页面。 + +要执行 Django 的测试套件: + +``` +python manage.py test +``` + +``` +Creating test database for alias 'default'... +System check identified no issues (0 silenced). +. +---------------------------------------------------------------------- +Ran 1 test in 0.041s + +OK +Destroying test database for alias 'default'... +``` + +现在我们可以测试 Django 是否为请求的 URL 返回了正确的视图函数。这也是一个有用的测试,因为随着开发的进展,您会发现 **urls.py** 模块可能变得非常庞大而复杂。URL 配置全部是关于解析正则表达式的。有些情况下我们有一个非常宽容的URL,所以 Django 最终可能返回错误的视图函数。 + +以下是我们如何做到的: + +> **boards/tests.py** + +``` +from django.core.urlresolvers import reverse +from django.urls import resolve +from django.test import TestCase +from .views import home + +class HomeTests(TestCase): + def test_home_view_status_code(self): + url = reverse('home') + response = self.client.get(url) + self.assertEquals(response.status_code, 200) + + def test_home_url_resolves_home_view(self): + view = resolve('/') + self.assertEquals(view.func, home) +``` + + + +在第二个测试中,我们正在使用 `resolve` 功能。Django 使用它来将请求的 URL与 **urls.py** 模块中列出的 URL 列表进行匹配。该测试将确保使用 `/`根 URL ,是否返回主视图(home view)。 + +再次测试: + +``` +python manage.py test +``` + +``` +Creating test database for alias 'default'... +System check identified no issues (0 silenced). +.. +---------------------------------------------------------------------- +Ran 2 tests in 0.027s + +OK +Destroying test database for alias 'default'... +``` + + +要查看有关测试执行的更多详细信息,请将 **verbosity** 设置为更高级别: + +``` +python manage.py test --verbosity=2 +``` + +``` +Creating test database for alias 'default' ('file:memorydb_default?mode=memory&cache=shared')... +Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: admin, auth, boards, contenttypes, sessions +Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... +Running migrations: + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying admin.0002_logentry_remove_auto_add... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying auth.0007_alter_validators_add_error_messages... OK + Applying auth.0008_alter_user_username_max_length... OK + Applying boards.0001_initial... OK + Applying sessions.0001_initial... OK +System check identified no issues (0 silenced). +test_home_url_resolves_home_view (boards.tests.HomeTests) ... ok +test_home_view_status_code (boards.tests.HomeTests) ... ok + +---------------------------------------------------------------------- +Ran 2 tests in 0.017s + +OK +Destroying test database for alias 'default' ('file:memorydb_default?mode=memory&cache=shared')... +``` + +详细程度决定了将要打印到控制台的通知和调试信息量; 0 是无输出,1 是正常输出,2 是详细输出。 + +##### 静态文件设置 + +静态文件是指 CSS,JavaScript,字体,图像或者是我们用来组成用户界面的任何其他资源。 + +事实上,Django 不提供这些文件。但在开发过程中,我们又会用到,因此 Django 提供了一些功能来帮助我们管理静态文件。这些功能可在配置文件(settings.py)中 `INSTALLED_APPS` 里的 **django.contrib.staticfiles** 。 + +有了这么多的前端组件库,我们没有理由继续渲染基本的 HTML 。我们可以轻松地将Bootstrap 4 添加到我们的项目中。Bootstrap 是一个用 HTML,CSS 和JavaScript 开发的开源工具包。 + +在项目根目录中,除**boards**,**templates** 和 **myproject** 文件夹外,我们还需要创建一个名为 **static** 的文件夹,并在 **static** 文件夹内创建另一个名为 **css** 文件夹: + +``` +myproject/ + |-- myproject/ + | |-- boards/ + | |-- myproject/ + | |-- templates/ + | |-- static/ <-- here + | | +-- css/ <-- and here + | +-- manage.py + +-- venv/ +``` + +到 [getbootstrap.com](https://getbootstrap.com/docs/4.0/getting-started/download/#compiled-css-and-js) 下载最新版本: + +![Bootstrap下载](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/bootstrap-download.png) + +下载 **Compiled CSS and JS** 的版本。 + +解压从 Bootstrap 网站下载的 **bootstrap-4.0.0-beta-dist.zip** 文件,将文件 **css / bootstrap.min.css** 复制到我们项目的css文件夹中: + +``` +myproject/ + |-- myproject/ + | |-- boards/ + | |-- myproject/ + | |-- templates/ + | |-- static/ + | | +-- css/ + | | +-- bootstrap.min.css <-- here + | +-- manage.py + +-- venv/ +``` + +还是一样的问题,我们需要将 Django 中的 **settings.py** 里配置一下静态文件的目录。在 `STATIC_URL` 添加以下内容: + +``` +STATIC_URL = '/static/' + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static'), +] +``` + + +这里可以回忆一下,`TEMPLATES` 配置目录的路径,操作是差不多的。 + + +现在我们必须在模板中加载静态文件(Bootstrap CSS文件): + +> **templates/home.html** + +``` +{% load static %} + + + + Boards + + + + + + +``` + + + +首先,我们在 html 的开头加载静态文件:`{% load static %}` + + +`{% static %}` 是用于告诉资源文件存在的路径,在这是,`{% static 'css/bootstrap.min.css' %}` 就会返回 **/static/css/bootstrap.min.css** ,相当于 **http://127.0.0.1:8000/static/css/bootstrap.min.css** + + +这个 `{% static %}` 标签将会和 **settings.py** 的 `STATIC_URL` 组成最终的 URL。怎么理解这句话呢? + +例如,我们在静态文件托管在 **https://static.example.com/** ,然后我们设置了这个属性:`STATIC_URL=https://static.example.com/`,然后 `{% static 'css/bootstrap.min.css' %}` 返回的是 :**https://static.example.com/css/bootstrap.min.css**。 + + +如果还不能理解,放心,你现在只需要了解和记住相关的过程就行了,后面正式开发上线的时候,会继续开展这部分的内容。 + + +刷新页面 **127.0.0.1:8000** 我们可以看到它是这个样子的: + +![Boards主页Bootstrap](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/boards-homepage-bootstrap.png) + +现在我们可以编辑模板,以利用Bootstrap CSS: + +现在我们可以利用 Bootstrap CSS 来编辑我们的模板页面了: + + + +``` +{% load static %} + + + + Boards + + + +
+ + + + + + + + + + + + {% for board in boards %} + + + + + + + {% endfor %} + +
BoardPostsTopicsLast Post
+ {{ board.name }} + {{ board.description }} + 00
+
+ + +``` + + + +修改后变成这样子: + +![Boards主页Bootstrap](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/boards-homepage-bootstrap-2.png) + + +到目前为止,我们使用交互式控制台(`python manage.py shell`)添加新的版块(board)。但是这样很不方便,因此我们需要一个更好的方式来做这个。在下一节中,我们将为网站管理员实施一个管理界面来管理它。 + +* * * + +#### Django Admin简介 + +当我们开始一个新项目时,Django 在 `INSTALLED_APPS` 中已经配置了 **Django Admin** 。 + +![Django Admin漫画](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/Pixton_Comic_Django_Admin.png) + +Django Admin 的一个很好的用例就是,在博客中,它可以被作者用来编写和发布文章。另一个例子是电子商务网站,工作人员可以创建,编辑,删除产品。 + +目前,我们将配置 Django Admin 来维护我们的应用程序的版块模块。 + +我们首先创建一个管理员帐户: + +``` +python manage.py createsuperuser +``` + +按照说明操作: + +``` +Username (leave blank to use 'vitorfs'): admin +Email address: admin@example.com +Password: +Password (again): +Superuser created successfully. +``` + +现在在浏览器中打开 URL:**http://127.0.0.1:8000/admin/** + +![Django管理员登录](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/django-admin-login.png) + +输入 **用户名** 和 **密码** : + +![Django Admin](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/django-admin.png) + + +在这里,它已经配置了一些功能,我们也可以添加**用户**和**组**来管理权限。 + + +那么我们如何在这个管理后台中管理版块(Board)里面的内容呢? + +其实很简单,在 **board** 目录下,**admin.py** 中添加以下代码: + + +> **boards/admin.py** + +``` +from django.contrib import admin +from .models import Board + +admin.site.register(Board) +``` + + +保存以下,然后刷新网页: + +![Django管理委员会](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/django-admin-boards.png) + +点击 **Boards** 链接就能查看现有版块列表: + +![Django管理委员会名单](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/django-admin-boards-list.png) + +我们可以通过点击 **Add Board** 按钮添加一个新的版块: + +![Django管理委员会添加](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/django-admin-boards-add.png) + +点击 **SAVE** 按钮: + +![Django管理委员会名单](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/django-admin-boards-list-2.png) + +我们可以检查一切是否正常,打开 **http://127.0.0.1:8000** URL: + +![董事会主页](https://simpleisbetterthancomplex.com/media/series/beginners-guide/1.11/part-2/boards-homepage-bootstrap-3.png) + +* * * + +#### 结论 + +在本教程中,我们探讨了许多新概念。我们为我们的项目定义了一些要求,创建了第一个模型,迁移了数据库,开始玩 Models API。我们创建了第一个视图并编写了一些单元测试。我们还配置了 Django 模板引擎,静态文件,并将 Bootstrap 4 库添加到项目中。最后,我们简要介绍了 Django Admin 界面。 + + +该项目的源代码在 GitHub 上,你可以在下面的链接中找到本章节的代码: + +[https://github.com/sibtc/django-beginners-guide/tree/v0.2-lw](https://github.com/sibtc/django-beginners-guide/tree/v0.2-lw) \ No newline at end of file diff --git "a/Article/supplement/Python\345\205\263\351\224\256\345\255\227yield.md" "b/Article/supplement/Python\345\205\263\351\224\256\345\255\227yield.md" new file mode 100644 index 00000000..60353d25 --- /dev/null +++ "b/Article/supplement/Python\345\205\263\351\224\256\345\255\227yield.md" @@ -0,0 +1,279 @@ +> 原文:http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained +> +> 注:这是一篇 stackoverflow 上一个火爆帖子的译文 + +## 问题 ## + +Python 关键字 yield 的作用是什么?用来干什么的? + +比如,我正在试图理解下面的代码: + +```Python +def node._get_child_candidates(self, distance, min_dist, max_dist): + if self._leftchild and distance - max_dist < self._median: + yield self._leftchild + if self._rightchild and distance + max_dist >= self._median: + yield self._rightchild +``` + + +下面的是调用: + + +```python +result, candidates = list(), [self] +while candidates: + node = candidates.pop() + distance = node._get_dist(obj) + if distance <= max_dist and distance >= min_dist: + result.extend(node._values) + candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) +return result +``` + +当调用 ```_get_child_candidates``` 的时候发生了什么?返回了一个列表?返回了一个元素?被重复调用了么? 什么时候这个调用结束呢? + + +## 回答 + +为了理解什么是 yield ,你必须理解什么是生成器。在理解生成器之前,让我们先走近迭代。 + +**可迭代对象** + +当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象: + +```Python +>>> mylist = [1, 2, 3] +>>> for i in mylist : +... print(i) +1 +2 +3 +``` + +mylist 是一个可迭代的对象。当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代的对象: + +```python +>>> mylist = [x*x for x in range(3)] +>>> for i in mylist : +... print(i) +0 +1 +4 +``` + +所有你可以使用 ```for .. in ..``` 语法的叫做一个迭代器:列表,字符串,文件……你经常使用它们是因为你可以如你所愿的读取其中的元素,但是你把所有的值都存储到了内存中,如果你有大量数据的话这个方式并不是你想要的。 + +**生成器** + +生成器是可以迭代的,但是你 只可以读取它一次 ,因为它并不把所有的值放在内存中,它是实时地生成数据: + +```python +>>> mygenerator = (x*x for x in range(3)) +>>> for i in mygenerator : +... print(i) +0 +1 +4 +``` + +看起来除了把 [] 换成 () 外没什么不同。但是,你不可以再次使用 ```for i in mygenerator``` , 因为生成器只能被迭代一次:先计算出0,然后继续计算1,然后计算4,一个跟一个的… + +**yield 关键字** + +yield 是一个类似 return 的关键字,只是这个函数返回的是个生成器。 + +```python +>>> def createGenerator() : +... mylist = range(3) +... for i in mylist : +... yield i*i +... +>>> mygenerator = createGenerator() # create a generator +>>> print(mygenerator) # mygenerator is an object! + +>>> for i in mygenerator: +... print(i) +0 +1 +4 +``` + +这个例子没什么用途,但是它让你知道,这个函数会返回一大批你只需要读一次的值. + +为了精通 yield ,你必须要理解:当你调用这个函数的时候,函数内部的代码并不立马执行 ,这个函数只是返回一个生成器对象,这有点蹊跷不是吗。 + +那么,函数内的代码什么时候执行呢?当你使用for进行迭代的时候. + +现在到了关键点了! + +第一次迭代中你的函数会执行,从开始到达 yield 关键字,然后返回 yield 后的值作为第一次迭代的返回值. 然后,每次执行这个函数都会继续执行你在函数内部定义的那个循环的下一次,再返回那个值,直到没有可以返回的。 + +如果生成器内部没有定义 yield 关键字,那么这个生成器被认为成空的。这种情况可能因为是循环进行没了,或者是没有满足 if/else 条件。 + +**回到你的代码** + +生成器: + +```Python +# Here you create the method of the node object that will return the generator +def node._get_child_candidates(self, distance, min_dist, max_dist): + + # Here is the code that will be called each time you use the generator object : + + # If there is still a child of the node object on its left + # AND if distance is ok, return the next child + if self._leftchild and distance - max_dist < self._median: + yield self._leftchild + + # If there is still a child of the node object on its right + # AND if distance is ok, return the next child + if self._rightchild and distance + max_dist >= self._median: + yield self._rightchild + + # If the function arrives here, the generator will be considered empty + # there is no more than two values : the left and the right children +``` + + +调用者: + +```Python +# Create an empty list and a list with the current object reference +result, candidates = list(), [self] + +# Loop on candidates (they contain only one element at the beginning) +while candidates: + + # Get the last candidate and remove it from the list + node = candidates.pop() + + # Get the distance between obj and the candidate + distance = node._get_dist(obj) + + # If distance is ok, then you can fill the result + if distance <= max_dist and distance >= min_dist: + result.extend(node._values) + + # Add the children of the candidate in the candidates list + # so the loop will keep running until it will have looked + # at all the children of the children of the children, etc. of the candidate + candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) + +return result +``` + +这个代码包含了几个小部分: + +* 我们对一个列表进行迭代,但是迭代中列表还在不断的扩展。它是一个迭代这些嵌套的数据的简洁方式,即使这样有点危险,因为可能导致无限迭代。 `candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))` 穷尽了生成器的所有值,但 while 不断地在产生新的生成器,它们会产生和上一次不一样的值,既然没有作用到同一个节点上. +* `extend()` 是一个迭代器方法,作用于迭代器,并把参数追加到迭代器的后面。 + + +通常我们传给它一个列表参数: + + +```Python +>>> a = [1, 2] +>>> b = [3, 4] +>>> a.extend(b) +>>> print(a) +[1, 2, 3, 4] +``` + + +但是在你的代码中的是一个生成器,这是不错的,因为: + +* 你不必读两次所有的值 +* 你可以有很多子对象,但不必叫他们都存储在内存里面。 + + +并且这很奏效,因为 Python 不关心一个方法的参数是不是个列表。Python 只希望它是个可以迭代的,所以这个参数可以是列表,元组,字符串,生成器... 这叫做 `duck typing`,这也是为何 Python 如此棒的原因之一,但这已经是另外一个问题了... + +你可以在这里停下,来看看生成器的一些高级用法: + +**控制生成器的穷尽** + +```Python +>>> class Bank(): # let's create a bank, building ATMs +... crisis = False +... def create_atm(self) : +... while not self.crisis : +... yield "$100" +>>> hsbc = Bank() # when everything's ok the ATM gives you as much as you want +>>> corner_street_atm = hsbc.create_atm() +>>> print(corner_street_atm.next()) +$100 +>>> print(corner_street_atm.next()) +$100 +>>> print([corner_street_atm.next() for cash in range(5)]) +['$100', '$100', '$100', '$100', '$100'] +>>> hsbc.crisis = True # crisis is coming, no more money! +>>> print(corner_street_atm.next()) + +>>> wall_street_atm = hsbc.create_atm() # it's even true for new ATMs +>>> print(wall_street_atm.next()) + +>>> hsbc.crisis = False # trouble is, even post-crisis the ATM remains empty +>>> print(corner_street_atm.next()) + +>>> brand_new_atm = hsbc.create_atm() # build a new one to get back in business +>>> for cash in brand_new_atm : +... print cash +$100 +$100 +$100 +$100 +$100 +$100 +$100 +$100 +$100 +... +``` + + +对于控制一些资源的访问来说这很有用。 + +**Itertools,你最好的朋友** + +itertools 包含了很多特殊的迭代方法。是不是曾想过复制一个迭代器?串联两个迭代器?把嵌套的列表分组?不用创造一个新的列表的 zip/map? + +只要 import itertools + +需要个例子?让我们看看比赛中4匹马可能到达终点的先后顺序的可能情况: + +```python +>>> horses = [1, 2, 3, 4] +>>> races = itertools.permutations(horses) +>>> print(races) + +>>> print(list(itertools.permutations(horses))) +[(1, 2, 3, 4), + (1, 2, 4, 3), + (1, 3, 2, 4), + (1, 3, 4, 2), + (1, 4, 2, 3), + (1, 4, 3, 2), + (2, 1, 3, 4), + (2, 1, 4, 3), + (2, 3, 1, 4), + (2, 3, 4, 1), + (2, 4, 1, 3), + (2, 4, 3, 1), + (3, 1, 2, 4), + (3, 1, 4, 2), + (3, 2, 1, 4), + (3, 2, 4, 1), + (3, 4, 1, 2), + (3, 4, 2, 1), + (4, 1, 2, 3), + (4, 1, 3, 2), + (4, 2, 1, 3), + (4, 2, 3, 1), + (4, 3, 1, 2), + (4, 3, 2, 1)] +``` + +**了解迭代器的内部机理** + +迭代是一个实现可迭代对象(实现的是 `__iter__()` 方法)和迭代器(实现的是 `__next__()` 方法)的过程。可迭代对象是你可以从其获取到一个迭代器的任一对象。迭代器是那些允许你迭代可迭代对象的对象。 diff --git a/Code/Python10Code/.idea/Python10Code.iml b/Code/Python10Code/.idea/Python10Code.iml deleted file mode 100644 index d8e9a180..00000000 --- a/Code/Python10Code/.idea/Python10Code.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python10Code/.idea/inspectionProfiles/profiles_settings.xml b/Code/Python10Code/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index c23ecacb..00000000 --- a/Code/Python10Code/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python10Code/.idea/misc.xml b/Code/Python10Code/.idea/misc.xml deleted file mode 100644 index dac3415e..00000000 --- a/Code/Python10Code/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python10Code/.idea/modules.xml b/Code/Python10Code/.idea/modules.xml deleted file mode 100644 index f89682dd..00000000 --- a/Code/Python10Code/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Code/Python10Code/.idea/workspace.xml b/Code/Python10Code/.idea/workspace.xml deleted file mode 100644 index 54385401..00000000 --- a/Code/Python10Code/.idea/workspace.xml +++ /dev/null @@ -1,606 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1501589773782 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python10Code/com/__init__.py b/Code/Python10Code/com/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python10Code/com/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python10Code/com/twowater/__init__.py b/Code/Python10Code/com/twowater/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python10Code/com/twowater/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python10Code/com/twowater/mtest1.py b/Code/Python10Code/com/twowater/mtest1.py deleted file mode 100644 index 92809822..00000000 --- a/Code/Python10Code/com/twowater/mtest1.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User(object): - def __init__(self, name, age): - self.name = name; - self.age = age; - -user=User('两点水',23) diff --git a/Code/Python10Code/com/twowater/mtest10.py b/Code/Python10Code/com/twowater/mtest10.py deleted file mode 100644 index e64448f6..00000000 --- a/Code/Python10Code/com/twowater/mtest10.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class Number(object): - def __init__(self, value): - self.value = value - - def __eq__(self, other): - print('__eq__') - return self.value == other.value - - def __ne__(self, other): - print('__ne__') - return self.value != other.value - - def __lt__(self, other): - print('__lt__') - return self.value < other.value - - def __gt__(self, other): - print('__gt__') - return self.value > other.value - - def __le__(self, other): - print('__le__') - return self.value <= other.value - - def __ge__(self, other): - print('__ge__') - return self.value >= other.value - - -if __name__ == '__main__': - num1 = Number(2) - num2 = Number(3) - print('num1 == num2 ? --------> {} \n'.format(num1 == num2)) - print('num1 != num2 ? --------> {} \n'.format(num1 == num2)) - print('num1 < num2 ? --------> {} \n'.format(num1 < num2)) - print('num1 > num2 ? --------> {} \n'.format(num1 > num2)) - print('num1 <= num2 ? --------> {} \n'.format(num1 <= num2)) - print('num1 >= num2 ? --------> {} \n'.format(num1 >= num2)) diff --git a/Code/Python10Code/com/twowater/mtest2.py b/Code/Python10Code/com/twowater/mtest2.py deleted file mode 100644 index 0252fa25..00000000 --- a/Code/Python10Code/com/twowater/mtest2.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User(object): - def __new__(cls, *args, **kwargs): - # 打印 __new__方法中的相关信息 - print('调用了 def __new__ 方法') - print(args) - # 最后返回父类的方法 - return super(User, cls).__new__(cls) - - def __init__(self, name, age): - print('调用了 def __init__ 方法') - self.name = name - self.age = age - - -if __name__ == '__main__': - usr = User('两点水', 23) diff --git a/Code/Python10Code/com/twowater/mtest3.py b/Code/Python10Code/com/twowater/mtest3.py deleted file mode 100644 index 41cc0763..00000000 --- a/Code/Python10Code/com/twowater/mtest3.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User(object): - - name='' - - def __setattr__(self, name, value): - # 每一次属性赋值时, __setattr__都会被调用,因此不断调用自身导致无限递归了 - # 会造成程序奔溃 - self.name = value - - -if __name__ == '__main__': - user = User() - user.name='两点水' diff --git a/Code/Python10Code/com/twowater/mtest4.py b/Code/Python10Code/com/twowater/mtest4.py deleted file mode 100644 index 5ef4e444..00000000 --- a/Code/Python10Code/com/twowater/mtest4.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User(object): - def __getattr__(self, name): - print('调用了 __getattr__ 方法') - return super(User, self).__getattr__(name) - - def __setattr__(self, name, value): - print('调用了 __setattr__ 方法') - return super(User, self).__setattr__(name, value) - - def __delattr__(self, name): - print('调用了 __delattr__ 方法') - return super(User, self).__delattr__(name) - - def __getattribute__(self, name): - print('调用了 __getattribute__ 方法') - return super(User, self).__getattribute__(name) - - -if __name__ == '__main__': - user = User() - # 设置属性值,会调用 __setattr__ - user.attr1 = True - # 属性存在,只有__getattribute__调用 - user.attr1 - try: - # 属性不存在, 先调用__getattribute__, 后调用__getattr__ - user.attr2 - except AttributeError: - pass - # __delattr__调用 - del user.attr1 diff --git a/Code/Python10Code/com/twowater/mtest5.py b/Code/Python10Code/com/twowater/mtest5.py deleted file mode 100644 index 8437539b..00000000 --- a/Code/Python10Code/com/twowater/mtest5.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User(object): - pass - - -if __name__ == '__main__': - print(dir(User())) diff --git a/Code/Python10Code/com/twowater/mtest6.py b/Code/Python10Code/com/twowater/mtest6.py deleted file mode 100644 index eb3d0200..00000000 --- a/Code/Python10Code/com/twowater/mtest6.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User(object): - def __init__(self, name='两点水', sex='男'): - self.sex = sex - self.name = name - - def __get__(self, obj, objtype): - print('获取 name 值') - return self.name - - def __set__(self, obj, val): - print('设置 name 值') - self.name = val - - -class MyClass(object): - x = User('两点水', '男') - y = 5 - - -if __name__ == '__main__': - m = MyClass() - print(m.x) - - print('\n') - - m.x = '三点水' - print(m.x) - - print('\n') - - print(m.x) - - print('\n') - - print(m.y) diff --git a/Code/Python10Code/com/twowater/mtest7.py b/Code/Python10Code/com/twowater/mtest7.py deleted file mode 100644 index fcb46428..00000000 --- a/Code/Python10Code/com/twowater/mtest7.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - - -class Meter(object): - def __init__(self, value=0.0): - self.value = float(value) - - def __get__(self, instance, owner): - return self.value - - def __set__(self, instance, value): - self.value = float(value) - - -class Foot(object): - def __get__(self, instance, owner): - return instance.meter * 3.2808 - - def __set__(self, instance, value): - instance.meter = float(value) / 3.2808 - - -class Distance(object): - meter = Meter() - foot = Foot() - - -if __name__ == '__main__': - d = Distance() - print(d.meter, d.foot) - d.meter = 1 - print(d.meter, d.foot) - d.meter = 2 - print(d.meter, d.foot) diff --git a/Code/Python10Code/com/twowater/mtest8.py b/Code/Python10Code/com/twowater/mtest8.py deleted file mode 100644 index 0ce96767..00000000 --- a/Code/Python10Code/com/twowater/mtest8.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class FunctionalList: - ''' 实现了内置类型list的功能,并丰富了一些其他方法: head, tail, init, last, drop, take ''' - - def __init__(self, values=None): - if values is None: - self.values = [] - else: - self.values = values - - def __len__(self): - return len(self.values) - - def __getitem__(self, key): - return self.values[key] - - def __setitem__(self, key, value): - self.values[key] = value - - def __delitem__(self, key): - del self.values[key] - - def __iter__(self): - return iter(self.values) - - def __reversed__(self): - return FunctionalList(reversed(self.values)) - - def append(self, value): - self.values.append(value) - - def head(self): - # 获取第一个元素 - return self.values[0] - - def tail(self): - # 获取第一个元素之后的所有元素 - return self.values[1:] - - def init(self): - # 获取最后一个元素之前的所有元素 - return self.values[:-1] - - def last(self): - # 获取最后一个元素 - return self.values[-1] - - def drop(self, n): - # 获取所有元素,除了前N个 - return self.values[n:] - - def take(self, n): - # 获取前N个元素 - return self.values[:n] diff --git a/Code/Python10Code/com/twowater/mtest9.py b/Code/Python10Code/com/twowater/mtest9.py deleted file mode 100644 index b40443d3..00000000 --- a/Code/Python10Code/com/twowater/mtest9.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class FunctionalList: - ''' 实现了内置类型list的功能,并丰富了一些其他方法: head, tail, init, last, drop, take''' - - def __init__(self, values=None): - if values is None: - self.values = [] - else: - self.values = values - - def __len__(self): - return len(self.values) - - def __getitem__(self, key): - return self.values[key] - - def __setitem__(self, key, value): - self.values[key] = value - - def __delitem__(self, key): - del self.values[key] - - def __iter__(self): - return iter(self.values) - - def __reversed__(self): - return FunctionalList(reversed(self.values)) - - def append(self, value): - self.values.append(value) - - def head(self): - # 获取第一个元素 - return self.values[0] - - def tail(self): - # 获取第一个元素之后的所有元素 - return self.values[1:] - - def init(self): - # 获取最后一个元素之前的所有元素 - return self.values[:-1] - - def last(self): - # 获取最后一个元素 - return self.values[-1] - - def drop(self, n): - # 获取所有元素,除了前N个 - return self.values[n:] - - def take(self, n): - # 获取前N个元素 - return self.values[:n] diff --git a/Code/Python11Code/.idea/Python11Code.iml b/Code/Python11Code/.idea/Python11Code.iml deleted file mode 100644 index 67116063..00000000 --- a/Code/Python11Code/.idea/Python11Code.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python11Code/.idea/inspectionProfiles/profiles_settings.xml b/Code/Python11Code/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index c23ecacb..00000000 --- a/Code/Python11Code/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python11Code/.idea/misc.xml b/Code/Python11Code/.idea/misc.xml deleted file mode 100644 index dac3415e..00000000 --- a/Code/Python11Code/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python11Code/.idea/modules.xml b/Code/Python11Code/.idea/modules.xml deleted file mode 100644 index b47c9865..00000000 --- a/Code/Python11Code/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Code/Python11Code/.idea/workspace.xml b/Code/Python11Code/.idea/workspace.xml deleted file mode 100644 index d4b50b89..00000000 --- a/Code/Python11Code/.idea/workspace.xml +++ /dev/null @@ -1,513 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1503024519578 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python11Code/com/__init__.py b/Code/Python11Code/com/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python11Code/com/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python11Code/com/twowater/__init__.py b/Code/Python11Code/com/twowater/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python11Code/com/twowater/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python11Code/com/twowater/mtest1.py b/Code/Python11Code/com/twowater/mtest1.py deleted file mode 100644 index ed390b02..00000000 --- a/Code/Python11Code/com/twowater/mtest1.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -from enum import Enum - -Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) - -# 遍历枚举类型 -for name, member in Month.__members__.items(): - print(name, '---------', member, '----------', member.value) - -# 直接引用一个常量 -print('\n', Month.Jan) diff --git a/Code/Python11Code/com/twowater/mtest2.py b/Code/Python11Code/com/twowater/mtest2.py deleted file mode 100644 index 84bf5aff..00000000 --- a/Code/Python11Code/com/twowater/mtest2.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -from enum import Enum, unique - -Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) - - -# @unique 装饰器可以帮助我们检查保证没有重复值 -@unique -class Month(Enum): - Jan = 'January' - Feb = 'February' - Mar = 'March' - Apr = 'April' - May = 'May' - Jun = 'June' - Jul = 'July' - Aug = 'August' - Sep = 'September ' - Oct = 'October' - Nov = 'November' - Dec = 'December' - - -if __name__ == '__main__': - print(Month.Jan, '----------', - Month.Jan.name, '----------', Month.Jan.value) - for name, member in Month.__members__.items(): - print(name, '----------', member, '----------', member.value) diff --git a/Code/Python11Code/com/twowater/mtest3.py b/Code/Python11Code/com/twowater/mtest3.py deleted file mode 100644 index e57024bc..00000000 --- a/Code/Python11Code/com/twowater/mtest3.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -from enum import Enum - - -class User(Enum): - Twowater = 98 - Liangdianshui = 30 - Tom = 12 - - -Twowater = User.Twowater -Liangdianshui = User.Liangdianshui - -print(Twowater == Liangdianshui, Twowater == User.Twowater) -print(Twowater is Liangdianshui, Twowater is User.Twowater) - -try: - print('\n'.join(' ' + s.name for s in sorted(User))) -except TypeError as err: - print(' Error : {}'.format(err)) diff --git a/Code/Python11Code/com/twowater/mtest4.py b/Code/Python11Code/com/twowater/mtest4.py deleted file mode 100644 index 6ff64bfb..00000000 --- a/Code/Python11Code/com/twowater/mtest4.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- -import enum - - -class User(enum.IntEnum): - Twowater = 98 - Liangdianshui = 30 - Tom = 12 - - -try: - print('\n'.join(s.name for s in sorted(User))) -except TypeError as err: - print(' Error : {}'.format(err)) diff --git a/Code/Python14Code/.idea/Python14Code.iml b/Code/Python14Code/.idea/Python14Code.iml deleted file mode 100644 index 67116063..00000000 --- a/Code/Python14Code/.idea/Python14Code.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python14Code/.idea/inspectionProfiles/profiles_settings.xml b/Code/Python14Code/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index c23ecacb..00000000 --- a/Code/Python14Code/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python14Code/.idea/misc.xml b/Code/Python14Code/.idea/misc.xml deleted file mode 100644 index dac3415e..00000000 --- a/Code/Python14Code/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python14Code/.idea/modules.xml b/Code/Python14Code/.idea/modules.xml deleted file mode 100644 index 462b3272..00000000 --- a/Code/Python14Code/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Code/Python14Code/.idea/workspace.xml b/Code/Python14Code/.idea/workspace.xml deleted file mode 100644 index 7a31079b..00000000 --- a/Code/Python14Code/.idea/workspace.xml +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1513907070570 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python14Code/com/__init__.py b/Code/Python14Code/com/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python14Code/com/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python14Code/com/twowater/__init__.py b/Code/Python14Code/com/twowater/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python14Code/com/twowater/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python14Code/com/twowater/test1.py b/Code/Python14Code/com/twowater/test1.py deleted file mode 100644 index dcf8a2fe..00000000 --- a/Code/Python14Code/com/twowater/test1.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import re - -# 设定一个常量 -a = '两点水|twowater|liangdianshui|草根程序员|ReadingWithU' - -# 判断是否有 “两点水” 这个字符串,使用 PY 自带函数 - -print('a 是否含有“两点水”这个字符串:{0}'.format(a.index('两点水') > -1)) -print('a 是否含有“两点水”这个字符串:{0}'.format('两点水' in a)) - -# 正则表达式 - -findall = re.findall('两点水', a) -print(findall) - -if len(findall) > 0: - print('a 含有“两点水”这个字符串') -else: - print('a 不含有“两点水”这个字符串') - -# 选择 a 里面的所有小写英文字母 - -re_findall = re.findall('[a-z]', a) - -print(re_findall) diff --git a/Code/Python14Code/com/twowater/test2.py b/Code/Python14Code/com/twowater/test2.py deleted file mode 100644 index 04160837..00000000 --- a/Code/Python14Code/com/twowater/test2.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import re - -a = 'uav,ubv,ucv,uwv,uzv,ucv,uov' - -# 字符集 - -# 取 u 和 v 中间是 a 或 b 或 c 的字符 -findall = re.findall('u[abc]v', a) -print(findall) -# 如果是连续的字母,数字可以使用 - 来代替 -l = re.findall('u[a-c]v', a) -print(l) - -# 取 u 和 v 中间不是 a 或 b 或 c 的字符 -re_findall = re.findall('u[^abc]v', a) -print(re_findall) diff --git a/Code/Python14Code/com/twowater/test3.py b/Code/Python14Code/com/twowater/test3.py deleted file mode 100644 index bbae7e0d..00000000 --- a/Code/Python14Code/com/twowater/test3.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import re - -a = 'uav_ubv_ucv_uwv_uzv_ucv_uov&123-456-789' - -# 概括字符集 - -# \d 相当于 [0-9] ,匹配所有数字字符 -# \D 相当于 [^0-9] , 匹配所有非数字字符 -findall1 = re.findall('\d', a) -findall2 = re.findall('[0-9]', a) -findall3 = re.findall('\D', a) -findall4 = re.findall('[^0-9]', a) -print(findall1) -print(findall2) -print(findall3) -print(findall4) - -# \w 匹配包括下划线的任何单词字符,等价于 [A-Za-z0-9_] -findall5 = re.findall('\w', a) -findall6 = re.findall('[A-Za-z0-9_]', a) -print(findall5) -print(findall6) diff --git a/Code/Python14Code/com/twowater/test4.py b/Code/Python14Code/com/twowater/test4.py deleted file mode 100644 index b234f3e8..00000000 --- a/Code/Python14Code/com/twowater/test4.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import re - -a = 'java*&39android##@@python' - -# 数量词 - -findall = re.findall('[a-z]{4,7}', a) -print(findall) - -# 贪婪与非贪婪 - -re_findall = re.findall('[a-z]{4,7}?', a) -print(re_findall) diff --git a/Code/Python14Code/com/twowater/test5.py b/Code/Python14Code/com/twowater/test5.py deleted file mode 100644 index 9a700110..00000000 --- a/Code/Python14Code/com/twowater/test5.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import re - -a = '347073565' - -# 边界匹配符 - -findall = re.findall('\d{6}565$', a) - -print(findall) diff --git a/Code/Python14Code/com/twowater/test6.py b/Code/Python14Code/com/twowater/test6.py deleted file mode 100644 index 57967fe2..00000000 --- a/Code/Python14Code/com/twowater/test6.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import re - -a = 'pythonpythonpython' - -# 组 - -findall = re.findall('(python){3}', a) -print(findall) - - diff --git a/Code/Python14Code/com/twowater/test7.py b/Code/Python14Code/com/twowater/test7.py deleted file mode 100644 index a973ec5d..00000000 --- a/Code/Python14Code/com/twowater/test7.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -import re - -a = 'Python*Android*Java-888' - -# 把字符串中的 * 字符替换成 & 字符 -sub1 = re.sub('\*', '&', a) -print(sub1) - -# 把字符串中的第一个 * 字符替换成 & 字符 -sub2 = re.sub('\*', '&', a, 1) -print(sub2) - - -# 把字符串中的 * 字符替换成 & 字符,把字符 - 换成 | - -# 1、先定义一个函数 -def convert(value): - group = value.group() - if (group == '*'): - return '&' - elif (group == '-'): - return '|' - - -# 第二个参数,要替换的字符可以为一个函数 -sub3 = re.sub('[\*-]', convert, a) -print(sub3) diff --git a/Code/Python14Code/com/twowater/test8.py b/Code/Python14Code/com/twowater/test8.py deleted file mode 100644 index 8dddad19..00000000 --- a/Code/Python14Code/com/twowater/test8.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -# 提取图片的地址 - -import re - -a = '' - -# 使用 re.search -search = re.search('', a) -# group(0) 是一个完整的分组 -print(search.group(0)) -print(search.group(1)) - -# 使用 re.findall -findall = re.findall('', a) -print(findall) - -# 多个分组的使用(比如我们需要提取 img 字段和图片地址字段) -re_search = re.search('<(.*) src="http://github.com/(.*)">', a) -# 打印 img -print(re_search.group(1)) -# 打印图片地址 -print(re_search.group(2)) -# 打印 img 和图片地址,以元祖的形式 -print(re_search.group(1, 2)) -# 或者使用 groups -print(re_search.groups()) diff --git a/Code/Python8Code/.idea/Python8Code.iml b/Code/Python8Code/.idea/Python8Code.iml deleted file mode 100644 index 67116063..00000000 --- a/Code/Python8Code/.idea/Python8Code.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python8Code/.idea/inspectionProfiles/profiles_settings.xml b/Code/Python8Code/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index c23ecacb..00000000 --- a/Code/Python8Code/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python8Code/.idea/misc.xml b/Code/Python8Code/.idea/misc.xml deleted file mode 100644 index dac3415e..00000000 --- a/Code/Python8Code/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python8Code/.idea/modules.xml b/Code/Python8Code/.idea/modules.xml deleted file mode 100644 index de5ca319..00000000 --- a/Code/Python8Code/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Code/Python8Code/.idea/workspace.xml b/Code/Python8Code/.idea/workspace.xml deleted file mode 100644 index 69dcbd38..00000000 --- a/Code/Python8Code/.idea/workspace.xml +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1499686684711 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python8Code/com/Learn/__init__.py b/Code/Python8Code/com/Learn/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python8Code/com/Learn/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python8Code/com/Learn/module/__init__.py b/Code/Python8Code/com/Learn/module/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python8Code/com/Learn/module/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python8Code/com/Learn/module/nameattributes/__init__.py b/Code/Python8Code/com/Learn/module/nameattributes/__init__.py deleted file mode 100644 index 24ba15a5..00000000 --- a/Code/Python8Code/com/Learn/module/nameattributes/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python8Code/com/Learn/module/nameattributes/__pycache__/lname.cpython-36.pyc b/Code/Python8Code/com/Learn/module/nameattributes/__pycache__/lname.cpython-36.pyc deleted file mode 100644 index baf0bfc4..00000000 Binary files a/Code/Python8Code/com/Learn/module/nameattributes/__pycache__/lname.cpython-36.pyc and /dev/null differ diff --git a/Code/Python8Code/com/Learn/module/nameattributes/lname.py b/Code/Python8Code/com/Learn/module/nameattributes/lname.py deleted file mode 100644 index 3ae7751e..00000000 --- a/Code/Python8Code/com/Learn/module/nameattributes/lname.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -if __name__ =='__main__' : - print('main') -else : - print('not main') diff --git a/Code/Python8Code/com/Learn/module/nameattributes/user_lname.py b/Code/Python8Code/com/Learn/module/nameattributes/user_lname.py deleted file mode 100644 index 50909273..00000000 --- a/Code/Python8Code/com/Learn/module/nameattributes/user_lname.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -import lname - - diff --git a/Code/Python8Code/com/Learn/module/privateattributes/__init__.py b/Code/Python8Code/com/Learn/module/privateattributes/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python8Code/com/Learn/module/privateattributes/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python8Code/com/Learn/module/privateattributes/vip_user.py b/Code/Python8Code/com/Learn/module/privateattributes/vip_user.py deleted file mode 100644 index 79768a69..00000000 --- a/Code/Python8Code/com/Learn/module/privateattributes/vip_user.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -def _diamond_vip(lv): - print('尊敬的钻石会员用户,您好') - vip_name = 'DiamondVIP' + str(lv) - return vip_name - - -def _gold_vip(lv): - print('尊敬的黄金会员用户,您好') - vip_name = 'GoldVIP' + str(lv) - return vip_name - - -def vip_lv_name(lv): - if lv == 1: - print(_gold_vip(lv)) - elif lv == 2: - print(_diamond_vip(lv)) - - -vip_lv_name(2) diff --git a/Code/Python8Code/com/Learn/module/sys/__init__.py b/Code/Python8Code/com/Learn/module/sys/__init__.py deleted file mode 100644 index 24ba15a5..00000000 --- a/Code/Python8Code/com/Learn/module/sys/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python8Code/com/Learn/module/sys/test_sys.py b/Code/Python8Code/com/Learn/module/sys/test_sys.py deleted file mode 100644 index e95a571f..00000000 --- a/Code/Python8Code/com/Learn/module/sys/test_sys.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -import sys - -print(sys.path) \ No newline at end of file diff --git a/Code/Python8Code/com/__init__.py b/Code/Python8Code/com/__init__.py deleted file mode 100644 index d7df38cb..00000000 --- a/Code/Python8Code/com/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python9Code/.idea/Python9Code.iml b/Code/Python9Code/.idea/Python9Code.iml deleted file mode 100644 index 67116063..00000000 --- a/Code/Python9Code/.idea/Python9Code.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python9Code/.idea/inspectionProfiles/profiles_settings.xml b/Code/Python9Code/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index c23ecacb..00000000 --- a/Code/Python9Code/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python9Code/.idea/misc.xml b/Code/Python9Code/.idea/misc.xml deleted file mode 100644 index dac3415e..00000000 --- a/Code/Python9Code/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Code/Python9Code/.idea/modules.xml b/Code/Python9Code/.idea/modules.xml deleted file mode 100644 index 0a15fc17..00000000 --- a/Code/Python9Code/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Code/Python9Code/.idea/workspace.xml b/Code/Python9Code/.idea/workspace.xml deleted file mode 100644 index 5177d29c..00000000 --- a/Code/Python9Code/.idea/workspace.xml +++ /dev/null @@ -1,680 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - DEFINITION_ORDER - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1500999902927 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Python9Code/com/__init__.py b/Code/Python9Code/com/__init__.py deleted file mode 100644 index 24ba15a5..00000000 --- a/Code/Python9Code/com/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python9Code/com/twowater/__init__.py b/Code/Python9Code/com/twowater/__init__.py deleted file mode 100644 index 24ba15a5..00000000 --- a/Code/Python9Code/com/twowater/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- \ No newline at end of file diff --git a/Code/Python9Code/com/twowater/mtest0.py b/Code/Python9Code/com/twowater/mtest0.py deleted file mode 100644 index 6d91e42d..00000000 --- a/Code/Python9Code/com/twowater/mtest0.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class Test: - def prt(self): - print(self) - print(self.__class__) - -t = Test() -t.prt() \ No newline at end of file diff --git a/Code/Python9Code/com/twowater/mtest1.py b/Code/Python9Code/com/twowater/mtest1.py deleted file mode 100644 index 2330058d..00000000 --- a/Code/Python9Code/com/twowater/mtest1.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -# 旧式类 -class OldClass: - def __init__(self, account, name): - self.account = account; - self.name = name; - - -# 新式类 -class NewClass(object): - def __init__(self, account, name): - self.account = account; - self.name = name; - - -if __name__ == '__main__': - old_class = OldClass(111111, 'OldClass') - print(old_class) - print(type(old_class)) - print(dir(old_class)) - print('\n') - new_class=NewClass(222222,'NewClass') - print(new_class) - print(type(new_class)) - print(dir(new_class)) diff --git a/Code/Python9Code/com/twowater/mtest2.py b/Code/Python9Code/com/twowater/mtest2.py deleted file mode 100644 index b320ac3a..00000000 --- a/Code/Python9Code/com/twowater/mtest2.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -class UserInfo(object): - name = '两点水' - - -class UserInfo(object): - def __init__(self, name): - self.name = name - - -class UserInfo(object): - def __init__(self, name, age, account): - self.name = name - self._age = age - self.__account = account diff --git a/Code/Python9Code/com/twowater/mtest3.py b/Code/Python9Code/com/twowater/mtest3.py deleted file mode 100644 index 5ae7048f..00000000 --- a/Code/Python9Code/com/twowater/mtest3.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -class UserInfo(object): - def __init__(self, name, age, account): - self.name = name - self._age = age - self.__account = account - - def get_account(self): - return self.__account - - -if __name__ == '__main__': - userInfo = UserInfo('两点水', 23, 347073565); - # 打印所有属性 - print(dir(userInfo)) - # 打印构造函数中的属性 - print(userInfo.__dict__) - print(userInfo.get_account()) - # 用于验证双下划线是否是真正的私有属性 - print(userInfo._UserInfo__account) diff --git a/Code/Python9Code/com/twowater/mtest4.py b/Code/Python9Code/com/twowater/mtest4.py deleted file mode 100644 index d7d0d497..00000000 --- a/Code/Python9Code/com/twowater/mtest4.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -class User(object): - def upgrade(self): - pass - - def _buy_equipment(self): - pass - - def __pk(self): - pass - diff --git a/Code/Python9Code/com/twowater/mtest5.py b/Code/Python9Code/com/twowater/mtest5.py deleted file mode 100644 index 75736fb3..00000000 --- a/Code/Python9Code/com/twowater/mtest5.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -class UserInfo(object): - lv = 5 - - def __init__(self, name, age, account): - self.name = name - self._age = age - self.__account = account - - def get_account(self): - return self.__account - - @classmethod - def get_name(cls): - return cls.lv - - @property - def get_age(self): - return self._age - - -if __name__ == '__main__': - userInfo = UserInfo('两点水', 23, 347073565); - # 打印所有属性 - print(dir(userInfo)) - # 打印构造函数中的属性 - print(userInfo.__dict__) - # 直接使用类名类调用,而不是某个对象 - print(UserInfo.lv) - # 像访问属性一样调用方法(注意看get_age是没有括号的) - print(userInfo.get_age) diff --git a/Code/Python9Code/com/twowater/mtest6.py b/Code/Python9Code/com/twowater/mtest6.py deleted file mode 100644 index 12474fa6..00000000 --- a/Code/Python9Code/com/twowater/mtest6.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class UserInfo(object): - lv = 5 - - def __init__(self, name, age, account): - self.name = name - self._age = age - self.__account = account - - def get_account(self): - return self.__account - - @classmethod - def get_name(cls): - return cls.lv - - @property - def get_age(self): - return self._age - - -class UserInfo2(UserInfo): - def __init__(self, name, age, account, sex): - super(UserInfo2, self).__init__(name, age, account) - self.sex = sex; - - -if __name__ == '__main__': - userInfo2 = UserInfo2('两点水', 23, 347073565, '男'); - # 打印所有属性 - print(dir(userInfo2)) - # 打印构造函数中的属性 - print(userInfo2.__dict__) - print(UserInfo2.get_name()) diff --git a/Code/Python9Code/com/twowater/mtest7.py b/Code/Python9Code/com/twowater/mtest7.py deleted file mode 100644 index 9d6b56a6..00000000 --- a/Code/Python9Code/com/twowater/mtest7.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -class UserInfo(object): - lv = 5 - - def __init__(self, name, age, account): - self.name = name - self._age = age - self.__account = account - - def get_account(self): - return self.__account - - -class UserInfo2(UserInfo): - pass - - -if __name__ == '__main__': - userInfo2 = UserInfo2('两点水', 23, 347073565); - print(userInfo2.get_account()) - diff --git a/Code/Python9Code/com/twowater/mtest8.py b/Code/Python9Code/com/twowater/mtest8.py deleted file mode 100644 index 1289281e..00000000 --- a/Code/Python9Code/com/twowater/mtest8.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User1(object): - pass - - -class User2(User1): - pass - - -class User3(User2): - pass - - -if __name__ == '__main__': - user1 = User1() - user2 = User2() - user3 = User3() - # isinstance()就可以告诉我们,一个对象是否是某种类型 - print(isinstance(user3, User2)) - print(isinstance(user3, User1)) - print(isinstance(user3, User3)) - # 基本类型也可以用isinstance()判断 - print(isinstance('两点水', str)) - print(isinstance(347073565, int)) - print(isinstance(347073565, str)) diff --git a/Code/Python9Code/com/twowater/mtest9.py b/Code/Python9Code/com/twowater/mtest9.py deleted file mode 100644 index f84240b9..00000000 --- a/Code/Python9Code/com/twowater/mtest9.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class User(object): - def __init__(self, name): - self.name = name - - def printUser(self): - print('Hello !' + self.name) - - -class UserVip(User): - def printUser(self): - print('Hello ! 尊敬的Vip用户:' + self.name) - - -class UserGeneral(User): - def printUser(self): - print('Hello ! 尊敬的用户:' + self.name) - - -def printUserInfo(user): - user.printUser() - - -if __name__ == '__main__': - userVip = UserVip('两点水') - printUserInfo(userVip) - userGeneral = UserGeneral('水水水') - printUserInfo(userGeneral) diff --git a/README.md b/README.md index c21b03b7..6053629b 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,169 @@ -# Python +IT 行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰,但是,我们要清楚:淘汰的永远只是那些初级水平的从业者,过硬技术的从业者永远都是稀缺的。因此对于学习,我们还是要踏踏实实的。 -草根学 Python 是基于 Python 3.6 写的 Python 入门系列教程,为了更好的阅读,把它整理在 [GitBook](https://www.readwithu.com/) 上了,希望对 Python 入门者有帮助。 -注:如果 [GitBook](https://www.readwithu.com/) 访问慢,也可以到个人博客查阅:[草根学 Python](http://twowater.com.cn/categories/Python/%E8%8D%89%E6%A0%B9%E5%AD%A6-Python/) +自学 Python ,也是一样,不要一开始因为头脑发热就不停地收藏各种资料网站,购买各种书籍,下载了大量的教学视频,过了几天,学习的热情开始褪去,再过几个星期,终于完成了学习课程 —— 《从入门到放弃》。所以,学习 Python 需要一步一个脚印,踏踏实实地学。 + + + +# FQ + +在讲 Python 如何入门之前,个人建议最好每个人都有自己的 FQ 工具,多使用 Google 搜索,多去看一下墙外的世界,多看 Github 上的开源项目。 + +至于如何 FQ ,这里提供一下我用过的工具:[FQ工具集](/Res/FQ.md) + + + +# Python 学习资源集 + +相信很多人学习某门编程语言的时候,都会找各种学习资料。说句实话,资料太多,反而没用,根据自己的学习习惯,个人能力选择一门资源坚持学就好了。 + +因为每个人的需求不同,这里整理了一批 Python 比较好的学习资料: + +* [Python 博客网站资源](/Res/Python博客网站资源.md) + +还有一些有趣的网站: + +* [一个可以看执行过程的网站](http://www.pythontutor.com/visualize.html#mode=edit) + + + +# Python 入门 + +对于入门,主要是掌握基本的语法和熟悉编程规范,因此大部分的教程基本一致的,所以还是建议选好适合自己的一个教程,坚持学下去。 + +在 Python 入门中,本人编写了一系列的 《草根学 Python 》 文章, 是基于 Python 3.6 写的 Python 入门系列教程,为了更好的阅读,把它整理在 [GitBook](https://www.readwithu.com/) 上,希望对各位入门 Python 有所帮助。 + +>注:2018 年 02 月 27 日,基础知识入门部分已经完成了的。因近期读者反映有些图片没法打开了(之前图片放在七牛云,用的是临时链接,最近七牛云把这个给关闭了,导致图片没法打开),且自己对之前的内容有些不满意,决定在 2019 年 7 月 7 日开始进行了再次修改。但这里做个说明,因为之前写的时候用的是 windows 电脑,现在用 mac ,所以有些例子是 windows 的截图,有些是 mac 的截图,不要觉得奇怪。 **主要目录如下:** -* [Python代码规范](/codeSpecification/codeSpecification_Preface.md) - - [简明概述](/codeSpecification/codeSpecification_first.md) - - [注释](/codeSpecification/codeSpecification_second.md) - - [命名规范](/codeSpecification/codeSpecification_third.md) -* [第一个Python程序](/python1/Preface.md) - - [Python 简介](/python1/Introduction.md) - - [Python 的安装](/python1/Installation.md) - - [第一个 Python 程序](/python1/The_first_procedure.md) - - [集成开发环境(IDE): PyCharm](/python1/IDE.md) -* [基本数据类型和变量](/python2/Preface.md) - - [Python 语法的简要说明](/python2/Grammar.md) - - [Python 的基本数据类型](/python2/Type_of_data.md) - - [基本数据类型转换](/python2/Type_conversion.md) - - [Python 中的变量](/python2/Variable.md) -* [List 和 Tuple](/python3/Preface.md) - - [List(列表)](/python3/List.md) - - [tuple(元组)](/python3/tuple.md) -* [ Dict 和 Set](/python4/Preface.md) - - [字典(Dictionary)](/python4/Dict.md) - - [set](/python4/Set.md) -* [条件语句和循环语句](/python5/Preface.md) - - [条件语句](/python5/If.md) - - [循环语句](/python5/Cycle.md) - - [条件语句和循环语句综合实例](/python5/Example.md) -* [函数](/python6/Preface.md) - - [Python 自定义函数的基本步骤](/python6/1.md) - - [函数传值问题](/python6/2.md) - - [函数返回值](/python6/3.md) - - [函数的参数](/python6/4.md) - - [匿名函数](/python6/5.md) -* [迭代器和生成器](/python7/Preface.md) - - [迭代](/python7/1.md) - - [Python 迭代器](/python7/2.md) - - [lsit 生成式(列表生成式)](/python7/3.md) - - [生成器](/python7/4.md) - - [迭代器和生成器综合例子](/python7/5.md) -* [模块与包](/python8/Preface.md) - - [Python 模块简介](/python8/1.md) - - [模块的使用](/python8/2.md) - - [主模块和非主模块](/python8/3.md) - - [包](/python8/4.md) - - [作用域](/python8/5.md) -* [面向对象](/python9/Preface.md) - - [面向对象的概念](/python9/1.md) - - [类](/python9/2.md) - - [类的属性](/python9/3.md) - - [类的方法](/python9/4.md) - - [类的继承](/python9/5.md) - - [类的多态](/python9/6.md) -* [Python 的 Magic Method](/python10/Preface.md) - - [Python 的 Magic Method](/python10/1.md) - - [构造(`__new__`)和初始化(`__init__`)](/python10/2.md) - - [属性的访问控制](/python10/3.md) - - [对象的描述器](/python10/4.md) - - [自定义容器(Container)](/python10/5.md) - - [运算符相关的魔术方法](/python10/6.md) -* [枚举类](/python11/Preface.md) - - [枚举类的使用](/python11/1.md) - - [Enum 的源码](/python11/2.md) - - [自定义类型的枚举](/python11/3.md) - - [枚举的比较](/python11/4.md) -* [元类](/python12/Preface.md) - - [Python 中类也是对象](/python12/1.md) - - [使用 `type()` 动态创建类](/python12/2.md) - - [什么是元类](/python12/3.md) - - [自定义元类](/python12/4.md) - - [使用元类](/python12/5.md) -* [线程与进程](/python13/Preface.md) - - [线程与进程](/python13/1.md) - - [多线程编程](/python13/2.md) - - [进程](/python13/3.md) -* [一步一步了解正则表达式](/python14/Preface.md) - - [初识 Python 正则表达式](/python14/1.md) - - [字符集](/python14/2.md) - - [数量词](/python14/3.md) - - [边界匹配符和组](/python14/4.md) - - [re.sub](/python14/5.md) - - [re.match 和 re.search](/python14/6.md) -* [闭包](/python15/1.md) -* [装饰器](/python16/1.md) +* [为什么学Python?](/Article/PythonBasis/python0/WhyStudyPython.md) +* [Python代码规范](/Article/codeSpecification/codeSpecification_Preface.md) + - [简明概述](/Article/codeSpecification/codeSpecification_first.md) + - [注释](/Article/codeSpecification/codeSpecification_second.md) + - [命名规范](/Article/codeSpecification/codeSpecification_third.md) +* [第一个Python程序](/Article/PythonBasis/python1/Preface.md) + - [Python 简介](/Article/PythonBasis/python1/Introduction.md) + - [Python 的安装](/Article/PythonBasis/python1/Installation.md) + - [第一个 Python 程序](/Article/PythonBasis/python1/The_first_procedure.md) + - [集成开发环境(IDE): PyCharm](/Article/PythonBasis/python1/IDE.md) +* [基本数据类型和变量](/Article/PythonBasis/python2/Preface.md) + - [Python 语法的简要说明](/Article/PythonBasis/python2/Grammar.md) + - [print() 函数](/Article/PythonBasis/python2/print.md) + - [Python 的基本数据类型](/Article/PythonBasis/python2/Type_of_data.md) + - [字符串的编码问题](/Article/PythonBasis/python2/StringCoding.md) + - [基本数据类型转换](/Article/PythonBasis/python2/Type_conversion.md) + - [Python 中的变量](/Article/PythonBasis/python2/Variable.md) +* [List 和 Tuple](/Article/PythonBasis/python3/Preface.md) + - [List(列表)](/Article/PythonBasis/python3/List.md) + - [tuple(元组)](/Article/PythonBasis/python3/tuple.md) +* [ Dict 和 Set](/Article/PythonBasis/python4/Preface.md) + - [字典(Dictionary)](/Article/PythonBasis/python4/Dict.md) + - [set](/Article/PythonBasis/python4/Set.md) +* [条件语句和循环语句](/Article/PythonBasis/python5/Preface.md) + - [条件语句](/Article/PythonBasis/python5/If.md) + - [循环语句](/Article/PythonBasis/python5/Cycle.md) + - [条件语句和循环语句综合实例](/Article/PythonBasis/python5/Example.md) +* [函数](/Article/PythonBasis/python6/Preface.md) + - [Python 自定义函数的基本步骤](/Article/PythonBasis/python6/1.md) + - [函数返回值](/Article/PythonBasis/python6/2.md) + - [函数的参数](/Article/PythonBasis/python6/3.md) + - [函数传值问题](/Article/PythonBasis/python6/4.md) + - [匿名函数](/Article/PythonBasis/python6/5.md) +* [迭代器和生成器](/Article/PythonBasis/python7/Preface.md) + - [迭代](/Article/PythonBasis/python7/1.md) + - [Python 迭代器](/Article/PythonBasis/python7/2.md) + - [list 生成式(列表生成式)](/Article/PythonBasis/python7/3.md) + - [生成器](/Article/PythonBasis/python7/4.md) + - [迭代器和生成器综合例子](/Article/PythonBasis/python7/5.md) +* [面向对象](/Article/PythonBasis/python8/Preface.md) + - [面向对象的概念](/Article/PythonBasis/python8/1.md) + - [类的定义和调用](/Article/PythonBasis/python8/2.md) + - [类方法](/Article/PythonBasis/python8/3.md) + - [修改和增加类属性](/Article/PythonBasis/python8/4.md) + - [类和对象](/Article/PythonBasis/python8/5.md) + - [初始化函数](/Article/PythonBasis/python8/6.md) + - [类的继承](/Article/PythonBasis/python8/7.md) + - [类的多态](/Article/PythonBasis/python8/8.md) + - [类的访问控制](/Article/PythonBasis/python8/9.md) +* [模块与包](/Article/PythonBasis/python9/Preface.md) + - [Python 模块简介](/Article/PythonBasis/python9/1.md) + - [模块的使用](/Article/PythonBasis/python9/2.md) + - [主模块和非主模块](/Article/PythonBasis/python9/3.md) + - [包](/Article/PythonBasis/python9/4.md) + - [作用域](/Article/PythonBasis/python9/5.md) +* [Python 的 Magic Method](/Article/PythonBasis/python10/Preface.md) + - [Python 的 Magic Method](/Article/PythonBasis/python10/1.md) + - [构造(`__new__`)和初始化(`__init__`)](/Article/PythonBasis/python10/2.md) + - [属性的访问控制](/Article/PythonBasis/python10/3.md) + - [对象的描述器](/Article/PythonBasis/python10/4.md) + - [自定义容器(Container)](/Article/PythonBasis/python10/5.md) + - [运算符相关的魔术方法](/Article/PythonBasis/python10/6.md) +* [枚举类](/Article/python11/PythonBasis/Preface.md) + - [枚举类的使用](/Article/PythonBasis/python11/1.md) + - [Enum 的源码](/Article/PythonBasis/python11/2.md) + - [自定义类型的枚举](/Article/PythonBasis/python11/3.md) + - [枚举的比较](/Article/PythonBasis/python11/4.md) +* [元类](/Article/PythonBasis/python12/Preface.md) + - [Python 中类也是对象](/Article/PythonBasis/python12/1.md) + - [使用 `type()` 动态创建类](/Article/PythonBasis/python12/2.md) + - [什么是元类](/Article/PythonBasis/python12/3.md) + - [自定义元类](/Article/PythonBasis/python12/4.md) + - [使用元类](/Article/PythonBasis/python12/5.md) +* [线程与进程](/Article/PythonBasis/python13/Preface.md) + - [线程与进程](/Article/PythonBasis/python13/1.md) + - [多线程编程](/Article/PythonBasis/python13/2.md) + - [进程](/Article/PythonBasis/python13/3.md) +* [一步一步了解正则表达式](/Article/PythonBasis/python14/Preface.md) + - [初识 Python 正则表达式](/Article/PythonBasis/python14/1.md) + - [字符集](/Article/PythonBasis/python14/2.md) + - [数量词](/Article/PythonBasis/python14/3.md) + - [边界匹配符和组](/Article/PythonBasis/python14/4.md) + - [re.sub](/Article/PythonBasis/python14/5.md) + - [re.match 和 re.search](/Article/PythonBasis/python14/6.md) +* [闭包](/Article/PythonBasis/python15/1.md) +* [装饰器](/Article/PythonBasis/python16/1.md) + + + + +# 知识点补漏 +* [Python 关键字 yield](/Article/supplement/Python关键字yield.md) + + + +# Python 进阶 + +* [使用Python虚拟环境](/Article/advanced/使用Python虚拟环境.md) +* [Mac中使用virtualenv和virtualenvwrapper](/Article/advanced/Mac中使用virtualenv和virtualenvwrapper.md) + + + + +# HTML 和 CSS 入门 + + +# JavaScript 入门 + + + +# Django + +Python 下有许多款不同的 Web 框架。Django 是重量级选手中最有代表性的一位。许多成功的网站和 APP 都基于 Django。 + +如果对自己的基础有点信息的童鞋,可以尝试通过国外的 [Django 博客从搭建到部署系列教程](https://simpleisbetterthancomplex.com/series/2017/09/04/a-complete-beginners-guide-to-django-part-1.html) 进行入门,这个教程讲的非常的详细,而且还有很多有趣的配图。不过可能因为墙的原因,很多人会访问不到,就算访问到了,也因为是英语的,不会进行耐心的阅读学习。因此我打算翻译这个教程。 + +* [一个完整的初学者指南Django-part1](/Article/django/一个完整的初学者指南Django-part1.md) +* [一个完整的初学者指南Django-part2](/Article/django/一个完整的初学者指南Django-part2.md) + + +持续更新.... + + +可以关注我的公众号,实时了解更新情况。 + + + + + + diff --git a/Res/FQ.md b/Res/FQ.md new file mode 100644 index 00000000..24cb613a --- /dev/null +++ b/Res/FQ.md @@ -0,0 +1,28 @@ + +# FQ + + +* **蓝灯** + + 简单粗暴,下载安装即可用,每月免费 5g ,也可以 购买专业版,一年两百多。其实如果不用来看视频,够用的了。 + + 传送门: [蓝灯官方论坛](https://github.com/getlantern/forum) ,[蓝灯镜像下载地址](http://s3.amazonaws.com/urtuz53txrmk9/index.html) + + +* **XX-Net** + + 基于 Google 免费的云服务搭建,这里有个矛盾就 是:搭建前你得 FQ。也就是说,我要下载 FQ 软件,可是 下载这个 FQ 软件就要 FQ 。 + + 所以这里你可以先用蓝灯 FQ 后,再搭建这个 + + 传送门:[官方中文文档](https://github.com/XX-net/XX-Net/wiki/%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3),[基于 Chrome 浏览器的搭建步骤](https://github.com/XX-net/XX-Net/wiki/%E4%BD%BF%E7%94%A8Chrome%E6%B5%8F%E8%A7%88%E5%99%A8) + + +* **自己搭建 ssr** + + 当然,最好的还是自己能搭建 ss/ssr 服务器,这里有个适合初学者的教程。 + + 传送门:[教程地址](../Res/自己搭建ss:ssr服务器.md) + + + diff --git "a/Res/Python\345\215\232\345\256\242\347\275\221\347\253\231\350\265\204\346\272\220.md" "b/Res/Python\345\215\232\345\256\242\347\275\221\347\253\231\350\265\204\346\272\220.md" new file mode 100644 index 00000000..de1e8026 --- /dev/null +++ "b/Res/Python\345\215\232\345\256\242\347\275\221\347\253\231\350\265\204\346\272\220.md" @@ -0,0 +1,47 @@ +# Python 博客网站资源 + + +* **本人编写的 Python 系列文章** + + 本草根编写的 Python 文章,里面有各种例子代码 + + 传送门: [Gitbook](https://www.readwithu.com/),[github](https://github.com/TwoWater/Python) + +* **Python 在线手册** + + Python 在线手册站,收集整理了大量 Python 流行技术文档和教程。更多时候我们用来查询 Api 。 + + 传送门:[官方地址](http://docs.pythontab.com) + + +* **Python轻松入门** + + 网易云课程,Python 轻松入门 + + 传送门: [官方地址](https://study.163.com/course/introduction.htm?courseId=1003655001&utm_campaign=share&utm_content=courseIntro&utm_medium=iphoneShare&utm_source=weixing) + + +* **廖雪峰 Python 教程** + + 最最最经典的 Python 入门文章。 + + 传送门:[官方地址](http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000) + + +* **Python 基础教程** + + 详细的记录 Python 各个知识点的用法讲解,很适合小白入门。 + + 传送门:[官方地址](http://www.runoob.com/python/python-tutorial.html) + + +* **莫烦Python** + + + 传送门:[官方地址](https://morvanzhou.github.io/tutorials/python-basic/) + +* **The Hitchhiker’s Guide to Python** + + 传送门:[官方地址](http://docs.python-guide.org/en/latest/) + + diff --git "a/Res/\350\207\252\345\267\261\346\220\255\345\273\272ss:ssr\346\234\215\345\212\241\345\231\250.md" "b/Res/\350\207\252\345\267\261\346\220\255\345\273\272ss:ssr\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 00000000..efb5e017 --- /dev/null +++ "b/Res/\350\207\252\345\267\261\346\220\255\345\273\272ss:ssr\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,293 @@ +# 客户端下载 + +第一次电脑系统使用SSR/SS客户端时,需要安装NET Framework 4.0,不然无法正常使用,[微软官网下载](https://www.microsoft.com/zh-cn/download/details.aspx?id=17718)。 + +NET Framework 4.0是SSR/SS的运行库,没有这个SSR/SS客户端无法正常运行。有的电脑系统可能会自带NET Framework 4.0。 + +* Windows SSR客户端 [下载地址](https://github.com/shadowsocksr-backup/shadowsocksr-csharp/releases) [备用下载地址](https://nofile.io/f/6Jm7WJCyOVv/ShadowsocksR-4.7.0-win.7z) + +* MAC SSR客户端 [下载地址](https://github.com/shadowsocksr-backup/ShadowsocksX-NG/releases) [备用下载地址](https://nofile.io/f/jgMWFwCBonU#ab0d3c3b6ac54482) + +* Linux客户端一键安装配置 [使用脚本](https://github.com/the0demiurge/CharlesScripts/blob/master/charles/bin/ssr) (使用方法见注释) 或者采用图形界面的[linux ssr客户端](https://github.com/erguotou520/electron-ssr/releases) + +* 安卓 SSR客户端 [下载地址](https://github.com/shadowsocksr-backup/shadowsocksr-android/releases) [备用下载地址](https://nofile.io/f/rvTJoj0h5GC/shadowsocksr-release.apk) + +* 苹果手机SSR客户端:Potatso Lite、Potatso、shadowrocket都可以作为SSR客户端,但这些软件目前已经在国内的app商店下架,可以用美区的appid账号来下载。但是,如果你配置的SSR账号兼容SS客户端,或者协议选择origin且混淆选择plain,那么你可以选择苹果SS客户端软件(即协议和混淆可以不填),APP商店里面有很多,比如:openwingy、superwingy、bestwingy、wingy+、greatwingy等。 + +**有了客户端后我们需要自己搭建服务器创建ss/ssr账号才能翻墙。提供ss/ssr免费账号 有需求的人可以使用。** + +# 搭建教程 + +### 为什么不怕被封ip?因为vultr可以随时删除和创建服务器,新服务器就是新的ip,所以不怕被封ip。 + + +**教程很简单,整个教程分三步:** + +第一步:购买VPS服务器 + +第二步:一键部署VPS服务器 + +第三步:一键加速VPS服务器 (谷歌BBR加速,推荐) + +* * * + +**第一步:购买VPS服务器** + +VPS服务器需要选择国外的,首选国际知名的vultr,速度不错、稳定且性价比高,按小时计费,能够随时开通和删除服务器,新服务器即是新ip。 + +vultr注册地址: [http://www.vultr.com/?ref=7048874](http://www.vultr.com/?ref=7048874) (全球15个服务器位置可选,KVM框架,最低2.5美元/月) + +[![img](https://camo.githubusercontent.com/e5b4fc7834baffafe9883ac40cc7f296e62f9741/68747470733a2f2f7777772e76756c74722e636f6d2f6d656469612f62616e6e65725f322e706e67)](https://www.vultr.com/?ref=7048874) + +虽然是英文界面,但是现在的浏览器都有网页翻译功能,鼠标点击右键,选择网页翻译即可翻译成中文。 + +注册并邮件激活账号,充值后即可购买服务器。充值方式是paypal(首选)或支付宝,使用paypal有银行卡(包括信用卡)即可。paypal注册地址:[https://www.paypal.com](https://www.paypal.com/) (paypal是国际知名的第三方支付服务商,注册一下账号,绑定银行卡即可购买国外商品) + +2.5美元/月的服务器配置信息:单核 512M内存 20G SSD硬盘 带宽峰值100M 500G流量/月 + +5美元/月的服务器配置信息: 单核 1G内存 25G SSD硬盘 带宽峰值100M 1000G流量/月 + +10美元/月的服务器配置信息: 单核 2G内存 40G SSD硬盘 带宽峰值100M 2000G流量/月 + +20美元/月的服务器配置信息: 2cpu 4G内存 60G SSD硬盘 带宽峰值100M 3000G流量/月 + +40美元/月的服务器配置信息: 4cpu 8G内存 100G SSD硬盘 带宽峰值100M 4000G流量/月 + +**vultr实际上是折算成小时来计费的,比如服务器是5美元1个月,那么每小时收费为5/30/24=0.0069美元 会自动从账号中扣费,只要保证账号有钱即可。如果你部署的服务器实测后速度不理想,你可以把它删掉(destroy),重新换个地区的服务器来部署,方便且实用。因为新的服务器就是新的ip,所以当ip被墙时这个方法很有用。当ip被墙时,为了保证新开的服务器ip和原先的ip不一样,先开新服务器,开好后再删除旧服务器即可。** + +计费从你开通服务器开始算的,不管你有没有使用,即使服务器处于关机状态仍然会计费,如果你没有开通服务器就不算。比如你今天早上开通了服务器,但你有事情,晚上才部署,那么这段时间是会计费的。同理,如果你早上删掉服务器,第二天才开通新的服务器,那么这段时间是不会计费的。在账号的Billing选项里可以看到账户余额。 + +温馨提醒:同样的服务器位置,不同的宽带类型和地区所搭建的账号的翻墙速度会不同,这与中国电信、中国联通、中国移动国际出口带宽和线路不同有关,所以以实测为准。可以先选定一个服务器位置来按照教程进行搭建,熟悉搭建方法,当账号搭建完成并进行了bbr加速后,测试下速度自己是否满意,如果满意那就用这个服务器位置的服务器。如果速度不太满意,就一次性开几台不同的服务器位置的服务器,然后按照同样的方法来进行搭建并测试,选择最优的,之后把其它的服务器删掉,按小时计费测试成本可以忽略。 + +如图: + +[![img](https://raw.githubusercontent.com/Alvin9999/pac2/master/pp100.png)](https://raw.githubusercontent.com/Alvin9999/pac2/master/pp100.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/pac2/master/pp101.png)](https://raw.githubusercontent.com/Alvin9999/pac2/master/pp101.png) + +**vps服务器系统推荐选择CentOS 6.X64位的系统(系统版本不要选centos7!centos7默认的防火墙会阻止ssr的正常连接!)。完成购买后,找到系统的密码记下来,部署服务器时需要用到。** + +如图: +[![img](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B01.png)](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B01.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B02.png)](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B02.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B04.png)](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B04.png) + +**不要选centos7系统!点击图中的CentOS几个字,会弹出centos6,然后选中centos6!entos7默认的防火墙可能会干扰ssr的正常连接!** + +> 接下来这一步是开启vps的ipv6 ip,选填项。如果你的电脑系统可以用ipv6,那么可以勾选此项。大多数用户没有这个需求,但有一些用户可能会用到,所以补充了这部分内容。 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/ssripv6-01.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/ssripv6-01.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B05.png)](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B05.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B06.png)](https://raw.githubusercontent.com/Alvin9999/crp_up/master/pac%E6%95%99%E7%A8%8B06.png) + +> 如果你开启了vps的ipv6,那么在后台的settings选项可以找到服务器的ipv6 ip。在部署SSR账号时,你用ipv6 ip就行。整个部署及使用过程中,记得把电脑系统开启ipv6喔。 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/ssripv6-02.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/ssripv6-02.png) + +* * * + +**第二步:部署VPS服务器** + +购买服务器后,需要部署一下。因为你买的是虚拟东西,而且又远在国外,我们需要一个叫Xshell的软件来远程部署。Xshell windows版下载地址: + +[国外云盘1下载](http://45.32.141.248:8000/f/d91974d046/) + +[国外云盘2下载](https://nofile.io/f/eb5dUzYMQK4/Xshell_setup_wm.exe) 提取密码:666 + +[国外云盘3下载](https://www.adrive.com/public/NdK3Ez/Xshell_setup_wm.exe) 密码:123 + +如果你是苹果电脑操作系统,更简单,无需下载xshell,系统可以直接连接VPS。打开**终端**(Terminal),输入ssh root@ip 其中“ip”替换成你VPS的ip, 按回车键,然后复制粘贴密码,按回车键即可登录。粘贴密码时有可能不显示密码,但不影响, [参考设置方法](http://www.cnblogs.com/ghj1976/archive/2013/04/19/3030159.html) 如果不能用MAC自带的终端连接的话,直接网上搜“MAC连接SSH的软件”,有很多,然后通过软件来连接vps服务器就行,具体操作方式参考windows xshell。 + +* * * + +部署教程: + +下载xshell软件并安装后,打开软件 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell11.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell11.png) + +选择文件,新建 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell12.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell12.png) + +随便取个名字,然后把你的服务器ip填上 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell13.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell13.png) + +连接国外ip即服务器时,软件会先后提醒你输入用户名和密码,用户名linux系统默认都是root,密码是购买服务器后的cent系统的密码。 + +**如果开好了服务器,发现xshell死活连不上,多半是开的服务器ip被墙了,遇到这种情况,把服务器删掉,重新开个新的服务器即可,可以是同地区的也可以选择其它地区。** + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell14.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/xshell14.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/xshell2.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/xshell2.png) + +连接成功后,会出现如上图所示,之后就可以复制粘贴代码部署了。 + +CentOS6/Debian6/Ubuntu14 ShadowsocksR一键部署管理脚本: + +* * * + +yum -y install wget + +wget -N –no-check-certificate [https://softs.fun/Bash/ssr.sh](https://softs.fun/Bash/ssr.sh) && chmod +x ssr.sh && bash ssr.sh + +备用脚本: + +yum -y install wget + +wget -N –no-check-certificate [https://raw.githubusercontent.com/ToyoDAdoubi/doubi/master/ssr.sh](https://raw.githubusercontent.com/ToyoDAdoubi/doubi/master/ssr.sh) && chmod +x ssr.sh && bash ssr.sh + +———————————————————代码分割线———————————————— + +复制上面的代码到VPS服务器里,按回车键,脚本会自动安装,以后只需要运行这个快捷命令就可以出现下图的界面进行设置,快捷管理命令为:bash ssr.sh + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/8.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/8.png) + +如上图出现管理界面后,**输入数字1来安装SSR服务端**。如果输入1后不能进入下一步,那么请退出xshell,重新连接vps服务器,然后输入快捷管理命令bash ssr.sh 再尝试。 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/31.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/31.png) + +根据上图提示,依次输入自己想设置的**端口和密码** (**密码建议用复杂点的字母组合,端口号为1-65535之间的数字**),回车键用于确认 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/32.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/32.png) + +如上图,选择想设置的**加密方式**,比如10,按回车键确认 + +接下来是选择**协议插件**,如下图: + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/11.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/11.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/41.PNG)](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/41.PNG) + +选择并确认后,会出现上图的界面,提示你是否选择兼容原版,这里的原版指的是SS客户端(SS客户端没有协议和混淆的选项),可以根据需求进行选择,演示选择y + +之后进行混淆插件的设置。 +**注意:有的地区需要把混淆设置成plain才好用。因为混淆不总是有效果,要看各地区的策略,有时候不混淆(plain)让其看起来像随机数据更好。(注意:tls 1.2_ticket_auth容易受到干扰!请选择除tls开头以外的其它混淆!!!)** + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/33.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/33.png) + +进行混淆插件的设置后,会依次提示你对设备数、单线程限速和端口总限速进行设置,默认值是不进行限制,个人使用的话,选择默认即可,即直接敲回车键。 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/14.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/14.png) + +之后代码就正式自动部署了,到下图所示的位置,提示你下载文件,输入:y + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/15.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/15.png) + +耐心等待一会,出现下面的界面即部署完成: + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/16.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/16.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/34.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/34.png) + +根据上图就可以看到自己设置的SSR账号信息,包括IP、端口、密码、加密方式、协议插件、混淆插件,这些信息需要填入你的SSR客户端。如果之后想修改账号信息,直接输入快捷管理命令:bash ssr.sh 进入管理界面,选择相应的数字来进行一键修改。例如: + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/22.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/22.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/23.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/23.png) + +**脚本演示结束。** + +此脚本是开机自动启动,部署一次即可。最后可以重启服务器确保部署生效(一般情况不重启也可以)。重启需要在命令栏里输入reboot ,输入命令后稍微等待一会服务器就会自动重启,一般重启过程需要2~5分钟,重启过程中Xshell会自动断开连接,等VPS重启好后才可以用Xshell软件进行连接。如果部署过程中卡在某个位置超过10分钟,可以用xshell软件断开,然后重新连接你的ip,再复制代码进行部署。 + +* * * + +**第三步:一键加速VPS服务器** + +此加速教程为谷歌BBR加速,Vultr的服务器框架可以装BBR加速,加速后对速度的提升很明显,所以推荐部署加速脚本。该加速方法是开机自动启动,部署一次就可以了。 + +按照第二步的步骤,连接服务器ip,登录成功后,在命令栏里粘贴以下代码: + +【谷歌BBR加速教程】 + +yum -y install wget + +wget –no-check-certificate [https://github.com/teddysun/across/raw/master/bbr.sh](https://github.com/teddysun/across/raw/master/bbr.sh) + +chmod +x bbr.sh + +./bbr.sh + +把上面整个代码复制后粘贴进去,不动的时候按回车,然后耐心等待,最后重启vps服务器即可。 + +演示开始,如图: + +复制并粘贴代码后,按回车键确认 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/18.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/18.png) + +如下图提示,按任意键继续部署 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/19.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/19.png) + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/20.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/20.png) + +部署到上图这个位置的时候,等待3~6分钟 + +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/21.png)](https://raw.githubusercontent.com/Alvin9999/PAC/master/ss/21.png) + +最后输入y重启服务器,如果输入y提示command not found ,接着输入reboot来重启服务器,确保加速生效,bbr加速脚本是开机自动启动,装一次就可以了。 + +* * * + +购买vps服务器后,ip有了,通过部署,端口、密码、加密方式、协议和混淆也有了,最后将这些信息填入SSR客户端就可以翻墙啦。 + +**有了账号后,打开SSR客户端,填上信息,这里以windows版的SSR客户端为例子**: +[![img](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/42.PNG)](https://raw.githubusercontent.com/Alvin9999/PAC/master/demo/42.PNG) + +在对应的位置,填上服务器ip、服务器端口、密码、加密方式、协议和混淆,最后将浏览器的代理设置为(http)127.0.0.1和1080即可。账号的端口号就是你自己设置的,而要上网的浏览器的端口号是1080,固定的,谷歌浏览器可以通过 SwitchyOmega 插件来设置。 + +启动SSR客户端后,右键SSR客户端图标,选择第一个“系统代理模式”,里面有3个子选项,选择”全局模式“,之后就可以用浏览器设置好了的代理模式(http)127.0.0.1和1080翻墙,此模式下所有的网站都会走SSR代理。(适合新手) + +[![ssr9000](https://user-images.githubusercontent.com/12132898/32225069-cfe6195a-be7e-11e7-99e0-e2fa98f93b1f.png)](https://user-images.githubusercontent.com/12132898/32225069-cfe6195a-be7e-11e7-99e0-e2fa98f93b1f.png) + +* * * + +**常见问题参考解决方法**: + +1、用了一段时间发现ssr账号用不了了 + +首先ping一下自己的ip,看看能不能ping的通,ping不通那么就是ip被墙了,ip被墙时,xshell也会连接不上服务器,遇到这种情况重新部署一个新的服务器,新的服务器就是新的ip。关于怎么ping ip的方法,可以自行网上搜索,或者用xshell软件连接服务器来判断,连不上即是被墙了。vultr开通和删除服务器非常方便,新服务器即新ip,大多数vps服务商都没有这样的服务,一般的vps服务商可能会提供免费更换1次ip的服务。 + +2、刚搭建好的ssr账号,ip能ping通,但是还是用不了 + +首选排除杀毒软件的干扰,尤其是国产杀毒软件,比如360安全卫生、360杀毒软件、腾讯管家、金山卫生等。这些东西很容易干扰翻墙上网,如果你的电脑安装了这样的东西,建议至少翻墙时别用,最好卸载。其次,检查下SSR信息是否填写正确。浏览器的代理方式是否是ssr代理,即(HTTP)127.0.0.1 和1080。如果以上条件都排除,还是用不了,那么可以更换端口、加密方式、协议、混淆,或者更换服务器位置。另外,如果你的vps服务器配置的是SSR账号,即有协议和混淆且没有兼容原版(SS版),那么你必须使用SSSR客户端来使用账号,因为SS客户端没有填写协议和混淆的选项。 + +3、有的地区需要把混淆参数设置成plain才好用。因为混淆不总是有效果,要看各地区的策略,有时候不混淆(plain)让其看起来像随机数据更好。 + +4、电脑能用但手机用不了 + +如果你的手机用的是SS客户端,SS客户端没有填协议和混淆的地方,如果你部署的协议和混淆的时候没有选择兼容原版(SS版),因此手机是用不了的。这个时候你把协议弄成兼容原版、混淆也设置成兼容原版即可。或者直接将协议设置成origin,混淆设置成plain。 + +5、vps的服务器操作系统不要用的太高,太高可能会因为系统的防火墙问题导致搭建的SSR账号连不上,如果你用的centos系统,建议用centos6,不要用centos7。如果你前面不小心装了centos7系统,那么只能重装系统或者重新部署新的vps服务器。 + +6、vultr服务商提供的vps服务器是单向流量计算,有的vps服务商是双向流量计算,单向流量计算对于用户来说更实惠。因为我们是在vps服务器上部署SSR服务端后,再用SSR客户端翻墙,所以SSR服务端就相当于中转,比如我们看一个视频,必然会产生流量,假如消耗流量80M,那么VPS服务器会产生上传80M和下载80M流量,vultr服务商只计算单向的80M流量。如果是双向计算流量,那么会计算为160M流量。 + +7、如果你想把搭建的账号给多人使用,不用额外设置端口,因为一个账号就可以多人使用。一般10美元的服务器可以同时支持100人在线使用。 + +如果想实现支持每个用户(端口)不同的加密方式/协议/混淆等,并且管理流量使用,可以参考多用户配置脚本:wget -N –no-check-certificate [https://softs.fun/Bash/ssrmu.sh](https://softs.fun/Bash/ssrmu.sh) && chmod +x ssrmu.sh && bash ssrmu.sh 备用脚本:wget -N –no-check-certificate [https://raw.githubusercontent.com/ToyoDAdoubi/doubi/master/ssrmu.sh](https://raw.githubusercontent.com/ToyoDAdoubi/doubi/master/ssrmu.sh) && chmod +x ssrmu.sh && bash ssrmu.sh 安装后管理命令为:bash ssrmu.sh +注意:这个多用户配置脚本和教程内容的脚本无法共存!要想用这个脚本,把之前的脚本卸载,输入管理命令bash ssr.sh ,选择3,卸载ShadowsocksR即可卸载原脚本。 + +8、vultr服务器每月有流量限制,超过限制后服务器不会被停止运行,但是超出的流量会被额外收费。北美和西欧地区的服务器超出流量后,多出的部分收费为0.01美元/G。新加坡和日本东京(日本)为0.025美元/G,悉尼(澳大利亚)为0.05美元/G。把vultr服务器删掉,开通新的服务器,流量会从0开始重新计算。 + +9、vultr怎样才能申请退款呢? + +vultr和其他的国外商家一样,都是使用工单的形式与客服联系,如果需要退款,直接在后台点击support,选择open ticket新开一个工单,选择billing question财务问题,简单的在文本框输入你的退款理由。比如:Please refund all the balance in my account。工单提交以后一般很快就可以给你确认退款,若干个工作日后就会退回你的支付方式。(全额退款结束后,账号可能会被删除) + +如果英语水平不好,但是想和客服进行交流,可以用百度在线翻译,自动中文转英文和英文转中文。 + +10、路由器也可以配置ssr,关键的是路由器刷固件,华硕路由器刷梅林改版固件最简单,下载固件直接刷,梅林改版固件自带软件中心,然后再软件中心点离线安装就可以了(原版梅林不带软件中心 [下载](http://asuswrt.lostrealm.ca/download))。路由器刷merlin_8wan_firmware(八万)的固件就行[KoolShare固件下载](http://firmware.koolshare.cn/) +其他的路由器也可以刷梅林。有问题或者对路由器配置ssr感兴趣的,可以在这些网站上自学:[koolshare](http://koolshare.cn/forum.php) [华硕路由爱好者社区](http://www.52asus.com/forum.php) [NAP6](https://nap6.com/portal.php) + +* * * + +>转接自:https://github.com/getlantern/forum/issues/5620 +原出处也已经被删除了 + + + diff --git a/SUMMARY.md b/SUMMARY.md index 08a017a2..501d1e0b 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,83 +1,96 @@ # Summary -* [前言](README.md) -* [Python代码规范](/codeSpecification/codeSpecification_Preface.md) - - [简明概述](/codeSpecification/codeSpecification_first.md) - - [注释](/codeSpecification/codeSpecification_second.md) - - [命名规范](/codeSpecification/codeSpecification_third.md) -* [第一个Python程序](/python1/Preface.md) - - [Python 简介](/python1/Introduction.md) - - [Python 的安装](/python1/Installation.md) - - [第一个 Python 程序](/python1/The_first_procedure.md) - - [集成开发环境(IDE): PyCharm](/python1/IDE.md) -* [基本数据类型和变量](/python2/Preface.md) - - [Python 语法的简要说明](/python2/Grammar.md) - - [Python 的基本数据类型](/python2/Type_of_data.md) - - [基本数据类型转换](/python2/Type_conversion.md) - - [Python 中的变量](/python2/Variable.md) -* [List 和 Tuple](/python3/Preface.md) - - [List(列表)](/python3/List.md) - - [tuple(元组)](/python3/tuple.md) -* [ Dict 和 Set](/python4/Preface.md) - - [字典(Dictionary)](/python4/Dict.md) - - [set](/python4/Set.md) -* [条件语句和循环语句](/python5/Preface.md) - - [条件语句](/python5/If.md) - - [循环语句](/python5/Cycle.md) - - [条件语句和循环语句综合实例](/python5/Example.md) -* [函数](/python6/Preface.md) - - [Python 自定义函数的基本步骤](/python6/1.md) - - [函数传值问题](/python6/2.md) - - [函数返回值](/python6/3.md) - - [函数的参数](/python6/4.md) - - [匿名函数](/python6/5.md) -* [迭代器和生成器](/python7/Preface.md) - - [迭代](/python7/1.md) - - [Python 迭代器](/python7/2.md) - - [lsit 生成式(列表生成式)](/python7/3.md) - - [生成器](/python7/4.md) - - [迭代器和生成器综合例子](/python7/5.md) -* [模块与包](/python8/Preface.md) - - [Python 模块简介](/python8/1.md) - - [模块的使用](/python8/2.md) - - [主模块和非主模块](/python8/3.md) - - [包](/python8/4.md) - - [作用域](/python8/5.md) -* [面向对象](/python9/Preface.md) - - [面向对象的概念](/python9/1.md) - - [类](/python9/2.md) - - [类的属性](/python9/3.md) - - [类的方法](/python9/4.md) - - [类的继承](/python9/5.md) - - [类的多态](/python9/6.md) -* [Python 的 Magic Method](/python10/Preface.md) - - [Python 的 Magic Method](/python10/1.md) - - [构造(`__new__`)和初始化(`__init__`)](/python10/2.md) - - [属性的访问控制](/python10/3.md) - - [对象的描述器](/python10/4.md) - - [自定义容器(Container)](/python10/5.md) - - [运算符相关的魔术方法](/python10/6.md) -* [枚举类](/python11/Preface.md) - - [枚举类的使用](/python11/1.md) - - [Enum 的源码](/python11/2.md) - - [自定义类型的枚举](/python11/3.md) - - [枚举的比较](/python11/4.md) -* [元类](/python12/Preface.md) - - [Python 中类也是对象](/python12/1.md) - - [使用 `type()` 动态创建类](/python12/2.md) - - [什么是元类](/python12/3.md) - - [自定义元类](/python12/4.md) - - [使用元类](/python12/5.md) -* [线程与进程](/python13/Preface.md) - - [线程与进程](/python13/1.md) - - [多线程编程](/python13/2.md) - - [进程](/python13/3.md) -* [一步一步了解正则表达式](/python14/Preface.md) - - [初识 Python 正则表达式](/python14/1.md) - - [字符集](/python14/2.md) - - [数量词](/python14/3.md) - - [边界匹配符和组](/python14/4.md) - - [re.sub](/python14/5.md) - - [re.match 和 re.search](/python14/6.md) -* [闭包](/python15/1.md) -* [装饰器](/python16/1.md) +* [为什么学Python?](/Article/PythonBasis/python0/WhyStudyPython.md) +* [Python代码规范](/Article/codeSpecification/codeSpecification_Preface.md) + - [简明概述](/Article/codeSpecification/codeSpecification_first.md) + - [注释](/Article/codeSpecification/codeSpecification_second.md) + - [命名规范](/Article/codeSpecification/codeSpecification_third.md) +* [第一个Python程序](/Article/PythonBasis/python1/Preface.md) + - [Python 简介](/Article/PythonBasis/python1/Introduction.md) + - [Python 的安装](/Article/PythonBasis/python1/Installation.md) + - [第一个 Python 程序](/Article/PythonBasis/python1/The_first_procedure.md) + - [集成开发环境(IDE): PyCharm](/Article/PythonBasis/python1/IDE.md) +* [基本数据类型和变量](/Article/PythonBasis/python2/Preface.md) + - [Python 语法的简要说明](/Article/PythonBasis/python2/Grammar.md) + - [print() 函数](/Article/PythonBasis/python2/print.md) + - [Python 的基本数据类型](/Article/PythonBasis/python2/Type_of_data.md) + - [字符串的编码问题](/Article/PythonBasis/python2/StringCoding.md) + - [基本数据类型转换](/Article/PythonBasis/python2/Type_conversion.md) + - [Python 中的变量](/Article/PythonBasis/python2/Variable.md) +* [List 和 Tuple](/Article/PythonBasis/python3/Preface.md) + - [List(列表)](/Article/PythonBasis/python3/List.md) + - [tuple(元组)](/Article/PythonBasis/python3/tuple.md) +* [ Dict 和 Set](/Article/PythonBasis/python4/Preface.md) + - [字典(Dictionary)](/Article/PythonBasis/python4/Dict.md) + - [set](/Article/PythonBasis/python4/Set.md) +* [条件语句和循环语句](/Article/PythonBasis/python5/Preface.md) + - [条件语句](/Article/PythonBasis/python5/If.md) + - [循环语句](/Article/PythonBasis/python5/Cycle.md) + - [条件语句和循环语句综合实例](/Article/PythonBasis/python5/Example.md) +* [函数](/Article/PythonBasis/python6/Preface.md) + - [Python 自定义函数的基本步骤](/Article/PythonBasis/python6/1.md) + - [函数返回值](/Article/PythonBasis/python6/2.md) + - [函数的参数](/Article/PythonBasis/python6/3.md) + - [函数传值问题](/Article/PythonBasis/python6/4.md) + - [匿名函数](/Article/PythonBasis/python6/5.md) +* [迭代器和生成器](/Article/PythonBasis/python7/Preface.md) + - [迭代](/Article/PythonBasis/python7/1.md) + - [Python 迭代器](/Article/PythonBasis/python7/2.md) + - [lsit 生成式(列表生成式)](/Article/PythonBasis/python7/3.md) + - [生成器](/Article/PythonBasis/python7/4.md) + - [迭代器和生成器综合例子](/Article/PythonBasis/python7/5.md) +* [面向对象](/Article/PythonBasis/python8/Preface.md) + - [面向对象的概念](/Article/PythonBasis/python8/1.md) + - [类的定义和调用](/Article/PythonBasis/python8/2.md) + - [类方法](/Article/PythonBasis/python8/3.md) + - [修改和增加类属性](/Article/PythonBasis/python8/4.md) + - [类和对象](/Article/PythonBasis/python8/5.md) + - [初始化函数](/Article/PythonBasis/python8/6.md) + - [类的继承](/Article/PythonBasis/python8/7.md) + - [类的多态](/Article/PythonBasis/python8/8.md) + - [类的访问控制](/Article/PythonBasis/python8/9.md) +* [模块与包](/Article/PythonBasis/python9/Preface.md) + - [Python 模块简介](/Article/PythonBasis/python9/1.md) + - [模块的使用](/Article/PythonBasis/python9/2.md) + - [主模块和非主模块](/Article/PythonBasis/python9/3.md) + - [包](/Article/PythonBasis/python9/4.md) + - [作用域](/Article/PythonBasis/python9/5.md) +* [Python 的 Magic Method](/Article/PythonBasis/python10/Preface.md) + - [Python 的 Magic Method](/Article/PythonBasis/python10/1.md) + - [构造(`__new__`)和初始化(`__init__`)](/Article/PythonBasis/python10/2.md) + - [属性的访问控制](/Article/PythonBasis/python10/3.md) + - [对象的描述器](/Article/PythonBasis/python10/4.md) + - [自定义容器(Container)](/Article/PythonBasis/python10/5.md) + - [运算符相关的魔术方法](/Article/PythonBasis/python10/6.md) +* [枚举类](/Article/python11/PythonBasis/Preface.md) + - [枚举类的使用](/Article/PythonBasis/python11/1.md) + - [Enum 的源码](/Article/PythonBasis/python11/2.md) + - [自定义类型的枚举](/Article/PythonBasis/python11/3.md) + - [枚举的比较](/Article/PythonBasis/python11/4.md) +* [元类](/Article/PythonBasis/python12/Preface.md) + - [Python 中类也是对象](/Article/PythonBasis/python12/1.md) + - [使用 `type()` 动态创建类](/Article/PythonBasis/python12/2.md) + - [什么是元类](/Article/PythonBasis/python12/3.md) + - [自定义元类](/Article/PythonBasis/python12/4.md) + - [使用元类](/Article/PythonBasis/python12/5.md) +* [线程与进程](/Article/PythonBasis/python13/Preface.md) + - [线程与进程](/Article/PythonBasis/python13/1.md) + - [多线程编程](/Article/PythonBasis/python13/2.md) + - [进程](/Article/PythonBasis/python13/3.md) +* [一步一步了解正则表达式](/Article/PythonBasis/python14/Preface.md) + - [初识 Python 正则表达式](/Article/PythonBasis/python14/1.md) + - [字符集](/Article/PythonBasis/python14/2.md) + - [数量词](/Article/PythonBasis/python14/3.md) + - [边界匹配符和组](/Article/PythonBasis/python14/4.md) + - [re.sub](/Article/PythonBasis/python14/5.md) + - [re.match 和 re.search](/Article/PythonBasis/python14/6.md) +* [闭包](/Article/PythonBasis/python15/1.md) +* [装饰器](/Article/PythonBasis/python16/1.md) +* [知识点补漏](README.md) + - [Python 关键字 yield](/Article/supplement/Python关键字yield.md) +* [**Python 进阶部分**](/Article/advanced/advanced.md) +* [使用Python虚拟环境](/Article/advanced/使用Python虚拟环境.md) +* [Mac中使用virtualenv和virtualenvwrapper](/Article/advanced/Mac中使用virtualenv和virtualenvwrapper.md) +* [**Django**](/Article/django/Django.md) + + diff --git a/codeSpecification/codeSpecification_Preface.md b/codeSpecification/codeSpecification_Preface.md deleted file mode 100644 index 83fa6609..00000000 --- a/codeSpecification/codeSpecification_Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -Python 学习之旅,先来看看 Python 的代码规范,让自己先有个意识,而且在往后的学习中慢慢养成习惯 - -# 目录 # - -![Python代码规范](https://dn-mhke0kuv.qbox.me/a542abfa2efe1fefd95e.png) \ No newline at end of file diff --git a/python1/IDE.md b/python1/IDE.md deleted file mode 100644 index 60582493..00000000 --- a/python1/IDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# 四、集成开发环境(IDE): PyCharm # - -当然,在学习周期还是建议使用文本编辑器或者是[Sublime Text](http://www.sublimetext.com/) 这个工具来操作的,因为这样有利于我们了解整个流程,到一定的程度,或者开始项目的时候就可以使用集成的开发环境了,这样可以提高我们的效率。PyCharm 是由 JetBrains 打造的一款 Python IDE,支持 macOS、 Windows、 Linux 系统。 - -PyCharm 下载地址 : [https://www.jetbrains.com/pycharm/download/](https://www.jetbrains.com/pycharm/download/) diff --git a/python1/Installation.md b/python1/Installation.md deleted file mode 100644 index 99b5af6d..00000000 --- a/python1/Installation.md +++ /dev/null @@ -1,13 +0,0 @@ -# 二、Python 的安装 # - -因为 Python 是跨平台的,它可以运行在 Windows、Mac 和各种 Linux/Unix 系统上。目前,Python 有两个版本,一个是 2.x 版,一个是 3.x版,这两个版本是不兼容的。本草根安装的是 3.6.1 版本的。 - -至于在哪里下载,本草根建议最好直接官网下载啦,随时下载下来的都是最新版本。官网地址:[https://www.python.org/](https://www.python.org/) - -本草根是 windows 系统,下载完后,直接安装,不过这里记得勾上Add Python 3.6 to PATH,然后点 “Install Now” 即可完成安装。如果没有勾上这个,就必须要自己配置环境变量了,至于如何配置,跟 JAVA 的差不多,具体可以 Google 一下。 - -![Python安装.png](http://upload-images.jianshu.io/upload_images/2136918-2bf6591f0a12e80b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -安装完成后,打开命令提示符窗口,敲入 python 后,出现下面的情况,证明 Python 安装成功了。你看到提示符 >>> 就表示我们已经在 Python交互式环境中了,可以输入任何 Python 代码,回车后会立刻得到执行结果。 - -![运行python.png](http://upload-images.jianshu.io/upload_images/2136918-817c22f802e8cfce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) \ No newline at end of file diff --git a/python1/Preface.md b/python1/Preface.md deleted file mode 100644 index 2a67728a..00000000 --- a/python1/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -一时冲动,就开始把 Python 的知识点做个总结归纳了。[gitbook](https://www.readwithu.com/) 同时更新。 - -# 目录 # - -![草根学 Python(一) 第一个 Python 程序](https://dn-mhke0kuv.qbox.me/2903b288b72a7ddb730c.png) \ No newline at end of file diff --git a/python1/The_first_procedure.md b/python1/The_first_procedure.md deleted file mode 100644 index 720a4c28..00000000 --- a/python1/The_first_procedure.md +++ /dev/null @@ -1,18 +0,0 @@ -# 三、第一个 Python 程序 # - -Python 的代码使用文本编辑器就可以写了,本草根使用 [Sublime Text](http://www.sublimetext.com/),第一个 Python 程序当然是 Hello Python 啦,把这句话打印出来。 - -注意 print 前面不要有任何空格,最后保存下来,可以看到,Python 保存后是一个以 .py 为后缀的文件。 - -![HelloPython.png](http://upload-images.jianshu.io/upload_images/2136918-f0ec1b2c06d1ab18.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - -最后就可以打开命令行窗口,把当前目录切换到 HelloPython.py 所在目录,就可以运行这个程序了,下面就是运行的结果。 - - -![运行第一个Python程序.png](http://upload-images.jianshu.io/upload_images/2136918-b7eb043853df29bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - -当然,如果你是使用 [Sublime Text](http://www.sublimetext.com/) ,并且在安装 Python 的时候配置好了环境变量,直接按 Ctrl + B 就可以运行了,运行结果如下: - -![Sublime运行Python.png](http://upload-images.jianshu.io/upload_images/2136918-a771a2fa1e4c03bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) \ No newline at end of file diff --git a/python10/Preface.md b/python10/Preface.md deleted file mode 100644 index 7c035ccb..00000000 --- a/python10/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -距离上一篇已经三个多星期了,最近比较累,下班回到家,很早就休息了,所以更新的进度有点慢。 - -# 目录 # - -![草根学Python(十) Python 的 Magic Method](http://p1ceh5usj.bkt.clouddn.com/%E8%8D%89%E6%A0%B9%E5%AD%A6Python%EF%BC%88%E5%8D%81%EF%BC%89%20Python%20%E7%9A%84%20Magic%20Method.png) diff --git a/python11/Preface.md b/python11/Preface.md deleted file mode 100644 index b0b522b2..00000000 --- a/python11/Preface.md +++ /dev/null @@ -1,9 +0,0 @@ -# 前言 # - -虽然没多少阅读,可是还是坚持写下去。对 Python 感兴趣的童鞋可以加入 Python 学习讨论微信群喔。可以先加我微信,然后拉进群。本人微信: - -![微信](http://img.blog.csdn.net/20170626191709373?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVHdvX1dhdGVy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) - -# 目录 # - -![草根学Python(十一) 枚举类](http://p1ceh5usj.bkt.clouddn.com/%E8%8D%89%E6%A0%B9%E5%AD%A6Python%EF%BC%88%E5%8D%81%E4%B8%80%EF%BC%89%20%E6%9E%9A%E4%B8%BE%E7%B1%BB.png) diff --git a/python12/Preface.md b/python12/Preface.md deleted file mode 100644 index 6a137ad5..00000000 --- a/python12/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -第十二篇了,撸起袖子,就是干。 - -# 目录 # - -![草根学Python(十二)元类](http://p1ceh5usj.bkt.clouddn.com/%E8%8D%89%E6%A0%B9%E5%AD%A6Python%EF%BC%88%E5%8D%81%E4%BA%8C%EF%BC%89%20%E5%85%83%E7%B1%BB.png) diff --git a/python13/Preface.md b/python13/Preface.md deleted file mode 100644 index 33eaf357..00000000 --- a/python13/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -拖了好久,不过还是得坚持。喜欢本文的话可以加下公众号【于你供读】。 - -# 目录 # - -![草根学Python(十三) 线程和进程](http://p1ceh5usj.bkt.clouddn.com/%E8%8D%89%E6%A0%B9%E5%AD%A6Python%EF%BC%88%E5%8D%81%E4%B8%89%EF%BC%89%20%E7%BA%BF%E7%A8%8B%E5%92%8C%E8%BF%9B%E7%A8%8B.png) diff --git a/python14/Preface.md b/python14/Preface.md deleted file mode 100644 index f50b849d..00000000 --- a/python14/Preface.md +++ /dev/null @@ -1,3 +0,0 @@ -# 目录 # - -![草根学Python(十四) 一步一步了解正则表达式](https://raw.githubusercontent.com/TwoWater/Python/master/python14/%E8%8D%89%E6%A0%B9%E5%AD%A6Python%EF%BC%88%E5%8D%81%E5%9B%9B%EF%BC%89%20%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%BA%86%E8%A7%A3%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.png) diff --git a/python2/Grammar.md b/python2/Grammar.md deleted file mode 100644 index 32e40e0a..00000000 --- a/python2/Grammar.md +++ /dev/null @@ -1,11 +0,0 @@ -# 一、Python 语法的简要说明 # - -每种语言都有自己的语法,不管是自然语言还是我们的计算机编程语言,Python 也不例外,编辑器或者解析器根据符合语法的程序代码转换成 CPU 能够执行的机器码,然后执行。 - -Python 的语法比较简单,采用缩进方式。因为之前是写 JAVA 或者 C++ 偏多,突然没了大括号和要注意缩进,是有点不习惯的,不过还是可以接受的。而且要养成使用 4 个空格的缩进,可以在文本编辑器设置 Tab 自动转换为 4 个空格。 - -![Python语法.png](http://upload-images.jianshu.io/upload_images/2136918-b9b072c2587cc89e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -以 # 开头的语句是注释,其他每一行都是一个语句,当语句以冒号 : 结尾时,缩进的语句视为代码块。要注意的是 Python 程序是大小写敏感的,如果写错了大小写,程序会报错。 - -更多的说明可以看看之前的文章:[Python代码规范中的简明概述](https://www.readwithu.com/codeSpecification/codeSpecification_first.html) \ No newline at end of file diff --git a/python2/Preface.md b/python2/Preface.md deleted file mode 100644 index 56ca228b..00000000 --- a/python2/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -最近要开始新的项目,工作又开始忙起来了,不过还是每天要抽时间来写博客,但不可能做到日更,因为一篇博客,写的时间还是挺长的。[Gitbook](https://www.readwithu.com/) 同时更新喔。 - -# 目录 # - -![草根学Python(二)基本数据类型和变量](https://dn-mhke0kuv.qbox.me/a3eb54781266e147c3cc.png) \ No newline at end of file diff --git a/python2/Type_conversion.md b/python2/Type_conversion.md deleted file mode 100644 index d49b180b..00000000 --- a/python2/Type_conversion.md +++ /dev/null @@ -1,18 +0,0 @@ -# 三、基本数据类型转换 # - -|方法|说明| -|-----|------| -|int(x [,base ]) | 将x转换为一个整数 | -|long(x [,base ])| 将x转换为一个长整数 | -|float(x ) | 将x转换到一个浮点数 | -|complex(real [,imag ])| 创建一个复数 | -|str(x ) | 将对象 x 转换为字符串 | -|repr(x ) | 将对象 x 转换为表达式字符串 | -|eval(str ) | 用来计算在字符串中的有效 Python 表达式,并返回一个对象 | -|tuple(s ) | 将序列 s 转换为一个元组 | -|list(s ) | 将序列 s 转换为一个列表 | -|chr(x ) | 将一个整数转换为一个字符 | -|unichr(x ) | 将一个整数转换为 Unicode 字符 | -|ord(x ) | 将一个字符转换为它的整数值 | -|hex(x ) | 将一个整数转换为一个十六进制字符串 | -|oct(x ) | 将一个整数转换为一个八进制字符串 | \ No newline at end of file diff --git a/python2/Type_of_data.md b/python2/Type_of_data.md deleted file mode 100644 index 315704b9..00000000 --- a/python2/Type_of_data.md +++ /dev/null @@ -1,90 +0,0 @@ -# 二、Python 的基本数据类型 # - -## 1、整数 ## - -Python 可以处理任意大小的整数,当然包括负整数,在 Python 程序中,整数的表示方法和数学上的写法一模一样,例如:`1`,`100`,`-8080`,`0`,等等。 - -计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用 0x 前缀和 0-9,a-f 表示,例如:0xff00,0xa5b4c3d2,等等。 - - -## 2、浮点数 ## - -浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的。整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法也是精确的),而浮点数运算则可能会有四舍五入的误差。 - -## 3、字符串 ## - -字符串是以 '' 或 "" 括起来的任意文本,比如 `'abc'` ,`"123"` 等等。请注意,'' 或 "" 本身只是一种表示方式,不是字符串的一部分,因此,字符串 `'abc'` 只有 a,b,c 这 3 个字符。这个其他的编程语言也是类似的。 - - -### (1) Python 中的字符串和字符串转义 ### - -在上面那里提到,字符串可以用 `''` 或者 `""` 括起来表示。可是有些时候,我们字符串本身就包含了 `''` 或者 `""` ,怎么办呢? - -那这个时候就需要对字符串的某些特殊字符进行“转义”,Python 字符串用 `\` 进行转义。跟 JAVA 也是一样的。 - -常用的转义字符还有: -``` -\n 表示换行 -\t 表示一个制表符 -\\ 表示 \ 字符本身 -``` -具体例子: - -![Python字符串转义.png](http://upload-images.jianshu.io/upload_images/2136918-88fdd2055dd834f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -那上面就有一个问题呢,如果一个字符串包含很多需要转义的字符,对每一个字符都进行转义会很麻烦。这里为了应付这种情况,我们可以在字符串前面加个前缀 `r` ,表示这是一个 raw 字符串,里面的字符就不需要转义了。 - -![Python转义r.png](http://upload-images.jianshu.io/upload_images/2136918-8391230097f54800.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -但是,要注意的一点是,但是`r'...'`表示法不能表示多行字符串,也不能表示包含`'`和`"`的字符串。 - -如果要表示多行字符串,可以用`'''...'''`表示,当然你也还可以在多行字符串前面添加 `r` ,把这个多行字符串也变成一个raw字符串 - - -![多行转义.png](http://upload-images.jianshu.io/upload_images/2136918-36df87f50895af18.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -### (2) 字符串的编码问题 ### - -我们都知道计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),0 - 255被用来表示大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母 A 的编码是 65,小写字母 z 的编码是 122。 - -如果要表示中文,显然一个字节是不够的,至少需要两个字节,而且还不能和 ASCII 编码冲突,所以,中国制定了 GB2312 编码,用来把中文编进去。 - -类似的,日文和韩文等其他语言也有这个问题。为了统一所有文字的编码,Unicode 应运而生。Unicode 把所有语言都统一到一套编码里,这样就不会再有乱码问题了。 - -Unicode 通常用两个字节表示一个字符,原有的英文编码从单字节变成双字节,只需要把高字节全部填为 0 就可以。 - -因为 Python 的诞生比 Unicode 标准发布的时间还要早,所以最早的Python 只支持 ASCII 编码,普通的字符串 'ABC' 在 Python 内部都是 ASCII 编码的。 - -Python 在后来添加了对 Unicode 的支持,以 Unicode 表示的字符串用`u'...'`表示。 - -不过在最新的 Python 3 版本中,字符串是以 Unicode 编码的,也就是说,Python 的字符串支持多语言。就像上面的例子一样,我的代码中没有加`u'...'`,也能正常显示。 - -不过由于 Python 源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为 UTF-8 编码。当Python 解释器读取源代码时,为了让它按 UTF-8 编码读取,我们通常在文件开头写上这两行: - -```python -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -``` - -第一行注释是为了告诉 Linux/OS X 系统,这是一个 Python 可执行程序,Windows 系统会忽略这个注释; - -第二行注释是为了告诉 Python 解释器,按照 UTF-8 编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。 - -申明了 UTF-8 编码并不意味着你的 .py 文件就是 UTF-8 编码的,必须并且要确保文本编辑器正在使用 UTF-8 without BOM 编码 - -## 4、布尔值 ## - -布尔值和布尔代数的表示完全一致,一个布尔值只有 `True` 、 `False `两种值,要么是 `True`,要么是 `False`,在 Python 中,可以直接用 True、False 表示布尔值(请注意大小写),也可以通过布尔运算计算出来。 - -布尔值可以用 `and`、`or` 和 `not` 运算。 - -`and` 运算是与运算,只有所有都为 True,and 运算结果才是 True。 - -`or` 运算是或运算,只要其中有一个为 True,or 运算结果就是 True。 - -`not` 运算是非运算,它是一个单目运算符,把 True 变成 False,False 变成 True。 - - -## 5、空值 ## - -基本上每种编程语言都有自己的特殊值——空值,在 Python 中,用 None 来表示 \ No newline at end of file diff --git a/python3/List.md b/python3/List.md deleted file mode 100644 index 860d08cb..00000000 --- a/python3/List.md +++ /dev/null @@ -1,158 +0,0 @@ -# 一、List(列表) # - -Python 内置的一种数据类型是列表:list。 list 是一种有序的集合,可以随时添加和删除其中的元素。 - -## 1、创建 List(列表) ## - -创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可,且列表的数据项不需要具有相同的类型 - -```python -list1=['两点水','twowter','liangdianshui',123] -``` - -## 2、访问 List(列表)中的值 ## - -使用下标索引来访问列表中的值,同样你也可以使用方括号的形式截取字符 - -```python -list1=['两点水','twowter','liangdianshui',123] -# 通过索引来访问列表 -print(list1[2]) -# 通过方括号的形式来截取列表中的数据 -print(list1[0:2]) -``` - -输出的结果: - -![访问 List(列表)中的值](http://upload-images.jianshu.io/upload_images/2136918-ab562ada6ba08848?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - -## 3、更新 List(列表) ## - -可以通过索引对列表的数据项进行修改或更新,也可以使用 append() 方法来添加列表项。 - -```python -list1=['两点水','twowter','liangdianshui',123] -print(list1) -# 通过索引对列表的数据项进行修改或更新 -list1[2]=456 -print(list1) -# 使用 append() 方法来添加列表项 -list1.append('hello'); -print(list1) -``` - -输出的结果: - -![更新 List(列表)](http://upload-images.jianshu.io/upload_images/2136918-96de950da2563ac6?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - -## 4、删除 List(列表) ## - -使用 del 语句来删除列表的的元素 - -```python -list1=['两点水','twowter','liangdianshui',123] -print(list1) -# 使用 del 语句来删除列表的的元素 -del list1[3] -print(list1) -``` - -输出的结果: - -![删除 List(列表)](http://upload-images.jianshu.io/upload_images/2136918-e761bf56f583089f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 5、List(列表)运算符 ## - -列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。 - -|Python 表达式|结果|描述| -|-----------|-----|-----| -|len([1, 2, 3])|3|计算元素个数| -|[1, 2, 3] + [4, 5, 6]| [1, 2, 3, 4, 5, 6]| 组合| -|['Hi!'] * 4|['Hi!', 'Hi!', 'Hi!', 'Hi!']|复制| -|3 in [1, 2, 3]|True|元素是否存在于列表中| -|for x in [1, 2, 3]: print x,|1 2 3|迭代| - -## 6、List (列表)函数&方法 ## - -|函数&方法|描述| -|----|----| -|cmp(list1, list2)|比较两个列表的元素| -|len(list)|列表元素个数| -|max(list)|返回列表元素最大值| -|min(list)|返回列表元素最小值| -|list(seq)|将元组转换为列表| -|list.append(obj)|在列表末尾添加新的对象| -|list.count(obj)|统计某个元素在列表中出现的次数| -|list.extend(seq)|在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)| -|list.index(obj)|从列表中找出某个值第一个匹配项的索引位置| -|list.insert(index, obj)|将对象插入列表| -|list.pop(obj=list[-1])|移除列表中的一个元素(默认最后一个元素),并且返回该元素的值| -|list.reverse()|反向列表中元素| -|list.sort([func])|对原列表进行排序| - - -## 7、实例 ## - - -最后通过一个例子来熟悉了解 List 的操作 - -例子: - -```python -#-*-coding:utf-8-*- -#-----------------------list的使用---------------------------------- - -# 1.一个产品,需要列出产品的用户,这时候就可以使用一个 list 来表示 -user=['liangdianshui','twowater','两点水'] -print('1.产品用户') -print(user) - -# 2.如果需要统计有多少个用户,这时候 len() 函数可以获的 list 里元素的个数 -len(user) -print('\n2.统计有多少个用户') -print(len(user)) - -# 3.此时,如果需要知道具体的用户呢?可以用过索引来访问 list 中每一个位置的元素,索引是0从开始的 -print('\n3.查看具体的用户') -print(user[0]+','+user[1]+','+user[2]) - -# 4.突然来了一个新的用户,这时我们需要在原有的 list 末尾加一个用户 -user.append('茵茵') -print('\n4.在末尾添加新用户') -print(user) - -# 5.又新增了一个用户,可是这个用户是 VIP 级别的学生,需要放在第一位,可以通过 insert 方法插入到指定的位置 -# 注意:插入数据的时候注意是否越界,索引不能超过 len(user)-1 -user.insert(0,'VIP用户') -print('\n5.指定位置添加用户') -print(user) - -# 6.突然发现之前弄错了,“茵茵”就是'VIP用户',因此,需要删除“茵茵”;pop() 删除 list 末尾的元素 -user.pop() -print('\n6.删除末尾用户') -print(user) - -# 7.过了一段时间,用户“liangdianshui”不玩这个产品,删除了账号 -# 因此需要要删除指定位置的元素,用pop(i)方法,其中i是索引位置 -user.pop(1) -print('\n7.删除指定位置的list元素') -print(user) - -# 8.用户“两点水”想修改自己的昵称了 -user[2]='三点水' -print('\n8.把某个元素替换成别的元素') -print(user) - -# 9.单单保存用户昵称好像不够好,最好把账号也放进去 -# 这里账号是整数类型,跟昵称的字符串类型不同,不过 list 里面的元素的数据类型是可以不同的 -# 而且 list 元素也可以是另一个 list -newUser=[['VIP用户',11111],['twowater',22222],['三点水',33333]] -print('\n9.不同元素类型的list数据') -print(newUser) - -``` - -![list的使用](http://upload-images.jianshu.io/upload_images/2136918-65d31cae9f8bb34d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python3/Preface.md b/python3/Preface.md deleted file mode 100644 index 4e9a5669..00000000 --- a/python3/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -继续更新,可以通过 [https://www.readwithu.com/](https://www.readwithu.com/) 来看之前的文章。 - -# 目录 # - -![草根学Python(三) List 和 Tuple](http://upload-images.jianshu.io/upload_images/2136918-4d3be05b7f048808?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python3/tuple.md b/python3/tuple.md deleted file mode 100644 index 6bb08c1e..00000000 --- a/python3/tuple.md +++ /dev/null @@ -1,118 +0,0 @@ -# 二、tuple(元组) # - -另一种有序列表叫元组:tuple 。tuple 和 list 非常类似,但是 tuple 一旦初始化就不能修改。那么不能修改是指什么意思呢? - -tuple 不可变是指当你创建了 tuple 时候,它就不能改变了,也就是说它也没有 append(),insert() 这样的方法,但它也有获取某个索引值的方法,但是不能赋值。那么为什么要有 tuple 呢?那是因为 tuple 是不可变的,所以代码更安全。所以建议能用 tuple 代替 list 就尽量用 tuple 。 - -## 1、创建 tuple(元祖) ## - -元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。 - -```python -tuple1=('两点水','twowter','liangdianshui',123,456) -tuple2='两点水','twowter','liangdianshui',123,456 -``` - -创建空元组 - -```python -tuple3=() -``` - -元组中只包含一个元素时,需要在元素后面添加逗号 - -```python -tuple4=(123,) -``` - -如果不加逗号,创建出来的就不是 tuple (元组),而是指 ```123``` 这个数了,这是因为括号 ()既可以表示 tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python 规定,这种情况下,按小括号进行计算,计算结果自然是 ```123``` 。具体看下图 tuple4 和 tuple5 的输出值 - -![创建tuple](http://upload-images.jianshu.io/upload_images/2136918-2072470ffe7cbee7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - - -## 2、tuple(元组)的索引 ## - -元组下标索引从0开始,可以进行截取,组合等。 - -## 3、访问 tuple (元组) ## - -tuple(元组)可以使用下标索引来访问元组中的值 - -```python -#-*-coding:utf-8-*- - -tuple1=('两点水','twowter','liangdianshui',123,456) -tuple2='两点水','twowter','liangdianshui',123,456 - -print(tuple1[1]) -print(tuple2[0]) -``` - -输出的结果: - -![访问 tuple](http://upload-images.jianshu.io/upload_images/2136918-edfb7c9ebc7d5ab0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 4、修改 tuple (元组) ## - -上面不是花了一大段来说 tuple 是不可变的吗?这里怎么又来修改 tuple (元组) 了。那是因为元组中的元素值是不允许修改的,但我们可以对元组进行连接组合,还有通过修改其他列表的值从而影响 tuple 的值。 - -具体看下面的这个例子: - -```python -#-*-coding:utf-8-*- -list1=[123,456] -tuple1=('两点水','twowater','liangdianshui',list1) -print(tuple1) -list1[0]=789 -list1[1]=100 -print(tuple1) -``` - -输出的结果: -``` -('两点水', 'twowater', 'liangdianshui', [123, 456]) -('两点水', 'twowater', 'liangdianshui', [789, 100]) -``` - - -可以看到,两次输出的 tuple 值是变了的。我们看看 tuple1 的存储是怎样的。 - - -![修改tuple流程图](https://dn-mhke0kuv.qbox.me/b2b75132251ec23a2f8a.png) - -可以看到,tuple1 有四个元素,最后一个元素是一个 List ,List 列表里有两个元素,当我们把 List 列表中的两个元素 `124` 和 `456` 修改为 `789` 和 `100` 的时候,从输出来的 tuple1 的值来看,好像确实是改变了,但其实变的不是 tuple 的元素,而是 list 的元素。tuple 一开始指向的 list 并没有改成别的 list,所以,tuple 所谓的“不变”是说,tuple 的每个元素,指向永远不变。注意是 tupe1 中的第四个元素还是指向原来的 list ,是没有变的。 - -## 5、删除 tuple (元组) ## - -tuple 元组中的元素值是不允许删除的,但我们可以使用 del 语句来删除整个元组 - -```python -#-*-coding:utf-8-*- - -tuple1=('两点水','twowter','liangdianshui',[123,456]) -print(tuple1) -del tuple1 -``` - -## 6、tuple (元组)运算符 ## - -与字符串一样,元组之间可以使用 + 号和 * 号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的元组。 - -|Python 表达式|结果|描述| -|-----------|-----|-----| -|len((1, 2, 3))|3|计算元素个数| -|(1, 2, 3) + (4, 5, 6)|(1, 2, 3, 4, 5, 6)|连接| -|('Hi!',) * 4|('Hi!', 'Hi!', 'Hi!', 'Hi!')|复制| -|3 in (1, 2, 3)|True|元素是否存在| -|for x in (1, 2, 3): print x,|1 2 3|迭代| - -## 7、元组内置函数 ## - -|方法|描述| -|----|----| -|cmp(tuple1, tuple2)|比较两个元组元素| -|len(tuple)|计算元组元素个数| -|max(tuple)|返回元组中元素最大值| -|min(tuple)|返回元组中元素最小值| -|tuple(seq)|将列表转换为元组| diff --git a/python4/Preface.md b/python4/Preface.md deleted file mode 100644 index 0c3221c2..00000000 --- a/python4/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -上一篇文章出现了个明显的知识点错误,不过感谢有个网友的提出,及时进行了修改。也希望各位多多包涵。 - -# 目录 # - -![草根学Python(四) Dict 和 Set](http://upload-images.jianshu.io/upload_images/2136918-726716aa6ab762fd?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python5/Cycle.md b/python5/Cycle.md deleted file mode 100644 index 5eb983dd..00000000 --- a/python5/Cycle.md +++ /dev/null @@ -1,190 +0,0 @@ -# 二、循环语句 # - -一般编程语言都有循环语句,循环语句允许我们执行一个语句或语句组多次。 - -循环语句的一般形式如下: - -![python循环语句](http://upload-images.jianshu.io/upload_images/2136918-eaaae2fbfec3330f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -Python 提供了 for 循环和 while 循环,当然还有一些控制循环的语句: - -|循环控制语句|描述| -|------|------| -|break|在语句块执行过程中终止循环,并且跳出整个循环| -|continue|在语句块执行过程中终止当前循环,跳出该次循环,执行下一次循环| -|pass|pass 是空语句,是为了保持程序结构的完整性| - - -## 1、While 循环语句 ## - - -```python -count = 1 -sum = 0 -while (count <= 100): - sum = sum + count - count = count + 1 -print(sum) -``` - -输出的结果: - -```txt -5050 -``` - -当然 while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,break 则是用于退出循环 - -比如,上面的例子是计算 1 到 100 所有整数的和,当我们需要判断 sum 大于 1000 的时候,不在相加时,可以用到 break ,退出整个循环 - -```python -count = 1 -sum = 0 -while (count <= 100): - sum = sum + count - if ( sum > 1000): #当 sum 大于 1000 的时候退出循环 - break - count = count + 1 -print(sum) -``` - -输出的结果: - -```txt -1035 -``` - -有时候,我们只想统计 1 到 100 之间的奇数和,那么也就是说当 count 是偶数,也就是双数的时候,我们需要跳出当次的循环,不想加,这时候可以用到 break - -```python -count = 1 -sum = 0 -while (count <= 100): - if ( count % 2 == 0): # 双数时跳过输出 - count = count + 1 - continue - sum = sum + count - count = count + 1 -print(sum) -``` - -输出的语句: - -```txt -2500 -``` - -在 Python 的 while 循环中,还可以使用 else 语句,while … else 在循环条件为 false 时执行 else 语句块 - -比如: - -```python -count = 0 -while count < 5: - print (count) - count = count + 1 -else: - print (count) -``` - -输出的结果: - -```txt -0 -1 -2 -3 -4 -5 -``` - -## 2、 for 循环语句 ## - - for循环可以遍历任何序列的项目,如一个列表或者一个字符串 - -它的流程图基本如下: - - -![for循环的流程图](http://upload-images.jianshu.io/upload_images/2136918-a0728c1c488238af?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -基本的语法格式: - -```python -for iterating_var in sequence: - statements(s) -``` - -实例: - -```python -for letter in 'Hello 两点水': - print(letter) -``` - -输出的结果如下: - -```txt -H -e -l -l -o - -两 -点 -水 -``` - -有 while … else 语句,当然也有 for … else 语句啦,for 中的语句和普通的没有区别,else 中的语句会在循环正常执行完(即 for 不是通过 break 跳出而中断的)的情况下执行,while … else 也是一样。 - -```python -for num in range(10,20): # 迭代 10 到 20 之间的数字 - for i in range(2,num): # 根据因子迭代 - if num%i == 0: # 确定第一个因子 - j=num/i # 计算第二个因子 - print ('%d 是一个合数' % num) - break # 跳出当前循环 - else: # 循环的 else 部分 - print ('%d 是一个质数' % num) -``` - -输出的结果: - -```txt -10 是一个合数 -11 是一个质数 -12 是一个合数 -13 是一个质数 -14 是一个合数 -15 是一个合数 -16 是一个合数 -17 是一个质数 -18 是一个合数 -19 是一个质数 -``` - -## 3、嵌套循环 ## - -Python 语言允许在一个循环体里面嵌入另一个循环。上面的实例也是使用了嵌套循环的,这里就不给出实例了。 - -具体的语法如下: - -**for 循环嵌套语法** - -```python -for iterating_var in sequence: - for iterating_var in sequence: - statements(s) - statements(s) -``` - -**while 循环嵌套语法** - -```python -while expression: - while expression: - statement(s) - statement(s) -``` - -除此之外,你也可以在循环体内嵌入其他的循环体,如在 while 循环中可以嵌入 for 循环, 反之,你可以在 for 循环中嵌入 while 循环 diff --git a/python5/Preface.md b/python5/Preface.md deleted file mode 100644 index ce4be8b1..00000000 --- a/python5/Preface.md +++ /dev/null @@ -1,10 +0,0 @@ -# 前言 # - -第一次建学习群,而且是 Python 的学习群,虽然之前深入学习和工作都是 Android 相关的,最近学起来 Python ,真的很好玩,所以创了个微信群,希望童鞋们进群学习讨论。也可以直接加我微`androidwed`拉进群。也欢迎大家在 [Gitbook](https://www.readwithu.com/) 中提出文章的不足。 - -![Python学习群](http://upload-images.jianshu.io/upload_images/2136918-f3f0c60ce12e5a92?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - - -# 目录 # - -![草根学Python(五) 条件语句和循环语句](http://upload-images.jianshu.io/upload_images/2136918-32902eec93d9ffc1?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python6/1.md b/python6/1.md deleted file mode 100644 index 4c3c0757..00000000 --- a/python6/1.md +++ /dev/null @@ -1,42 +0,0 @@ -# 一、Python 自定义函数的基本步骤 # - -函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 - -自定义函数,基本有以下规则步骤: - -* 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号() -* 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数 -* 函数的第一行语句可以选择性地使用文档字符串(用于存放函数说明) -* 函数内容以冒号起始,并且缩进 -* return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的 return 相当于返回 None。 - -语法示例: - -```python -def functionname( parameters ): - "函数_文档字符串" - function_suite - return [expression] -``` - -实例: - -1. def 定义一个函数,给定一个函数名 sum -2. 声明两个参数 num1 和 num2 -3. 函数的第一行语句进行函数说明:两数之和 -4. 最终 return 语句结束函数,并返回两数之和 - -```python -def sum(num1,num2): - "两数之和" - return num1+num2 - -# 调用函数 -print(sum(5,6)) -``` - -输出结果: - -```python -11 -``` \ No newline at end of file diff --git a/python6/Preface.md b/python6/Preface.md deleted file mode 100644 index f05ffefa..00000000 --- a/python6/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -前天创了个 Python 微信讨论群,以为没人进的,哈哈,想不到还真有小伙伴进群学习讨论。如果想进群,可以加我微信: androidwed ,拉进群,就不贴微信群二维码了,一是会失效,二影响文章。 - -# 目录 # - -![草根学Python(六) 函数](http://upload-images.jianshu.io/upload_images/2136918-be9226fe109027f3?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python7/Preface.md b/python7/Preface.md deleted file mode 100644 index 22583dc6..00000000 --- a/python7/Preface.md +++ /dev/null @@ -1,7 +0,0 @@ -# 前言 # - -这篇博客写了很久,其实写每一篇博客用的时间还是挺长的,不够这有利于自己的学习,也想分享一下。之前也说了创建了一个微信群,Python 学习讨论群,现在只有 40 个左右的小伙伴,如果有兴趣加入学习讨论的话,可以加我微信:`androidwed`,拉你进群。想看回之前的文章,也可以通过 [Gitbook](https://www.gitbook.com/book/twowater/python/details) 查看,欢迎提出问题和点下 star,及时查看更新。 - -# 目录 # - -![草根学Python(七) 迭代器和生成器](http://upload-images.jianshu.io/upload_images/2136918-b350c0e98ca47183?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python8/1.md b/python8/1.md deleted file mode 100644 index 444fe162..00000000 --- a/python8/1.md +++ /dev/null @@ -1,21 +0,0 @@ -# 一、Python 模块简介 # - -在开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。 - -为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在 Python 中,一个 .py 文件就称之为一个模块(Module)。 - -之前我们学习过函数,知道函数是实现一项或多项功能的一段程序 。其实模块就是函数功能的扩展。为什么这么说呢?那是因为模块其实就是实现一项或多项功能的程序块。 - -通过上面的定义,不难发现,函数和模块都是用来实现功能的,只是模块的范围比函数广,在模块中,可以有多个函数。 - -竟然了解了什么是模块了,那么为什么需要模块呢?竟然有了函数,那为啥那需要模块? - -最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括 Python 内置的模块和来自第三方的模块。 - -使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。 - -Python 本身就内置了很多非常有用的模块,只要安装完毕,这些模块就可以立刻使用。我们可以尝试找下这些模块,比如我的 Python 安装目录是默认的安装目录,在 C:\Users\Administrator\AppData\Local\Programs\Python\Python36 ,然后找到 Lib 目录,就可以发现里面全部都是模块,没错,这些 `.py` 文件就是模块了。 - -![python36bin目录](http://upload-images.jianshu.io/upload_images/2136918-5ecc6493206da1ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -其实模块可以分为标准库模块和自定义模块,而刚刚我们看到的 Lib 目录下的都是标准库模块。 diff --git a/python9/2.md b/python9/2.md deleted file mode 100644 index 6e7606c6..00000000 --- a/python9/2.md +++ /dev/null @@ -1,117 +0,0 @@ -# 二、类 # - -## 1、定义类 ## - -类定义语法格式如下: - -```python -class ClassName: - - . - . - . - -``` - -一个类也是由属性和方法组成的,有些时候我们定义类的时候需要设置类的属性,因此这就需要构造函 - -类的构造函数如下: - -```python -def __init__(self,[...): -``` - -类定义了 __init__() 方法的话,类的实例化操作会自动调用 __init__() 方法。 - -那么如构造函数相对应的是析构函数,理所当然,一个类创建的时候我们可以用过构造函数设置属性,那么当一个类销毁的时候,就会调用析构函数。 - -析构函数语法如下: - -```python -def __del__(self,[...): -``` - -仔细观察的童鞋都会发现,类的方法与普通的函数有一个特别的区别,它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。 - -那么这个 self 代表什么呢? - -我们可以看下实例,通过实例来找出答案: - -```python -#!/usr/bin/env python3 -# -*- coding: UTF-8 -*- - -class Test: - def prt(self): - print(self) - print(self.__class__) - -t = Test() -t.prt() -``` - -观察输出的结果: - -![Python self](http://upload-images.jianshu.io/upload_images/2136918-66d29b081ad5510b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -从执行结果可以很明显的看出,self 代表的是类的实例,输出的是当前对象的地址,而 `self.__class__` 则指向类。 - -当然 self 不是 python 关键字,也就是说我们把他换成其他的字符也是可以正常执行的。只不过我们习惯使用 self - -## 2、Python 定义类的历史遗留问题 ## - -Python 在版本的迭代中,有一个关于类的历史遗留问题,就是新式类和旧式类的问题,具体先看以下的代码: - -```python -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -# 旧式类 -class OldClass: - pass - -# 新式类 -class NewClass(object): - pass - -``` - -可以看到,这里使用了两者中不同的方式定义类,可以看到最大的不同就是,新式类继承了`object` 类,在 Python2 中,我们定义类的时候最好定义新式类,当然在 Python3 中不存在这个问题了,因为 Python3 中所有类都是新式类。 - -那么新式类和旧式类有什么区别呢? - -运行下下面的那段代码: - -```python -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -# 旧式类 -class OldClass: - def __init__(self, account, name): - self.account = account; - self.name = name; - - -# 新式类 -class NewClass(object): - def __init__(self, account, name): - self.account = account; - self.name = name; - - -if __name__ == '__main__': - old_class = OldClass(111111, 'OldClass') - print(old_class) - print(type(old_class)) - print(dir(old_class)) - print('\n') - new_class=NewClass(222222,'NewClass') - print(new_class) - print(type(new_class)) - print(dir(new_class)) - -``` - - -仔细观察输出的结果,对比一下,就能观察出来,注意喔,Pyhton3 中输出的结果是一模一样的,因为Python3 中没有新式类旧式类的问题。 diff --git a/python9/3.md b/python9/3.md deleted file mode 100644 index 34a593e8..00000000 --- a/python9/3.md +++ /dev/null @@ -1,64 +0,0 @@ -# 三、类的属性 # - -## 1、直接在类中定义属性 ## - -定义类的属性,当然最简单最直接的就是在类中定义,例如: - -```python -class UserInfo(object): - name='两点水' -``` - -## 2、在构造函数中定义属性 ## - -故名思议,就是在构造对象的时候,对属性进行定义。 - -```python -class UserInfo(object): - def __init__(self,name): - self.name=name -``` - -## 3、属性的访问控制 ## - -在 Java 中,有 public (公共)属性 和 private (私有)属性,这可以对属性进行访问控制。那么在 Python 中有没有属性的访问控制呢? - -一般情况下,我们会使用 `__private_attrs` 两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 `self.__private_attrs`。 - -为什么只能说一般情况下呢?因为实际上, Python 中是没有提供私有属性等功能的。但是 Python 对属性的访问控制是靠程序员自觉的。为什么这么说呢?看看下面的示例: - -![Python 属性访问控制](http://upload-images.jianshu.io/upload_images/2136918-4ac2643aa5b0fa37?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -仔细看图片,为什么说双下划线不是真正的私有属性呢?我们看下下面的例子,用下面的例子来验证: - -```python - -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -class UserInfo(object): - def __init__(self, name, age, account): - self.name = name - self._age = age - self.__account = account - - def get_account(self): - return self.__account - - -if __name__ == '__main__': - userInfo = UserInfo('两点水', 23, 347073565); - # 打印所有属性 - print(dir(userInfo)) - # 打印构造函数中的属性 - print(userInfo.__dict__) - print(userInfo.get_account()) - # 用于验证双下划线是否是真正的私有属性 - print(userInfo._UserInfo__account) - - -``` - -输出的结果如下图: - -![Python 属性访问控制](http://upload-images.jianshu.io/upload_images/2136918-de89d4dc5f5f9f77?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) diff --git a/python9/Preface.md b/python9/Preface.md deleted file mode 100644 index cc15f62c..00000000 --- a/python9/Preface.md +++ /dev/null @@ -1,10 +0,0 @@ -# 前言 # - -这篇写的很纠结,不过还是写完了。弄了个很逊的公众号,如果对本文有兴趣,可以关注下公众号喔,会持续更新。 - - -![公众号](http://img.blog.csdn.net/20170730171715934?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVHdvX1dhdGVy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) - -# 目录 # - -![草根学Python(九)面向对象](http://upload-images.jianshu.io/upload_images/2136918-eecf427fdbd1688c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)