From e3a10fe2ba0a1e58a4cdd875d38a4902ad165866 Mon Sep 17 00:00:00 2001 From: zwb <1465302821@qq.com> Date: Thu, 26 Dec 2024 09:59:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 01-Python语言概述.md | 875 +++++++++++++++++++++++++++++++++++++ 02-Python开发环境.md | 224 ++++++++++ 03-Python基本用法.md | 404 +++++++++++++++++ 04-Python变量.md | 250 +++++++++++ 05-Python运算符与表达式.md | 327 ++++++++++++++ 5 files changed, 2080 insertions(+) create mode 100644 01-Python语言概述.md create mode 100644 02-Python开发环境.md create mode 100644 03-Python基本用法.md create mode 100644 04-Python变量.md create mode 100644 05-Python运算符与表达式.md diff --git a/01-Python语言概述.md b/01-Python语言概述.md new file mode 100644 index 0000000..a9db046 --- /dev/null +++ b/01-Python语言概述.md @@ -0,0 +1,875 @@ +# 01-Python语言概述 + +**Life is short ,You need Python !** + +​ -- Brce Eckel + +## 一、计算机语言发展历程 + +[![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\1.png](assets/1.png)]() + +**编译型与解释型** +常见编译型语言 c c++ java +常见解释型语言 shell php python ruby perl + +interpreted -- 解释型 + +​ Python 一是种解释型语言,与之相对的是编译型语言,虽然两者的区别由于字节码编译器的存在而会有所模糊。这意味着源文件可以直接运行而不必显式地创建可执行文件再运行。解释型语言通常具有比编译型语言更短的开发/调试周期,但是其程序往往运行得更慢。 + +**二进制** + 计算机能识别的语言,就叫做机器语言,简称机器码。 + +​ 二进制表示,可以直接被机器识别,上个世纪50年代之前,工程师直接将二进制机器码和数值编写在打孔卡上,通过读卡机读入计算机存储器,然后执行。 + +[![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\2.png](assets/2.png)]() +**汇编语言** + 为了便于阅读,就将机器代码以英文字符串来表示,于是出现了汇编语言 + +**高级语言** + 一开始人们只用汇编语言进行程序开发。所以只需要将汇编语言翻译为机器语言就可以了。这是相当直截了当的过程,因为汇编语言的助记符和机器指令是一一对应的关系。所以只需要完成一个能够自动查表并转换的程序即可。很快,这样的程序就被发明了出来。称之为"汇编器" + +​ 将常用的一些程序结构编写成对应的助记符,在需要时就使用这个助记符,于是,又在汇编器中引入了宏指令。 +宏的引入,催生了程序结构化表达。 + +​ 结构化表达的方式,给了一些计算机科学人员一些启发。能不能更进一步,使用完全结构化,脱离某个对应机器平台的形式化语言来描述一个源程序?于是,就有了高级语言及其编译器。 + +​ 开发人员利用高级语言编写程序,然后利用对应的编译器生成中间代码,最后再将中间代码变成机器码。中间代码可以是等价的汇编代码,也可以是其它类型的代码例如JVM 的字节码。 + +​ 最终处理中间代码的程序可以是一个对应平台的汇编器,也可以是一个解释器。 + +​ 将编译的最终产物都视为一系列可以被执行的二进制机器码。 + +**静态语言和动态语言** +`静态语言` + C、C++、C#、Java + +​ **变量需要声明类型,变量不能改变类型** +​ 比如:int x= 1 + +​ 需要先编译,在运行 + +`动态语言`(脚本语言) + shell python php + +​ **使用变量前不需要声明类型** +​ 比如:x =1 +​ 不需要编译,用解释器解释后运行 + +**Python** + Python源码 —> 编译器(解释器) —> 字节码 —> 编译器 —> 机器码 + +## 二、Python简史 + +Python是开源(open source)运动的一个成功案例。 + +**Python起源** + Python作者: Guido von Rossum,荷兰人. 05年加入Google. + +​ 2013年1月从Google离职并加入Dropbox,现就职于Dropbox. + +​ 1982年,Guido从阿姆斯特丹大学(University of Amsterdam)获得了数学和计算机硕士学位。然而,尽管他算得上是一位数学家,但他更加享受计算机带来的乐趣。用他的话说,尽管拥有数学和计算机双料资质,他总趋向于做计算机相关的工作,并热衷于做任何和编程相关的活儿。 + +​ [![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\1.png](assets/1-1600220045873.png)]() + +​ 在那个时候,他接触并使用过诸如Pascal、C、 Fortran等语言。这些语言的基本设计原则是让机器能更快运行。在80年代,虽然IBM和苹果已经掀起了个人电脑浪潮,但这些个人电脑的配置很低 (在今天看来)。比如早期的Macintosh,只有8MHz的CPU主频和128KB的RAM,一个大的数组就能占满内存。所有的编译器的核心是做优化,以便让程序能够运行。为了增进效率,语言也迫使程序员像计算机一样思考,以便能写出更符合机器口味的程序。在那个时代,程序员恨不得用手榨取计算机每一寸的能力。有人甚至认为C语言的指针是在浪费内存。至于动态类型,内存自动管理,面向对象…… 别想了,那会让你的电脑陷入瘫痪。 + +​ 然而,这种思考方式让Guido感到苦恼。Guido知道如何用C语言写出一个功能,但整个编写过程需要耗费大量的时间 (即使他已经准确的知道了如何实现)。他的另一个选择是shell。Bourne Shell作为UNIX系统的解释器(interpreter)已经长期存在。UNIX的管理员们常常用shell去写一些简单的脚本,以进行一些系统维护的工作,比如定期备份、文件系统管理等等。shell可以像胶水一样,将UNIX下的许多功能连接在一起。许多C语言下上百行的程序,在shell下只用几行就可以完成。然而,shell的本质是调用命令。它并不是一个真正的语言。比如说,shell没有数值型的数据类型,加法运算都很复杂。总之,shell不能全面的调动计算机的功能。 + +​ Guido希望有一种语言,这种语言能够像C语言那样,能够全面调用计算机的功能接口,又可以像shell那样,可以轻松的编程。ABC语言让Guido看到希望。ABC是由荷兰的CWI (Centrum Wiskunde & Informatica, 数学和计算机研究所)开发的。Guido在CWI工作,并参与到ABC语言的开发。ABC语言以教学为目的。与当时的大部分语言不同,ABC语言的目标是“"用户感觉更好”"ABC语言希望让语言变得容易阅读,容易使用,容易记忆,容易学习,并以此来激发人们学习编程的兴趣。 + + 比如下面是一段来自Wikipedia的ABC程序,这个程序用于统计文本中出现的词(word)的总数: + +```ABC +a equal b + HOW TO RETURN words document: + PUT {} IN collection + FOR line IN document: + FOR word IN split line: + IF word not.in collection: + INSERT word IN collection + RETURN collection +``` + + HOW TO用于定义一个函数。一个Python程序员应该很容易理解这段程序。ABC语言使用冒号(:)和缩进来表示程序块(C语言使用{}来表示程序块)。行尾没有分号。for和if结构中也没有括号()。如果将HOW TO改为def,将PUT行改为collection = [],将INSERT行改为collection.append(word),这就几乎是一个标准的Python函数。上面的函数读起来就像一段自然的文字。 + +​ 尽管已经具备了良好的可读性和易用性,ABC语言最终没有流行起来。在当时,ABC语言编译器需要比较高配置的电脑才能运行。而这些电脑的使用者通常精通计算机,他们更多考虑程序的效率,而非它的学习难度。除了硬件上的困难外,ABC语言的设计也存在一些致命的问题: +​ 1. 可拓展性差。ABC语言不是模块化语言。如果想在ABC语言中增加功能,比如对图形化的支持,就必须改动很多地方。 +​ 2. 不能直接进行IO。ABC语言不能直接操作文件系统。尽管你可以通过诸如文本流的方式导入数据,但ABC无法直接读写文件。输入输出的困难对于计算机语言来说是致命的。你能想像一个打不开车门的跑车么? +​ 3. 过度革新。ABC用自然语言的方式来表达程序的意义,比如上面程序中的HOW TO (如何)。然而对于程序员来说,他们更习惯用function或者define来定义一个函数。同样,程序员也习惯了用等号(=)来分配变量。这尽管让ABC语言显得特别,但实际上增加了程序员的学习难度 (程序员大都掌握不止一种语言)。 +​ 4. 传播困难。ABC编译器很大,必须被保存在磁带(tape)上。当时Guido在访问的时候,就必须有一个大磁带来给别人安装ABC编译器。 这样,ABC语言就很难快速传播。 +​ [![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\2.png](assets/2-1600220045874.png)]() +​ IBM tape drive:读写磁带 + +​ 1989年,为了打发圣诞节假期,Guido开始写Python语言的编译/解释器。Python来自Guido所挚爱的电视剧Monty Python's Flying Circus (BBC1960-1970年代播放的室内情景幽默剧,以当时的英国生活为素材)。他希望这个新的叫做Python的语言,能实现他的理念(一种C和shell之间,功能全面,易学易用,可拓展的语言)。Guido作为一个语言设计爱好者,已经有过设计语言的(不很成功)的尝试。这一次,也不过是一次纯粹的hacking行为。 + +**Python的诞生** + 1991年,第一个Python编译器(同时也是解释器)诞生。它是用C语言实现的,并能够调用C库(.so文件)。从一出生,Python已经具有了:类(class),函数(function),异常处理(exception),包括表(list)和词典(dictionary)在内的核心数据类型,以及模块(module)为基础的拓展系统。 + [![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\3.png](assets/3.png)]() + 最初的Python logo: 由Guido的兄弟Just von Rossum设计 + + +​ Python语法很多来自C,但又受到ABC语言的强烈影响。来自ABC语言的一些规定直到今天还富有争议,比如强制缩进。但这些语法规定让Python容易读。另一方面,Python聪明的选择服从一些惯例(特别是C语言的惯例)。比如使用等号赋值,使用def来定义函数。Guido认为,如果"常识"上确立的东西,没有必要过度纠结。 + +​ Python从一开始就特别在意可拓展性(extensibility)。Python可以在多个层次上拓展。从高层上,你可以引入.py文件。在底层,你可以引用C语言的库。Python程序员可以快速的使用Python写.py文件作为拓展模块。但当性能是考虑的重要因素时,Python程序员可以深入底层,写C程序,编译为.so文件引入到Python中使用。Python就好像是使用钢构建房一样,先规定好大的框架。而程序员可以在此框架下相当自由的拓展或更改。 + +​ 最初的Python完全由Guido本人开发。Python得到Guido同事的欢迎。他们迅速的反馈使用意见,并参与到Python的改进。Guido和一些同事构成Python的核心团队。他们将自己大部分的业余时间用于hack Python (也包括工作时间,因为他们将Python用于工作)。随后,Python拓展到CWI之外。Python将许多机器层面上的细节隐藏,交给编译器处理,并凸显出逻辑层面的编程思考。Python程序员可以花更多的时间用于思考程序的逻辑,而不是具体的实现细节 (Guido有一件T恤,写着:人生苦短,我用Python)。这一特征吸引了广大的程序员。Python开始流行。 + +​ 我们不得不暂停我们的Python时间,转而看一看这时的计算机概况。1990年代初,个人计算机开始进入普通家庭。Intel发布了486处理器,windows发布window 3.0开始的一系列视窗系统。计算机的性能大大提高。程序员开始关注计算机的易用性 (比如图形化界面)。 +[![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\4.png](assets/4.png)]() +​ Windows 3.0 +​ 由于计算机性能的提高,软件世界也开始随之改变。硬件足以满足许多个人电脑的需要。硬件厂商甚至渴望高需求软件的出现,以带动硬件的更新换代。C++和Java相继流行。C++和Java提供了面向对象的编程范式,以及丰富的对象库。在牺牲了一定的性能的代价下,C++和Java大大提高了程序的产量。语言的易用性被提到一个新的高度。我们还记得,ABC失败的一个重要原因是硬件的性能限制。从这方面说,Python要比ABC幸运许多。 + +​ 另一个悄然发生的改变是Internet。1990年代还是个人电脑的时代,windows和Intel挟PC以令天下,盛极一时。尽管Internet为主体的信息革命尚未到来,但许多程序员以及资深计算机用户已经在频繁使用Internet进行交流 (包括email和newsgroup)。Internet让信息交流成本大大下降。一种新的软件开发模式开始流行:开源 (open source)。程序员利用业余时间进行软件开发,并开放源代码。1991年,Linus在comp.os.minix新闻组上发布了Linux内核源代码,吸引大批hacker的加入。Linux和GNU相互合作,最终构成了一个充满活力的开源平台。 + +​ 硬件性能不是瓶颈,Python又容易使用,所以许多人开始转向Python。Guido维护了一个maillist,Python用户就通过邮件进行交流。Python用户来自许多领域,有不同的背景,对Python也有不同的需求。Python相当的开放,又容易拓展,所以当用户不满足于现有功能,很容易对Python进行拓展或改造。随后,这些用户将改动发给Guido,并由Guido决定是否将新的特征加入到Python或者标准库中。如果代码能被纳入Python自身或者标准库,这将极大的荣誉。Python自身也因此变得更好。(Guido不得不作出许多决定,这也是他被称为Benevolent Dictator For Life的原因) + +​ Python被称为"Battery Included",是说它以及其标准库的功能强大。这些是整个社区的贡献。Python的开发者来自不同领域,他们将不同领域的优点带给Python。比如Python标准库中的正则表达(regular expression)是参考Perl,而lambda, map, filter, reduce函数参考Lisp。Python本身的一些功能以及大部分的标准库来自于社区。Python的社区不断扩大,进而拥有了自己的newsgroup,网站(python.org),以及基金 (Python Software Foundation)。从Python 2.0开始,Python也从maillist的开发方式,转为完全开源的开发方式。社区气氛已经形成,工作被整个社区分担,Python也获得了更加高速的发展。 (由于Guido享有绝对的仲裁权,所以在Python早期maillist的开发时代,不少爱好者相当担心Guido的生命。他们甚至作出假设:如果Guido挂了的话,Python会怎样。见[If Guido was hit by a bus](http://www.python.org/search/hypermail/python-1994q2/1040.html)) + + 到今天,Python的框架已经确立。Python语言以对象为核心组织代码(Everything is object),支持多种编程范式(multi-paradigm),采用动态类型(dynamic typing),自动进行内存回收(garbage collection)。Python支持解释运行(interpret),并能调用C库进行拓展。Python有强大的标准库 (battery included)。由于标准库的体系已经稳定,所以Python的生态系统开始拓展到第三方包。这些包,如Django, web.py, wxpython, numpy, matplotlib,PIL,将Python升级成了物种丰富的热带雨林。 + +​ 今天Python已经进入到3.0的时代。由于Python 3.0向后不兼容,所以从2.0到3.0的过渡并不容易。另一方面,Python的性能依然值得改进,Python的运算性能低于C++和Java(见[Google的讨论](https://groups.google.com/forum/?fromgroups#!topic/unladen-swallow/TtvEBvVEZD4))。Python依然是一个在发展中的语言。我期待看到Python的未来。 + +**Python启示录** + Python崇尚优美、清晰、简单,是一个优秀并广泛使用的语言 (TIOBE语言排行第八,Google的第三大开发语言,Dropbox的基础语言,豆瓣的服务器语言)。这个世界并不缺乏优秀的语言,但Python的发展史作为一个代表,带给我许多启示。 + +​ 在Python的开发过程中,社区起到了重要的作用。Guido自认为自己不是全能型的程序员,所以他只负责制订框架。如果问题太复杂,他会选择绕过去,也就是cut the corner。这些问题最终由社区中的其他人解决。社区中的人才是异常丰富的,就连创建网站,筹集基金这样与开发稍远的事情,也有人乐意于处理。如今的项目开发越来越复杂,越来越庞大,合作以及开放的心态成为项目最终成功的关键。 + +​ Python从其他语言中学到了很多,无论是已经进入历史的ABC,还是依然在使用的C和Perl,以及许多没有列出的其他语言。可以说,Python的成功代表了它所有借鉴的语言的成功。同样,Ruby借鉴了Python,它的成功也代表了Python某些方面的成功。每个语言都是混合体,都有它优秀的地方,但也有各种各样的缺陷。同时,一个语言"好与不好"的评判,往往受制于平台、硬件、时代等等外部原因。程序员经历过许多语言之争。我想,为什么不以开放的心态和客观的分析,去区分一下每个语言的具体优点缺点,去区分内部和外部的因素。说不定哪一天发现,我不喜欢的某个语言中,正包含了我所需要的东西。 + +​ 无论Python未来的命运如何,Python的历史已经是本很有趣的小说。 + +## 三、Python特性 + +1. 面向对象的特性 + 面向对象的程序设计抽象出对象的行为和属性,把行为和属性分离开,但是又合理的组织在一起。它消除了 + 保护类型、抽象类、接口等面向对象的元素,使得面向对象的概念更容易理解。 + +2. 简单性 + 没有分号,使用缩进的方式分隔代码,代码简洁,短小,易于阅读。 + +3. 内置的数据结构 + 类似于Java中集合类的功能。python的数据结构包括元组,列表,字典等。元组相当于“"读”"数组,列表 + 可以作为可变长度的数组使用,字典相当于java中的hashtable类型。 + +4. 健壮性 + 提供异常退出机制,能捕获程序的异常情况。 + +5. 跨平台性 + python会先先编译成与平台相关的二进制码,然后再解释执行,这种方式和java类似。 + +6. 可拓展性 + python是用c开发的语言,因此可以使用c扩展python,可以给python添加新的模块、新的类。同时 + python可以嵌入到c,c++语言开发的项目中,使语言具备脚本语言的特性。 + +7. 动态性 + python不需要另外声明变量,直接赋值即可以创建一个新的变量 + +8. 强类型语言 + python会根据赋值表达式的内容决定变量的数据类型。python在内部建立了管理这些变量的机制,出现在 + 同一个表达式的不同类型的变量需要做类型转换。 + +9. 应用广泛 + python有许多第三方的库支持。例如:PIL库应用于图像处理,numpy库应用于数学计算,wxpython库应 + 用于GUI程序的设计,Django库应用于web程序的开发等。 + + + + + +c c++ java python golang + + + +**各种流行语言hello world对比:** + +```bash +#!/usr/bin/env bash +echo "hello world" +``` + + + +```c +# cat HelloWorld.c +#include +int main(int agrc,char *agrv[]){ + int language = 1; + printf("Hello World!I am C! language: %d\n", language); + return 0; +} +``` + +```c++ +# cat HelloWorld.c++ +#include +using namespace std; +int main(){ + int language = 2; + cout << "Hello World! I am C++! Language: " << language <>> import this + The Zen of Python + Python 之禅 + + Beautiful is better than ugly. + 美胜于丑 + + Explicit is better than implicit. + 显胜于隐 + + Simple is better than complex. + 简胜于繁 + + Complex is better than complicated. + 繁胜于杂 + + Flat is better than nested. + 平胜于迭 + + Sparse is better than dense. + 疏胜于密 + + Readability counts. + 读胜于写 + + Special cases aren't special enough to break the rules. + 规则胜于特例 + + Although practicality beats purity. + 实用胜于单纯 + + Errors should never pass silently. + 告错胜于沉默 + + Unless explicitly silenced. + 沉默胜于吵闹 + + In the face of ambiguity, refuse the temptation to guess. + 拒绝胜于猜测 + + There should be one-- and preferably only one --obvious way to do it. + 唯一胜于显然 + + Although that way may not be obvious at first unless you're Dutch. + 显然不是荷兰 + + Now is better than never. + 现在胜于永不 + + Although never is often better than *right* now. + 永不胜于匆猝 + + If the implementation is hard to explain, it's a bad idea. + 凡值得说,必易于说 + + If the implementation is easy to explain, it may be a good idea. + 反之则不然 + + Namespaces are one honking great idea -- let's do more of those! + 名可名, 请常名 + +• 优美胜于丑陋(Python 以编写优美的代码为目标) +• 明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似) +• 简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现) +• 复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁) +• 扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套) +• 间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题) +• 可读性很重要(优美的代码是可读的) +• 即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上) +• 不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码) +• 当存在多种可能,不要尝试去猜测 +• 而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法) +• 虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido ) +• 做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量) +• 如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准) +• 命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召) + +对于翻译,我没有什么发言权。我对翻译的了解大多来自思果先生的《翻译研究》和《翻译新究》这两本书。思果先生是著名的散文家、翻译家。说来惭愧,我还未能有幸拜读他的散文,不过只是这两本翻译论著就已经感受到老人家文字功底之深了。每次读都会觉得很舒服,仿佛先生坐在面前谆谆教导翻译的经验,时常如醍醐灌顶,发出“哦,原来还能这样翻译啊”的感叹。我最喜欢的是他老人家说的我们翻译要翻译得像中文这种思想,我想翻译毕竟是给中国人看的嘛,尽量不要让读者读译文读的太辛苦,所以有关翻译,推荐译者去读读《翻译研究》和《翻译新究》这两本书。 + +另一方面,学 Python 必须知道的一点,我觉得应该是 import this,这是什么?这就是 Python 之禅。编程语言其实就是把人类的思想翻译给机器听,Python 之禅就是这种翻译工作的理念。都说 Python 是一门优雅简洁、易学易懂的编程语言,我觉得科技界的译者同仁也可以参考,下面是我对 Python 之禅的译文。 + +Python 之禅 +Tim Peters 著 +美比丑好,明比涩强。 +简胜于繁,繁强于难。 +平言莫绕,宜疏莫密。 +行文如水,易懂为王。 +勿提特例,皆循此规。 +实虽胜纯,识错必究。 +若需留证,亦要言明。 +不明其理,追根问底。 +必有一法,可解谜题。 +汝非龟叔,求之故难。 +立足当下,行必有方。 +行难言喻,所思欠妥。 +行易言表,所思可嘉。 +名正易识,善莫大焉! + +下面,容我一句一句把我的启示说来给大家听听。 + +Beautiful is better than ugly. +美比丑好。 + +编程之美已经衍生出来了众多之美标题党。而翻译之美,百余年前严复先生提出的信达雅更是世人皆知,就算我们这些后辈没有前人那么深厚的国文功底,也别翻译得让人读得皱眉头。 + +Explicit is better than implicit. +明比涩强。 + +编程主张显性,不提倡隐性。翻译也要清清楚楚、明明白白,别拐弯抹角,让人去猜。 + +Simple is better than complex. +简胜于繁。 + +写代码要精简,翻译也不能繁琐,译文中有一些常见问题,呆鸟总结下来就是:“一个一个满天飞,你我他们说不腻。所有如果的时候,被来被去被不完。” 这是英文的习惯,我们中国人说话没这么啰里啰嗦,没必要那么老实地按原文译出。 + +Complex is better than complicated. +繁强于难。 + +当码农已经很难了,代码写得尽量让同事和未来的自己读起来轻松一点,算得上功德。翻译更是,因为读者更多,不能让不懂英文的人读起来觉得译文比英文还难理解,最后被逼得自学英语去读英文原著。我算是其中一个。 + +Flat is better than nested. +平言莫绕。 + +编程讲究扁平,不鼓励嵌套,翻译也可以这么干,最好像梯田一样平铺直叙,别搞得如九连环一般,要烦劳读者去解。 + +Sparse is better than dense. +宜疏莫密。 + +编程说的是不要想着用一行代码实现过多的功能,多些写几行没关系,看的清楚,易于理解。我们中文也不喜欢大长句子,一段话几十上百字一逗到底,甚至都不带打嗑呗儿,那可不行,读起来心累。 + +Readability counts. +行文如水,易懂为王。 + +编程也好翻译也罢,越容易让人读明白越好! + +Special cases aren't special enough to break the rules. +勿提特例,皆循此规。 + +没有规矩,不成方圆,写代码讲究语言规则,多一个字母,少一个空格,都会报错。翻译这点就宽容多了,没有编译一说,但也不能因此就老拿原文就是怎样怎样说事儿,中文有中文的行文规矩,虽然不需要编译,也做不到译者前辈改译文如重译的境界,但也要多读几遍译文,自己编译一下。 + +Although practicality beats purity. +Errors should never pass silently. +实虽胜纯,识错必究。 + +这里说的是实用性比语言的纯粹更重要,但发现错误也一定要说明清楚,计算机是可以 Debug 的,翻译没有,不过我们有万千读者,我希望读者能多与译者沟通,指正勘误,帮助译者优化译文,在此,呆鸟先拜谢了。 + +Unless explicitly silenced. +若需留证,亦要言明。 + +编程有注释,翻译有译注。有些英文典故也好,俗语也罢,实在用中文解释不通的,可以用译注说明,起码也算证明这是经过译者思考了的。 + +In the face of ambiguity, refuse the temptation to guess. +不明其理,追根问底。 + +这里只说翻译,一定要多读原文,读不懂或理解不清的要多读几遍,多查字典,按思果先生的说法,一本字典是不够的,要想译好文章,多查字典才行。好在我们现在有互联网了,查单词、查典故、查人物、查事件都比当年方便百倍,所以不懂莫猜,请多查多验。 + +There should be one — and preferably only one — obvious way to do it. +Although that way may not be obvious at first unless you're Dutch. +必有一法,可解谜题。汝非龟叔,求之故难。 + +Dutch 指的是龟叔,Python 的生身父母,荷兰人,大神!所以这两句可以这么认为,原文只有一个,译文也应该只有一个,好的译文就像一字千金的《吕氏春秋》一样,改一字都会破坏整体的美感,你做不到,那是因为你不是翻译大神!好吧,我承认,我现在还理解不了这种境界,貌似除了吕不韦,也还没听谁再这么说过,再说 Python 也一直在优化,所以我还是接着改译文吧。 + +Now is better than never. +Although never is often better than right now. +立足当下,行必有方。 + +这句话的意思呆鸟觉得应该是,现在开始做,比永远都不做强。但永远都不做,比想起来就干,不准备、不思考、没方向的蛮干、胡干要强。也就是说,翻译的不好,还不如别翻译,貌似很多事都是如此。 + +If the implementation is hard to explain, it's a bad idea. +If the implementation is easy to explain, it may be a good idea. +行难言喻,所思欠妥。行易言表,所思可嘉。 + +这句话好理解,译文说的明白,好懂易读就能算好译文了,晦涩难懂,就是糟糕的译文。 + +Namespaces are one honking great idea — let's do more of those! +名正易识,善莫大焉! + +命名空间是编程的事情,在翻译里可以当它说的是名词,已经被大家接受的名词不难,难的是一些少见多怪的名词,比如 Informational Interview,绞尽脑汁翻译成信息化约谈,网上也有翻译成信息化面试的,实际上人家说的是面试前找公司里的招聘经理或部门员工,约出来喝喝咖啡聊聊天,认识一下,了解下公司,老外喜欢这么干,国内这样干的应该都是比较高层了,我等底层人士估计约不出来。所以这个词很少见,很难翻译,求指教。还有诸如 take-home assignment、democratize access、raw intelligence、hustle and grit 这样的,真是叫人不知道该怎么下手好,所以说,把名词翻译好了,真是善莫大焉了。 + +``` + +python之禅乃是python中的彩蛋之一,其实还有其他彩蛋 +**彩蛋2:反地心引力漫画** +\>>> import antigravity +导入 antigravity,浏览器会跳转到一副漫画网页 http://xkcd.com/353/,漫画非常有意思。 +[![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\1.png](assets/1-1600221954979.png)]() + +**彩蛋3:Hello world!** + +```python +>>> import __hello__ +Hello world! +``` + +**彩蛋4:No chance!** + +想当年我写得了一手流利的 C 代码,大括号用的出神入化,无处不括号成了我写代码的风格… + +想当年我还和别人为“大括号是放在一行结尾还是另起一行”争论不休,撸起袖子,指点江山激扬文字… + +而我接触了 Python 以后,这门神奇的语言,竟然省去了大括号,我无比想念它,为此我还吟诗一首…啊,大括号~我,想念你! + +后来我发现了 braces 库可以使用大括号的功能,我激动的像个帕金森症的晚期患者,哆里哆嗦的导入库,然后…[![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\2.png](assets/2-1600221954979.png)]() +[![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\3.png](assets/3-1600221954979.png)]() + +## 五、Python 家族 + +**CPython** + **CPython是标准Python**,也是其他Python编译器的参考实现。**通常提到"Python"一词,都是指CPython**。 +CPython由C编写,将Python源码编译成CPython字节码,由虚拟机解释执行。没有用到JIT等技术,垃圾回收方面 +采用的是引用计数。 + 所以当有人问道Python是解释执行还是编译执行,可以这样回答:Python(CPython)将Python源码编译成 +CPython字节码,再由虚拟机解释执行这些字节码。 + 如果需要广泛用到C编写的第三方扩展,或让大多数用户都能直接使用你的Python代码,那么还是使用CPython +吧。 + +**Jython** + Jython在JVM上实现的Python,由Java编写。Jython将Python源码编译成JVM字节码,由JVM执行对应的字节码。因此能很好的与JVM集成,比如利用JVM的垃圾回收和JIT,直接导入并调用JVM上其他语言编写的库和函数。 +对于想在JVM上使用Python简化工作流程,或者出于某些原因需要在Python语言中使用Java的相关代码,同时无 +需用到太多CPython扩展的用户来说,极力推荐Jython。 + IronPythonIronPython与Jython类似,所不同的是IronPython在CLR上实现了Python,即面向.NET平台,由C#编写。IronPython将源码编译成TODO CLR,同样能很好的与.NET平台集成。即与Jython相同,可以利用.NET框架的 +JIT、垃圾回收等功能,能导入并调用.NET上其他语言编写的库和函数。IronPython默认使用Unicode字符串。 + 另外,Python Tools for Visual Studio可以将CPython和IronPython无缝集成进VS中。如果仅需要在Windows上开发较大的Python项目。条件允许的情况下,IronPython是个不错的选择。 + +**PyPy** + 这里说的PyPy是指使用RPython实现,利用Tracing JIT技术实现的Python,而不是RPython工具链。PyPy可以选 +择多种垃圾回收方式,如标记清除、标记压缩、分代等。 + 相对于CPython,PyPy的性能提升非常明显,但对第三方模块的支持真心是弱爆了。比如无法很好的支持使用 +CPython的C API编写的扩展,完全不支持使用SWIG、SIP等工具编写的扩展。就连NumPy,也要在编译器的层面 +上从头实现。即使实现了,也只能在Python层面中使用,无法供其他第三方模块在非Python环境中使用。关于 +PyPy,后续会尝试用一篇完整的文章来介绍。不过我的这一篇文章中对PyPy和下面的Pyston有更详细的描述。 + +**Pyston** + +​ Pyston由Dropbox开发,使用C++11编写,采用Method-at-a-time-JIT和Mark Sweep——Stop the World的GC技术。Pyston使用类似JavaScript V8那样的多层编译,其中也用到了LLVM来优化代码。Pyston正在发展中,还不成 +熟。但其前景是非常值得看好的,如果没像Google的Unladen Swallow那样死掉的话。 + +## 六、Python应用场景 + +1. 网站运维是Python(继Bash,Perl之后)的一大领域。 +2. 抓取第三方数据是Python爬虫的领域。 +3. 金融数据分析。 +4. 网站中许多核心都是C/C++/Java开发的,如Redis,Memcached,ngnix,消息队列,Hadoop等。但是客户端中Python必须列入其中。 +5. Python有许多实现(利用其他语言来写Python解释器),不仅仅是CPython。它可以基于Java,C,Python自己,C#,Ruby,Javascript等各个语言制作。可以这么说,Python的底层实现语言是最丰富的,绝对没有之一。所以它可以和C/C++/Java/C#/Ruby/Javascript等各类语言直接交换数据。不仅仅通过REST/JSON/XML交换。Java/C/C#/Ruby/Javascript使用的场景它都可以插足 + +**Windows编程** + Python不仅可以在Unix类型的操作系统上应用,同样可以在Windows系统里有很好的表现。通过添加PythonWin模块,就可以通过COM 形式调用和建立各种资源,包括调用注册表、ActiveX控件以及各种COM等工作,最常见的例子就是通过程序对Office文档进行处理,自动生成文档 和图表。 +通过Python,还可以利用py2exe模块生成exe应用程序。还有许多其他的日常维护和管理工作也可以交给Python来做,从而减少维护的工作 量。利用Python,你还可以开发出象VB,VC,Delphi那样的GUI程序,但却可以在多个平台上执行。这在许多方面并不逊色于Java。 + +**多媒体** + 利用PIL、Piddle、ReportLab等模块,你可以处理图象、声音、视频、动画等,从而为你的程序添加亮丽的光彩。动态图表的生成、统计分析图 表都可以通过Python来完成。另外,还有OpenGL。利用PyOpenGl模块,你可以非常迅速的编写出三维场景。 + +**科学计算** + Python可以广泛的在科学计算领域发挥独特的角色。有许多模块可以帮助你在计算巨型数组、矢量分析、神经网络等方面高效率完成工作。尤其是在教育科研方面,可以发挥出独特的优势。 + +**网络编程** + Python可以非常方便的完成网络编程的工作,提供了众多的解决方案和模块,可以非常方便的定制出自己的服务器软件,无论是c/s,还是b/s模式,都有很好的解决方法。 + +**图形用户界面** + Python可以非常方便的实现GUI编程,通过Tkinter,wxPython,QT等等模块,你就可以根据需要编写出强大的跨平台的用户界面程序。 + +**开发环境与编辑器** + Python程序的开发工具较多,既有IDLE,PythonWin这样的免费工具, 也有一些商业工具 + 集成开发环境(IDE): + IDLE:这是Python里边自带的,基本上可以满足一般开发需要,请参考cnIDLE。 + PythonWin:这是基于Windows平台的编辑开发环境,基本上可以满足一般开发需要。 + PythonWorks Pro + Wing IDE + Komodo + 代码编辑器: + LEO:完全由Python编写的程序代码编写辅助工具,可运行在多种操作系统中,支持独特的程序代码管理方式。 + gVim:相当专业的代码编辑器,可运行在多种操作系统中,支持Python扩展。 + Emacs:Unix系统中常用的工具。 + SciTE:简单易用的代码编辑器,支持unicode编辑。 + +**嵌入和扩展** + Python可以嵌入到其它应用程序中,也可以通过C/C++编写扩展模块,从而可以提高程序的运行速度或者完成只有通过C/C++才能完成的工作。现在 Python已经可以和C#相结合,并且结合到Visual Studio里边,实现微软的.Net思想。如果你会C语言,再学习Python,这将是一个非常棒的一种选择。 + 如果你掌握了Python,想在Java里应用它,你可以采用Jython。Jython是采用Java语言实现的Python。这样,你只 要按照Python的语法,就可以调用Java的各种类库,快速的编写出基于Java的程序。也就是通过Jython,编写Java程序。这样就可以更为 快速的实现Java的功能。Python在面向对象方面和Java是相通的。 + 除了c/c++和java, Python 目前还可以和Delphi、VB结合。 + +**游戏编程** + Python在很早的时候就是一种游戏编程的辅助工具。在《星球大战》中扮演了重要的角色。在"贝斯(Abyss)"、"星球之旅(Star Trek)"、"Indiana Jones"超级大片中担当特技和动画制作的工业光魔公司(Industrial Light)就采用Python制作商业动画。目前,通过Python完全可以编写出非常棒的游戏程序。 + +**企业与政务应用** + 目前,Python已经成功的实现企业级应用,在全球,已经有很多公司采用Python进行企业级软件的开发和应用,比如:ERP和CRM这样的应用。同时,通过Python技术,成功的实现了许多政务应用。 + +**比较有名的网站或应用** + 其中有一些是用python进行开发,有一些在部分业务或功能上使用到了python,还有的是支持python作为扩展脚本语言。数据大部分来自Wikepedia和Quora。 +[![file://C:\Users\86186\AppData\Local\Temp\.A5M1Q0\1.png](assets/1-1600222653676.png)]() + Reddit - 社交分享网站,最早用Lisp开发,在2005年转为python + Dropbox - 文件分享服务 + 豆瓣网 - 图书、唱片、电影等文化产品的资料数据库网站 + Django - 鼓励快速开发的Web应用框架 + Fabric - 用于管理成百上千台Linux主机的程序库 + EVE - 网络游戏EVE大量使用Python进行开发 + Blender - 以C与Python开发的开源3D绘图软件 + BitTorrent - bt下载软件客户端 + Ubuntu Software Center - Ubuntu 9.10版本后自带的图形化包管理器 + YUM - 用于RPM兼容的Linux系统上的包管理器 + Civilization IV - 游戏《文明4》 + Battlefield 2 - 游戏《战地2》 + Google - 谷歌在很多项目中用python作为网络应用的后端,如Google Groups、Gmail、 + Google Maps等,Google App Engine支持python作为开发语言 + NASA - 美国宇航局,从1994年起把python作为主要开发语言 + Industrial Light & Magic - 工业光魔,乔治·卢卡斯创立的电影特效公司 + Yahoo! Groups - 雅虎推出的群组交流平台 + YouTube - 视频分享网站,在某些功能上使用到python + Cinema 4D - 一套整合3D模型、动画与绘图的高级三维绘图软件,以其高速的运算和强大 + 的渲染插件著称 + Autodesk Maya - 3D建模软件,支持python作为脚本语言 + gedit - Linux平台的文本编辑器 + GIMP - Linux平台的图像处理软件 + Minecraft: Pi Edition - 游戏《Minecraft》的树莓派版本 + MySQL Workbench - 可视化数据库管理工具 + Digg - 社交新闻分享网站 + Mozilla - 为支持和领导开源的Mozilla项目而设立的一个非营利组织 + Quora - 社交问答网站 + Path - 私密社交应用 + Pinterest - 图片社交分享网站 + SlideShare - 幻灯片存储、展示、分享的网站 + Yelp - 美国商户点评网站 + Slide - 社交游戏/应用开发公司,被谷歌收购 + +## 七、Python编程风格 + +​ 这篇文档改编自Guido最初的《Python风格指南》一文,并从《Barry's style guide》中添加了部分内容。在有冲突的地方,应以Guido风格为准。这篇PEP仍然尚未完成(实际上,它可能永远都不会完成)。 + +​ 在这篇风格指导中的一致性是重要的。在一个项目内的一致性更重要。在一个模块或函数内的一致性最重要。但最重要的是:知道何时会不一致——有时只是没有实施风格指导。当出现疑惑时,运用你的最佳判断,看看别的例子,然后决定怎样看起来更好。并且要不耻下问! + +a = 8 + +a=8 + +{"a" : 8, "b":9} + +**打破一条既定规则的两个好理由:** +1、当应用这个规则是将导致代码可读性下降,即便对某人来说,他已经习惯于按这条规则来阅读代码了。 +2、为了和周围的代码保持一致而打破规则(也许是历史原因),虽然这也是个清除其它混乱的好机会。 + +**代码的布局** +**1、缩进** + +​ 4个空格一个缩进层次。对于确实古老的代码,你不希望产生混乱,可以继续使用8空格的制表符(8-space tabs)。 + +**2、制表符还是空格** + 永远不要混用制表符和空格。最流行的Python缩进方式是仅使用空格,其次是仅使用制表符,混合着制表符和空格缩进的代码将被转换成仅使用空格。 + +​ 对于新的项目,强烈推荐仅使用空格而不是制表符。 + +**3、行的最大长度** + 周围仍然有许多设备被限制在每行80字符:而且,窗口限制在80个字符。使将多个窗口并排放置成为可能。在这些设备上使用默认的折叠方式看起来有点丑陋。因此,请将所有行限制在最大79字符,对顺序排放的大块文本(文档字符串或注释),推荐将长度限制在72字符。 + +​ 折叠长行的首选方法是使用Pyhon支持的圆括号,方括号和花括号内的行延续。如果需要,可以在表达式周围增加一对额外的圆括号,但是有时使用反斜杠看起来更好,确认恰当得缩进了延续的行。 + +**4、空行** + 用两行空行分割顶层函数和类的定义,类内方法的定义用单个空行分割,额外的空行可被用于(保守的)分割相关函数组成的群,在一组相关的单句中间可以省略空行。 + +​ 当空行用于分割方法的定义时,在‘class’行和第一个方法定义之间也要有一个空行。在函数中使用空行时,请谨慎的用于表示一个逻辑段落。 + +**5、导入** + 通常应该在单独的行中导入(Imports),例如: + No: import sys, os + Yes:import sys + import os + +​ 但是这样也是可以的: + +​ from types import StringType, ListType + + Imports 通常被放置在文件的顶部,仅在模块注释和文档字符串之后,在模块的全局变量和常量之前。 + +​ Imports应该有顺序地成组安放: + +​ 1、标准库的导入(Imports ) + +​ 2、相关的主包(major package)的导入(即,所有的email包在随后导入) + +​ 3、特定应用的导入(imports) + +​ 你应该在每组导入之间放置一个空行,对于内部包的导入是不推荐使用相对导入的,对所有导入都要使用包的绝对路径。 + +**6、表达式和语句中的空格** + Guido不喜欢在以下地方出现空格: + 紧挨着圆括号,方括号和花括号的, + +​ 如:"spam( ham[ 1 ],{ eggs:2 } )",要始终将它写成"spam(ham[1],{eggs:2})"。 + +​ 紧贴在逗号,分号或冒号前的, + +​ 要始终将它写成 "if x == 4:print x,y:x,y = y,x"。 + +​ 紧贴着函数调用的参数列表前开式括号(open parenthesis )的, + +​ 如:"spam (1)"。要始终将它写成"spam(1)"。 + +​ 紧贴在索引或切片,开始的开式括号前的, + +​ 如: "dict ['key'] = list [index]"。要始终将它写成"dict['key'] = list[index]"。 + +​ 在赋值(或其它)运算符周围的用于和其它并排的一个以上的空格,如: + + + +``` + x= 1 + y= 2 + long_variable = 3 + +要始终将它写成 + x = 1 + y = 2 + long_variable = 3 +``` + +其它建议 + 始终在这些二元运算符两边放置一个空格:赋值(=), 比较(==,<,>,!=,<>,<=, >=,in,not in,is,is not),布尔运算 (and,or,not)。 + +​ 不要在用于指定关键字参数或默认参数值的'='号周围使用空格,例如: + +``` +def complex(real, imag=0): + return magic(r=real, i=imag) +``` + +​ 不要将多条语句写在同一行上: + +``` +No: if foo == 'blah':do_blah_thing() + +Yes:if foo == 'blah': + + do_blah_thing() + +No:do_one():do_two():do_three() + +Yes:do_one() + + do_two() + + do_three() +``` + +**7、注释** + 同代码不一致的注释比没注释更差。当代码修改时,始终优先更新注释!注释应该是完整的句子,如果注释是一个短语或句子,首字母应该大写,除非他是一个以小写字母开头的标识符(永远不要修改标识符的大小写)。 + +​ 如果注释很短,最好省略末尾的句号。注释块通常由一个或多个由完整句子构成的段落组成,每个句子应该以句号结尾。你应该在句末,句号后使用两个空格 + +​ 用英语书写时,断词和空格是可用的。非英语国家的Python程序员:请用英语书写你的注释,除非你120%的确信这些代码不会被不懂你的语言的人阅读。 + +**8、注释块** + 注释块通常应用于跟随着一些(或者全部)代码并和这些代码有着相同的缩进层次。注释块中每行以‘#’和一个空格开始(除非他是注释内的缩进文本)。注释块内的段落以仅含单个‘#’的行分割。注释块上下方最好有一空行包围(或上方两行下方一行,对一个新函数定义段的注释)。 + +**9、行内注释** + 一个行内注释是和语句在同一行的注释,行内注释应该谨慎使用,行内注释应该至少用两个空格和语句分开,它们应该以'#'和单个空格开始。 + +​ 如果语意是很明了的,那么行内注释是不必要的,事实上是应该被移除的。不要这样写: + +​ x = x+1 # Increment x +​ x = x+1 # Compensate for border + +**10、文档字符串** + 应该一直遵守编写好的文档字符串的约定PEP 257 [3]。为所有公共模块,函数,类和方法编写文档字符串。文档字符串对非公开的方法不是必要的,但你应该有一个描述这个方法做什么的注释。这个注释应该在"def"这行后。 + +​ PEP 257 描述了好的文档字符串的约定。一定注意,多行文档字符串结尾的"""应该单独成行,例如: + +```python +"""Return a foobang + +Optional plotz says to frobnicate the bizbaz first。 + +""" +``` + +​ 对单行的文档字符串,结尾的"""在同一行也可以。 + +​ 对单行的文档字符串,结尾的"""在同一行也可以。 + +**11、命名约定** + Python库的命名约定有点混乱,所以我们将永远不能使之变得完全一致,不过还是有公认的命名规范的。新的模块和包(包括第三方的框架)必须符合这些标准,但对已有的库存在不同风格的,保持内部的一致性是首选的。 + +**描述:命名风格** + 有许多不同的命名风格。以下的有助于辨认正在使用的命名风格,独立于它们的作用。以下的命名风格是众所周知的: + +​ b (单个小写字母) + +​ B (单个大写字母) + +​ Lowercase(小写) + +​ lower_case_with_underscores(有下划线的小写) + +​ UPPERCASE(大写) + +​ UPPER_CASE_WITH_UNDERSCORES(有下划线的大写) + +​ CapitalizedWords (或 CapWords,CamelCase这样命名是因为可从字母的大小写分出单词。这有时也被当作StudlyCaps。 + +​ mixedCase (与CapitalizedWords的不同在于首字母小写!) + +​ Capitalized_Words_With_Underscores(有下划线的首字母大写) (丑陋!) + +另外,以下用下划线作前导或结尾的特殊形式是被公认的(这些通常可以和任何习惯组合): + +​ `_single_leading_underscore`(单个下划线作前导):弱的"内部使用(internal use)"标志。 (例如,"from M import *"不会导入以下划线开头的对象)。 + +​ `single_trailing_underscore_`(单个下划线结尾): 用于避免与Python关键词的冲突,例如:"Tkinter.Toplevel(master,class_='ClassName')"。 + +​ `__double_leading_underscore`(双下划线):从Python 1.4起为类私有名。 + +**说明:命名约定** + +​ 应避免的名字。永远不要用字符‘l’(小写字母el(就是读音,下同)),‘O’(大写字母oh),或‘I’(大写字母eye)作为单字符的变量名。在某些字体中这些字符不能与数字1和0分辨。试着在使用‘l’时用‘L’代替。 + +**模块名** + 模块应该是不含下划线的,简短的,小写的名字。因为模块名被映射到文件名,有些文件系统大小写不敏感并且截短长名字,模块名被选为相当短是重要的,这在Unix上不是问题,但当代码传到Mac或Windows上就可能是个问题了。 + +​ 当用C或C++编写的扩展模块有一个伴随Python模块提供高层(例如进一步的面向对象)接口时,C/C++模块有下划线前导(如:_socket)。Python包应该是不含下划线的,简短的,全小写的名字。 + +**类名** + 几乎不出意料,类名使用CapWords约定。内部使用的类外加一个前导下划线。 + +**异常名** + 如果模块对所有情况定义了单个异常,它通常被叫做"error"或"Error"。似乎内建(扩展)的模块使用"error"(例如:os.error),而Python模块通常用"Error" (例如:xdrlib.Error)。趋势似乎是倾向使用CapWords异常名。 + +**全局变量名** + 这些约定和在函数中的一样。模块是被设计为通过"from M import *"来使用的,必须用一个下划线作全局变量(及内部函数和类)的前缀防止其被导出(exporting)。 + +**函数名** + +​ 函数名应该为小写,可能用下划线风格单词以增加可读性。mixedCase仅被允许用于这种风格已经占优势的上下文(如:threading.py),以便保持向后兼容。 + +**方法名和实例变量** + +​ 这段大体上和函数相同:通常使用小写单词,必要时用下划线分隔增加可读性。仅为不打算作为类的公共界面的内部方法和实例使用一个前导下划线,Python不强制要求这样:它取决于程序员是否遵守这个约定。 + +​ 使用两个前导下划线以表示类私有的名字,Python将这些名字和类名连接在一起: + +​ 如果类Foo有一个属性名为_a,它不能以Foo._a访问。(固执的用户还是可以通过Foo._Foo__a得到访问权。) + +​ 通常双前导下划线仅被用于避免含子类的类中的属性名的名字冲突。 + +**继承的设计** + +​ 始终要确定一个类中的方法和实例变量是否要被公开。通常,永远不要将数据变量公开,除非你实现的本质上只是记录,人们几乎总是更喜欢代之给出一个函数作为类的界面 + +​ 同样,确定你的属性是否应为私有的。私有和非私有的区别在于模板将永远不会对原有的类(导出类)有效,而后者可以。你应该在大脑中就用继承设计好了你的类,私有属性必须有两个前导下划线,无后置下划线,非公有属性必须有一个前导下划线,无后置下划线,公共属性没有前导和后置下划线,除非它们与保留字冲突,在此情况下,单个后置下划线比前置或混乱的拼写要好,例如:class_优于class。 + +​ 最后一点有些争议:如果相比class_你更喜欢class,那么这只是一致性问题。 + +**设计建议** + +​ 单个元素(singletons)的比较,如None 应该永远用:‘is’或‘is not’来做。当你本意是"if x is not None"时,对写成"if x"要小心。例如当你测试一个默认为None的变量或参数是否被设置为其它值时,这个值也许在布尔上下文(Boolean context)中是false! + +​ 基于类的异常总是好过基于字符串的异常。模块和包应该定义它们自己的域内特定的基异常类,基类应该是内建的Exception类的子类。还始终包含一个类的文档字符串。例如: + +```python +class MessageError(Exception): +"""Base class for errors in the email package。""" +``` + +​ 使用字符串方法(methods)代替字符串模块,除非必须向后兼容Python 2.0以前的版本。字符串方法总是非常快,而且和unicode字符串共用同样的API(应用程序接口)在检查前缀或后缀时避免对字符串进行切片。用startswith()和endswith()代替,因为它们是明确的并且错误更少。例如: + +```python +No : if foo[:3] == 'bar': +Yes: if foo.startswith('bar'): +``` + +​ 例外是如果你的代码必须工作在Python 1.5.2 (但是我们希望它不会发生!),对象类型的比较应该始终用isinstance()代替直接比较类型,例如: + +```python +No: if type(obj) is type(1): +Yes: if isinstance(obj, int): +``` + +​ 对序列,(字符串,列表,元组),使用空列表是false这个事实,因此"if not seq"或"if seq"比"if len(seq)"或"if not len(seq)"好。书写字符串文字时不要依赖于有意义的后置空格。这种后置空格在视觉上是不可辨别的,并且有些编辑器会将它们修整掉。不要用==来比较布尔型的值以确定是True或False + +```python +No : if greeting == True: + +Yes: if greeting: +``` + +## 八、Shell和Python速度测试 + +下面是用shell和python分别创建10000个目录的脚本,分别用time测试运行时间 + +```python +[root@vmware1 test]# cat a.py +#!/usr/bin/env python3.8 +#coding=utf-8 +import os +for i in range(10000): + dirname = "dir"+str(i) + os.mkdir(dirname) +``` + +```bash +[root@vmware1 test]# cat a.sh +#!/bin/bash +for i in {1..10000} +do + mkdir dir$i +done +``` + + + +1.编译 解释型 + +​ 静态 动态 + +2.guido + +3.CPython是标准Python 是我们平时用的python + + + + + + + + + + + + + + + diff --git a/02-Python开发环境.md b/02-Python开发环境.md new file mode 100644 index 0000000..d63e46a --- /dev/null +++ b/02-Python开发环境.md @@ -0,0 +1,224 @@ +# 02-Python开发环境 + +python golang + +java php ruby + +c c++ + +python php bash 脚本语言 解释型语言 + +## 一、Python安装 + +现在Centos8已经取消Python2.7,默认自带Python3.6和Python3.8 + + + +windows环境安装了python3.9 + +打开python3.9的解释器 + + + + + +## 二、pip用法 + +Centos8里面必须使用pip3命令,直接使用pip不可用 + +pip是Python 包管理器 + 管理的是python第三方包 + +Python 的库 +1.标准库 + 目录/usr/lib64/python3.6 内除了site-packages其他的库都是内置标准库 +2.第三方库 + 存放目录: /usr/lib64/python3.6/site-packages + +第三方库由pip管理: + +```bash +# pip3 install 包名字 +# pip3 install requests +# pip3 install pillow +# pip3 install flask +# pip3 install django==版本号 +# pip3 uninstall 包名字 +# pip3 list 查看安装的第三方包 +``` + +​ 跨平台移动python环境的时候使用freeze收集已经安装好的模块安装到其他系统内 + +```bash +# pip3 freeze > requirements.txt 将第三方的包输出到一个文件中,文件名:requirements.txt +# pip3 install -r requirements.txt 将requirements.txt文件中的所有的第三方包一次性安装 +``` + + + +下载 pypi.org + +解压 + +cd + +python setup.py install + + + +php扩展包 pecl.php.net + +php mysql redis + +## 三、使用ipython + +```bash +python2.7 +# yum install -y epel-release +# yum search pip +# yum install python-ipython + +python3 +# yum install python3 +# yum install python3-pip +# pip3 install ipython +``` + + + +```bash +# pip3 install ipython +``` + +2版本的ipython自带tab补全,但是3版本取消掉了,解决方法如下 + +```bash +# pip3 install jedi==0.17.2 +``` + + + +## 四、IDE集成开发环境 + +常用Python IDE环境: + +​ pycharm + +​ vscode + +**vscode基本使用** + +### 1、下载安装 + +官方网站下载,按官方提示安装即可 + +![image-20200916114956638](assets/image-20200916114956638.png) + +![image-20200916115044429](assets/image-20200916115044429.png) + +### 2、安装插件 + +打开商店,安装中文简体插件 + +![image-20200916115306793](assets/image-20200916115306793.png) + +安装文档图标 + +![image-20200916115345855](assets/image-20200916115345855.png) + +### 3、基本设置 + +![image-20200916115449910](assets/image-20200916115449910.png) + +打开配置文件方式 + +![image-20200916115526379](assets/image-20200916115526379.png) + +添加如下内容到 `settings.json` 配置文件中,并按下 `Control + s` 保存** + +```json +{ + "editor.fontSize": 30, + "debug.console.fontSize": 30, + "markdown.preview.fontSize": 26, + "terminal.integrated.fontSize": 30, + // 编辑的文件 每 1 秒自动保存一次 + "files.autoSave": "afterDelay" +} +``` + +在打开文件夹创建python文件的时候会提示安装python扩展,跟随提示安装即可 + +![image-20200916120135841](assets/image-20200916120135841.png) + +### 4、配置默认 python 解释器 + +> vscode 默认选择的python 解释器是 python2.7 ,我们需要的是 python3 + +![image-20200916115826385](assets/image-20200916115826385.png) + +接下来会提示安装用于 python 语法检测的插件 `pylint` + +### 5、安装 Code Runner + +当重复执行文件的时,之前的输出在终端中不能清除,这可能会影响观看。使用 `code runner` 插件可以解决 + +1. 安装 Code Runner + +![image.png](assets/11414906-77275177467c966b.png) + +2. 配置 Run Code + +再次打开配置文件 `settings.json` 文件添加如下内容,并按下 `Control + s` 保存 + +```json + "code-runner.clearPreviousOutput": true, + "code-runner.runInTerminal": true, + // 每次运行文件之前,保存当前文件 + "code-runner.saveFileBeforeRun": true, + // 默认的语言 + "code-runner.defaultLanguage": "python", + // 每次运行文件前 保存所有的文件 + "code-runner.saveAllFilesBeforeRun": true, + // 设置 phthon3 解释器路径 + "code-runner.executorMap": { + "python": "/usr/local/bin/python3.8" + } +``` + +最终的配置文件 + +```json +{ + "workbench.iconTheme": "vscode-icons", + "editor.fontSize": 30, + "debug.console.fontSize": 30, + "markdown.preview.fontSize": 26, + "terminal.integrated.fontSize": 30, + // 编辑的文件 每 1 秒自动保存一次 + "files.autoSave": "afterDelay", + "code-runner.clearPreviousOutput": true, + "code-runner.runInTerminal": true, + "code-runner.saveFileBeforeRun": true, + "code-runner.defaultLanguage": "python", + "code-runner.saveAllFilesBeforeRun": true, + // set python path + "code-runner.executorMap": { + "python": "/usr/bin/python3.8" + } +} +``` + +## 五、pycharm + +### 1.过期刷新插件(可能不能用了) + +添加插件仓库地址https://plugins.zhile.io,然后搜索插件IDE Evarl Reset + +![image-20240222093708703](assets/image-20240222093708703.png) + +![image-20240222093751794](assets/image-20240222093751794.png) + +2.汉化插件 + +插件页面搜索chinese diff --git a/03-Python基本用法.md b/03-Python基本用法.md new file mode 100644 index 0000000..9a30f6f --- /dev/null +++ b/03-Python基本用法.md @@ -0,0 +1,404 @@ +# 03-Python基本用法 + +[TOC] + +## 一、编程模式 + +**交互模式编程** + +interactive -- 交互 + +Python 带有一个交互式解释器,即你可以在解释器提示符后输入语句和表达式,立即执行并查看其结果。只需不带参数地启动 `python` 命令(也可以在你的计算机开始菜单中选择相应菜单项)。在测试新想法或检验模块和包的时候用这种方式会非常方便(请记得使用 `help(x)`)。 + +```python +# python +Python 2.6.4 (#1, Nov 11 2014, 13:34:43) +[GCC 4.1.2 20120704 (Red Hat 5.6.2-48)] on linux2 +Type "help", "copyright", "credits" or "license" for more information. + +键入下列文字在Python提示符,然后按Enter键: +>>> print("Hello, Python!") + Hello, Python! +``` + +Python代码在执行时默认会动态加载一些内置库builtins.py + +**脚本模式编程** +调用解释器及脚本作为参数,并开始执行脚本 +写如下代码在一个test.py文件 + +```python +print("Hello, Python!") +``` + +运行程序: + +```bash +# python test.py +Hello, Python! +``` + +```bash +另一种方式执行Python脚本,修改后的test.py文件: +#!/usr/bin/python3.8 +print("Hello, Python!") + +运行程序: +# chmod +x test.py +# ./test.py +Hello, Python! +``` + + + +## 二、Python标识符 + +**作用** + +用来标识一个变量,函数,类,模块或其他对象的名称。 +一个标识符开始以字母A到Z或a到z后跟零个或多个字母下划线(_)和数字(0〜9)。 +Python标识符内不允许标点符号,如@、$、%等。 +Python区分大小写 + +**标识符命名约定:** + +一句话:只能由数字,字母和下划线组成,不能以数字开头 + +• 类名以大写字母以及所有其它标识符以小写字母。 +• 开头单个前导下划线的标识符表示由该标识符约定的意思是私有的,避免用下划线作为变量名的开始。 +• 开头两个前导下划线的标识符表示一个强烈的私有的标识符。 +• 如果标识符末尾还具有两个下划线结束时,该标识符是一个语言定义的特殊名称。 + +**保留字** + +bash: if for 等关键字 可以当作标识名称 +python: if for 等关键字 不能当作标识名称 + +保留字不可以被用作常量或变量,或任何其它标识符。所有Python关键字只包含小写字母。 + +```python +查询当前版本python中所有关键字: +>>> import keyword # 如果系统中没有这个模块,需要安装python-docs +>>> keyword.kwlist + ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield'] + +判断是否为关键字: +>>> keyword.iskeyword ('False') +此时将返回True +``` + + + +## 三、行和缩进 + +​ 一个程序员学习Python时,遇到的第一个需要注意的地方是,不使用括号来表示代码的类和函数定义块或流程控制。代码块是由行缩进,这是严格执行表示方式。 +​ 缩进位数目是可变的,但在块中的所有语句必须缩进相同的量。在这个例子中,两个功能块都很好使用: + +```python +if True: + print "True" +else: + print "False" +``` + +​ 然而,在本实例中的第二块将产生一个错误: + +```python +#!/usr/bin/env python3.8 +if True: + print ("Answer") + print ("True") +else: + print ("Answer") + print ("False") +``` + +**使用空行** + 一行只含有空格,可能带有注释,如果是空行那么Python完全忽略它。 + 在交互式解释器会话中,必须输入一个空的物理行终止多行语句。 + +**多行语句** + Python语句通常用一个新行结束。 但是,Python允许使用续行符`\`来表示该行应该继续下去(跨行)。但是包含在[],{},()括号内的陈述并不需要使用续行符`\`。 + 例如: + +```python +>>> total = (item_one + + item_two + + item_three) + +``` + +```python +>>> days = ['Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday'] +``` + +**续行符**( \ ): + Python 语句,一般使用换行分隔,也就是说一行一个语句。一行过长的语句可以使用反斜杠`\`分解成几行,比如: + +```python +# check conditions +if (weather_is_hot == 1) and \ +(shark_warnings == 0): + send_goto_beach_mesg_to_pager() +``` + + + +**单行中多条语句**: + 分号( ; ) 允许在单行写入多条语句,不管语句是否启动一个新的代码块。下面是使用分号示例: + +```python +import sys; x = 'foo'; sys.stdout.write(x + '') + +import sys +x = 'foo' +sys.stdout.write(x + '') +``` + + + +## 四、引号和注释 + +**引号** + Python接受单引号('),双引号(")和三('''或""")引用,以表示字符串常量,只要是同一类型的引号开 +始和结束的字符串。 + 三重引号可以用于跨越多个行的字符串。 + 例如,所有下列写法都是合法的: + +```python +word = 'word' +sentence = "This is a sentence." +paragraph = """This is a paragraph. It is +made up of multiple lines and sentences.""" +``` + +**注释** + "#"号之后字符是注释的一部分,Python解释器会忽略它们。 + +```python +#!/usr/bin/python +# First comment +print "Hello, Python!" # second comment +运行结果: +Hello, Python! +``` + +​ 可以使用三引号完成多行注释: + +```python +''' +comment1 +comment2 +'''' +``` + + + +## 五、读取用户输入 + +Python提供内置函数从标准输入读入一行文本,默认的标准输入设备是键盘:input() + +在 **Python3.x** 中 **raw_input( )** 和 **input( )** 进行了整合,去除了 **raw_input( )**,仅保留了 **input( )** 函数,其接收任意输入,将所有输入默认为字符串处理,并返回字符串类型。 + +**input函数** + input([prompt]) 函数从标准输入读取一个行,并返回一个字符串 + +```python +#!/usr/bin/python3.8 +str = input("请输入:") +print("你输入的内容是: ", str) + +这将提示你输入任意字符串,然后在屏幕上显示相同的字符串。当我输入"Hello Python!",它的输出如下: +请输入:Hello Python! +你输入的内容是: Hello Python! +``` + +**实例:等待用户** + 程序显示提示,按回车键退出,等待用户按下回车键: + +```python +#!/usr/bin/python3.8 +input("Press the enter key to exit.") #不接收用户输入 +在这里,一旦用户按下键时,程序结束。这是一个很好的技巧,保持一个控制台窗口打开,直到用户完成应用程序运行。 +``` + +**输入不可见密码** + +​ getpass() +​ 输入密码时,如果想要不可见,需要利用 getpass 模块中的 getpass 方法: + +```python +#!/usr/bin/env python3.8 +import getpass +pwd = getpass.getpass("请输入密码:") # 将用户输入的内容赋值给 pwd变量 +print(pwd) # 打印输入的内容 + +执行结果: + 请输入密码: + 123 +``` + +## 六、模块 + +​ 模块以磁盘文件的形式存在, 每一个 Python 脚本文件都可以被当成是一个模块。 + +​ 当一个模块变得过大, 且驱动了太多功能时,就应该考虑拆一些代码出来另外建一个模块。 + +​ 模块代码可以是一段直接执行的脚本, 也可以是一堆类似库函数的代码, 从而可以被别的模块import调用。 + +​ 模块可以包含直接运行的代码块、类定义、 函数定义或这几者的组合。 + +## 七、命令行参数 + +​ 程序可以运行时提供有关如何运行的一些基本信息。 位置变量 位置参数 + +​ 例如Python中可以使用 -h 做到这一点: + +```bash +# python3.8 -h + usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ... + Options and arguments (and corresponding environment variables): + -c cmd : program passed in as string (terminates option list) + -d : debug output from parser (also PYTHONDEBUG=x) + -E : ignore environment variables (such as PYTHONPATH) + -h : print this help message and exit + [ etc. ] +``` + +​ 你也可以设定你的脚本,它应该以这样的方式接受各种选项。 命令行参数会在以后学习,当你学会其它的Python概念之后如果想对python脚本传参数,需要模块:sys 或者 getopt + +**sys模块** + +| 用法 | 意义 | +| ------------- | -------- | +| len(sys.argv) | 参数个数 | +| sys.argv[0] | 脚本名 | +| sys.argv[1] | 参数1 | +| sys.argv[2] | 参数2 | + +```python +#vim test.py +import sys +print("脚本名:",sys.argv[0]) +for i in range(1,len(sys.argv)): + print("参数",i,sys.argv[i]) sys.argv[1] + +#python3.8 test.py hello world + 脚本名:test.py + 参数 1 hello + 参数 2 world +``` + +**python参数解包**(**unpack**): + +```python +[root@wing python]# cat unpack.py +#!/usr/bin/env python3.8 +from sys import argv + +script, first, second, third = sysargv +print(argv) +print(script) +print(first) +print(second) +print(third) + +[root@wing python]# python unpack.py 1 2 3 +['unpack.py', '1', '2', '3'] +unpack.py +1 +2 +3 +``` + +代码'script,first,second,third=argv' 表示将argv "解包(unpack)",argv本身是将所有参数放到同一个变量下面,这里是将每个参数赋予一个变量名:script, first, second, 以及third。 + +这看上去有些奇怪, 不过" 解包" 可能是最好的描述方式了。它的含义很简单:"把argv 中的东西解包,将所有的参数依次赋予左边的变量名"。 + + + +## 八、Python文件类型 + +**导语** +python常用的有3种文件类型 + 1.源代码 py + 2.字节代码 pyc + 3.优化代码 pyo + +**源代码**: + python源代码的文件以"py"为扩展名,由python程序解释,不需要编译 + +**字节代码**: + python源文件经编译后生成的扩展名为"pyc"的文件,用于隐藏代码,提高加载速度 + +什么是pyc文件: + pyc是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨平台的字节码,是由python的虚拟机来执行的,这个是类似于JAVA或者.NET的虚拟机的概念。pyc的内容,是跟python的版本相关的,不同版本编译后的pyc文件是不同的,2.5编译的pyc文件,2.4版本的python是无法执行的。 + +为什么pyc文件: + 因为py文件是可以直接看到源码的,如果你是开发商业软件的话,不可能把源码也泄漏出去吧?所以就需要编译为pyc后,再发布出去。当然,pyc文件也是可以反编译的,不同版本编译后的pyc文件是不同的,根据python源码中提供的opcode,可以根据pyc文件反编译出py文件源码,网上可以找到一个反编译python2.3版本的pyc文件的工具,不过该工具从python2.4开始就要收费了,如果需要反编译出新版本的pyc文件的话,就需要自己动手了,不过你可以自己修改python的源代码中的opcode文件,重新编译python,从而防止不法分子的破解。 + +**编译方法** +生成单个pyc文件: + +```python +方法1:代码方式 +#vim compile.py +import py_compile +py_compile.compile("hello.py") +``` + +```python +方法2:命令行 +#python3.8 -m py_compile hello.py +-m 相当于脚本中的import +``` + +> **注意**: +> 字节代码和优化代码不能直接执行,只能用解释器运行 +> 正确执行方法: +> \#python hello.pyc +> \#python hello.pyo +> 错误执行方法: +> \#./hello.pyc //这样执行会报错 + +批量生成pyc文件: + 一般,工程都是在一个目录下的,不会仅仅编译一个py文件而已,而是需要把整个文件夹下的py文件都编译为pyc文件,python提供了另一个模块:compileall 。使用方法如下: + +```python +方法1:代码方式 +import compileall +compileall.compile_dir(r'/root/src\') + +方法2:命令行方式 +# python3.8 -m compileall /root/src/ +``` + +**优化代码**: + pyo是经过优化编译后的程序,扩展名为"pyo",也可以提高加载速度,针对嵌入式系统,把需要的模块编译成pyo文件**可减少容量**,本质上和pyc没有区别,优化方法如下: + +```python +# python -O -m py_compile hello.py +``` + + + + + + + + + + + + + + + + + + + diff --git a/04-Python变量.md b/04-Python变量.md new file mode 100644 index 0000000..6d42ec9 --- /dev/null +++ b/04-Python变量.md @@ -0,0 +1,250 @@ +# 04-Python变量 + +[TOC] + +## 一、变量概念 + +​ Python中会用到许多数据,为了方便操作,需要把这些数据分别用一个简单的名字代表,方便在接下来的程序中引用。变量就是代表某个数据(值)的名称。简单点说变量就是给数据起个名 + +## 二、变量名称 + +**命名规定** + +​ 由字母数字下划线组成的,且不能以数字开头,不能使用关键字,区分大小写。 + +**关键字:** +不要以关键字命名变量 + +```python +>>> import keyword +>>> keyword.kwlist + ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] +``` + +可以用以下方法验证,返回 True 就是 Python 的关键字 + +```python +>>> keyword.iskeyword('del') + True +``` + +**命名规范:** + +``` +模块:小写字母,单词之间用_分割,比如:ad_stats.py + +包名:同模块命名规范 + +类名:单词首字母大写,比如:AdStats ConfigUtil + +全局变量:大写字母,单词之间用_分割,比如:NUMBER COLOR_WRITE + +普通变量:小写字母,单词之间用_分割,比如:this_is_a_var + + +实例变量:以_开头,其他和普通变量一样,比如:price _instance_var + +私有实例变量(外部访问会报错):以__开头(2个下划线),其他和普通变量一样,比如:__private_var + +专有变量: __开头,__结尾,一般为python的自有变量,不要以这种方式命名,比如:__doc__ __class +``` + +## 三、变量赋值 + +变量赋值是变量声明和定义的过程 +**单个变量赋值:** + +```python +#!/usr/bin/python3.8 +counter = 100 # 赋值整型 +miles = 1000.0 # 赋值浮点型 +name = "John" # 赋值字符串 + +print(counter) +print(miles) +print(name) +``` + +**多个变量赋值** + Python允许同时为多个变量赋值。例如: + +```python +a = b = c = 1 +# 创建一个整型对象,值为1,三个变量被分配到相同的内存空间上。 +``` + +​ 同时为多个变量赋不同的值。例如: + +```python +a, b, c = 1, 2, "john" +# 两个整型对象1和2分配给变量a和b,字符串对象"john"分配给变量c。 +``` + +## 四、存储方式 + + 1、一般编程语言变量存储数据的方式 + 变量是计算机内存中的一块区域,变量可以存储规定范围内的值,而且值是可变的。 + 在创建变量时会在内存中开辟一个空间。基于变量的数据类型,解释器会分配指定内存,并决定什么数据可被存储在内存中。因此,变量可以指定不同的数据类型,这些变量可以存储整数,小数或字符。 + 如c语言在声明一个变量a之后,会在内存中开辟出一块对应的空间,在此空间中可以存储不同的值,也就是给变量赋予不同的值 + +2、Python变量在内存中存储值得方式和其他编程语言不同 + 在Python中,变量名没有类型,但对象有;变量名只是对对象的引用(内部实现为指针) + +​ Python中是以数据为主,变量a只是相当于一个内存空间的标签,a=1开辟一块空间存储1,之后重新复制a=2是重新开辟出新的空间存储2,变量名称a换了个位置指向新空间中的2 + +​ 同样的地址空间可以有两个或多个标签,比如a=1,b=1实际上是a和b指向同一个地址空间 + +**地址空间** + +​ 查看变量指向内存地址空间的地址:使用id()函数 + +```python +>>> a=1 +>>> id(a) + 19882304 +>>> b=1 +>>> id(b) + 19882304 + # 发现同一个值赋值给不同变量,实际地址空间未发生变化,只是标签发生了变化 +``` + +**对象类型** + +对象都有不同的类型,用 type()函数查看 + +``` +In [9]: type(1) +Out[9]: int +1 # 值,对象本身 +``` + +**对象比较** + +```python +# 通常用 `is` 或者`==`来判断两个对象的标识是否一样,即判断两个变量绑定的是不是同一个对象 +a = 'wing' +b = a +a is b +``` + +```python +x = 'wing' +y = 'wing' +x is y +x == y +``` + +## 五、引用计数 + +在 Python 中,不用关心内存溢出问题,Python 已经帮忙实现了内存管理。 + +**注意:sys.getrefcount()获取的引用计数在2.7没问题,3.0内只对字符串生效,获取数值类型的计数不准确** + +**引用计数器** + Python内部记录着所有使用中的对象有多少引用。一个内部跟踪变量,称为一个引用计数器。当对象被创建时,就创建了一个引用计数,当这个对象不再需要时,也就是这个对象的引用计数变为0时,它被垃圾回收。(这个只是形象的说一下,并不是严格的100%正确,但是通俗的理解往往是最好的学习方式) + +**增加引用计数** + 1、当对象被创建并赋值给变量时,该对象的引用技术就被设置为1。 + 2、当同一个对象的应用或是对象又被赋值给其他变量时,或者作为参数传递给函数,方法或类实例时,或者被赋值为一个窗口对象的成员时,该对象的一个新的引用,或者称作别名,就被创建,则该对象的引用计数自动加1 + +**减少引用计数** + 1、当对象的引用被销毁时,引用计数会减少。最明显的例子就是当引用离开其作用范围时,这种情况最经常出现在函数运行结束时,所有局部变量都被自动销毁,对象的引用计数也就随之减少。 + +​ 2、当变量被赋值给另外一个对象时,源对象的引用技术也会自动减1 + +​ 3、其他造成对象的引用计数减少的方式包括使用del语句删除一个变量 + +**Python内部的引用计数使用sys.getrefcount获取** + +例子:references + +```python +>>> import sys +>>> a="ab" +>>> sys.getrefcount("ab") + 3 # 第一次结果为3 +>>> b="ab" +>>> sys.getrefcount("ab") + 4 # 第二次结果+1 +>>> b=0 # b引用了其他的对象(0),对于"ab"来讲就取消了一个引用 +>>> sys.getrefcount("ab") + 3 # 结果在上次引用的基础上-1 + + +``` + +注意:在交互式解释器中`带空格`的对象引用次数永远为3,但是在脚本中回归正常,例如: + +```python +#!/usr/bin/env python +import sys +print sys.getrefcount("ab cd") +a="ab cd" +print sys.getrefcount("ab cd") +b="ab cd" +print sys.getrefcount("ab cd") +c=b +print sys.getrefcount("ab cd") +``` + +**垃圾收集** + 不再被使用的内存会被一种称为垃圾收集的机制释放。虽然解释器跟踪对象的引用计数,但是垃圾收集器负责释放内存。垃圾收集器是一块独立的代码,它用来寻找引用计数为0的对象,也负责检查那些虽然引用计数大于0但也该被销毁的对象。特定情形会导致循环引用。 + 一个循环引用发生在当你有至少两个对象互相引用时,也就是所说的引用都消失时,这些引用仍然存在,这说明只靠引用计数是不够的。Python的垃圾收集器实际上是**一个引用计数器和一个循环垃圾收集器**。当一个对象的引用计数变为0,解释器会暂停,释放掉这个对象和仅有这个对象可访问的其他对象,作为引用计数的补充,垃圾收集器也会留心被分配的总量很大(以及未通过引用计数销毁的那些) 的对象。在这种情况下,解释器会暂停下来,试图清理所有为引用的循环。 + +## 六、变量互传 + +Python和Shell变量互相传递的方法 + +shell==>python: + +```python +import os +var=os.popen('df -h').read( ) +print(var) + +执行结果: +[root@workstation day01]# /usr/bin/python3.8 "/root/Development/python_code/day01/hello.py" +Filesystem Size Used Avail Use% Mounted on +devtmpfs 3.9G 0 3.9G 0% /dev +tmpfs 3.9G 57M 3.9G 2% /dev/shm +tmpfs 3.9G 10M 3.9G 1% /run +tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup +/dev/mapper/cl-root 44G 7.4G 37G 17% / +/dev/nvme0n1p1 976M 234M 675M 26% /boot +tmpfs 795M 1.2M 794M 1% /run/user/42 +tmpfs 795M 6.9M 788M 1% /run/user/0 +/dev/sr0 7.7G 7.7G 0 100% /run/media/root/CentOS-8-2-2004-x86_64-dvd +``` + +python==>shell: + +```python +import os +var=123 +os.environ['var']=str(var) #environ的键值必须是字符串 + +os.system('echo $var') +``` + +```python +不用转变量的方式替代上面的写法 +In [9]: c="/tmp/hello" +In [10]: os.system("mkdir"+" "+c) +``` + + + +# **用shell编写自己的wc命令** + + + + + + + + + + + + + diff --git a/05-Python运算符与表达式.md b/05-Python运算符与表达式.md new file mode 100644 index 0000000..b88e4e4 --- /dev/null +++ b/05-Python运算符与表达式.md @@ -0,0 +1,327 @@ +# 05-Python运算符与表达式 + +[TOC] + +## 一、基本概念 + +**什么是运算符** + 运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算 + +​ 例如:2+3,其操作数是2和3,而运算符则是"+" + + + +**什么是表达式** + 表达式,是由数字、运算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。约束变量在表达式中已被指定数值,而自由变量则可以在表达式之外另行指定数值。 + +**Python运算符分类** + 算术运算符 + 关系运算符 + 赋值运算符 + 逻辑运算符 + 位运算符 + 成员运算符 + 身份运算符 + +## 二、算术运算符 + +以下假设变量a为10,变量b为20: + +| 运算符 | 描述 | 实例 | +| ------ | ----------------------------------------------- | -------------------------------------------------- | +| + | 加 - 两个对象相加 | a + b 输出结果 30 | +| - | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -10 | +| * | 乘 - 两个数相乘或是返回一个被重复若干次的字符串 | a * b 输出结果 200 | +| / | 除 - x除以y | b / a 输出结果 2 | +| % | 取模 - 返回除法的余数 | b % a 输出结果 0 | +| ** | 幂 - 返回x的y次幂 | a**b 为10的20次方, 输出结果 100000000000000000000 | +| // | 取整除 - 返回商的整数部分 | 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 | + +交互模式下,上次输出的表达式会赋给变量 `_`。把 Python 当作计算器时,用该变量实现下一步计算更简单,例如: + +```python +>>> tax = 12.5 / 100 +>>> price = 100.50 +>>> price * tax +12.5625 +>>> price + _ +113.0625 +>>> round(_, 2) +113.06 +``` + +最好把该变量当作只读类型。不要为它显式赋值,否则会创建一个同名独立局部变量,该变量会用它的魔法行为屏蔽内置变量。 + +## 三、关系运算符 + +也叫比较运算符 + +以下假设变量a为10,变量b为20: + +| 运算符 | 描述 | 实例 | +| ------ | ------------------------------------------------------------ | --------------------- | +| == | 等于 - 比较对象是否相等 | (a == b) 返回 False。 | +| != | 不等于 - 比较两个对象是否不相等 | (a != b) 返回 true. | +| > | 大于 - 返回x是否大于y | (a > b) 返回 False。 | +| < | 小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意,这些变量名的大写。 | (a < b) 返回 true。 | +| >= | 大于等于- 返回x是否大于等于y。 | (a >= b) 返回 False。 | +| <= | 小于等于 -返回x是否小于等于y。 | (a <= b) 返回 true。 | + + + +## 四、赋值运算符 + +以下假设变量a为10,变量b为20: + +| 运算符 | 描述 | 实例 | +| ------ | ---------------- | ------------------------------------- | +| = | 简单的赋值运算符 | c = a + b 将 a + b 的运算结果赋值为 c | +| += | 加法赋值运算符 | c += a 等效于 c = c + a | +| -= | 减法赋值运算符 | c -= a 等效于 c = c - a | +| *= | 乘法赋值运算符 | c *= a 等效于 c = c * a | +| /= | 除法赋值运算符 | c /= a 等效于 c = c / a | +| %= | 取模赋值运算符 | c %= a 等效于 c = c % a | +| **= | 幂赋值运算符 | c `**=` a 等效于 c = c `**`a | +| //= | 取整除赋值运算符 | c //= a 等效于 c = c // a | + +## 五、逻辑运算符 + +以下假设变量 a 为 10, b为 20: + +| 运算符 | 逻辑表达式 | 描述 | 实例 | +| ------ | ---------- | ------------------------------------------------------------ | ----------------------- | +| and | x and y | 布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 | (a and b) 返回 20。 | +| or | x or y | 布尔"或"- 如果 x 是非 0,它返回 x 的值,否则它返回 y 的计算值。 | (a or b) 返回 10。 | +| not | not x | 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 False | + +## 六、位运算符 + +按位运算符是把数字看作二进制来进行计算的。Python中的按位运算法则如下: +下表中变量 a 为 60,b 为 13 + +| 运算符 | 描述 | 实例 | +| ------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| & | 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 | +| \| | 按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。 | (a \| b) 输出结果 61 ,二进制解释: 0011 1101 | +| ^ | 按位异或运算符:当两对应的二进位相异时,结果为1 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 | +| ~ | 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 | +| << | 左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,低位补0。 | a << 2 输出结果 240 ,二进制解释: 1111 0000 | +| >> | 右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数,高位补0,低位舍弃 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 | + +注:上例中计算结果有问题,做好的结果没改,按实际结果来 + + + +## 七、成员运算符 + +除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。 + +| 运算符 | 描述 | 实例 | +| ------ | ------------------------------------------------------- | ------------------------------------------------- | +| in | 如果在指定的序列中找到值返回 True,否则返回 False。 | x 在 y 序列中 , 如果 x 在 y 序列中返回 True。 | +| not in | 如果在指定的序列中没有找到值返回 True,否则返回 False。 | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。 | + +## 八、身份运算符 + +身份运算符用于比较两个对象的存储单元(python3推荐用==) + +| 运算符 | 描述 | 实例 | +| ------ | ------------------------------------------ | ------------------------------------------------------ | +| is | is是判断两个标识符是不是引用自一个对象 | x is y, 如果 id(x) 等于 id(y) , is 返回结果 1 | +| is not | is not是判断两个标识符是不是引用自不同对象 | x is not y, 如果 id(x) 不等于 id(y). is not 返回结果 1 | + +## 九、三元运算符 + +变量名 = 表达式 if 判断条件 else 表达式 + +当 if 后边的 判断条件成立, 变量名的值就是 紧跟在等号后面的值,否则,变量名的值将会是 else 后面的值。 + +```python +x = 11 +n = x -1 if x >10 else x +1 +print(n) + + +x = 11 +if x > 10: + n = x-1 +else: + n = x+1 +print(n) +``` + +## 十、运算符优先级 + +以下表格列出了从最高到最低优先级的所有运算符: + +| 运算符 | 描述 | +| ------------------------ | ------------------------------------------------------ | +| ** | 指数 (最高优先级) | +| ~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) | +| * / % // | 乘,除,取模和取整除 | +| + - | 加法减法 | +| >> << | 右移,左移运算符 | +| & | 位 'AND' | +| ^ \| | 位运算符 | +| <= < > >= | 比较运算符 | +| <> == != | 等于运算符 | +| = %= /= //= -= += *= **= | 赋值运算符 | +| is is not | 身份运算符 | +| in not in | 成员运算符 | +| not or and | 逻辑运算符 | +| lambada | 一种灵活,便捷的且具有函数功能的表达式,又称匿名函数 | + +算术运算符 > 比较>逻辑 + + + +## 十一、进制转换 + +进制转换是人们利用符号来计数的方法。 + +由一组数码符号和两个基本因素"基数"与"位权"构成。 + +基数是指,进位计数制中所采用的数码(数制中用来表示"量"的符号)的个数。 + +位权是指,进位制中每一固定位置对应的单位值。 + + + +**简单转换理念** + 把二进制三位一组分开就是八进制, 四位一组就是十六进制 + +**二进制与十进制** +(1)二进制转十进制:"按权展开求和" +(1011)2=1x2**3 + 0x2**2 + 1x2**1 + 1x2**0=(11)10 + + 规律:个位上的数字的次数是0,十位上的数字的次数是1,......,依次递增,而十分位的数字的次数是-1,百分位上数字的次数是-2,......,依次递减。 + 注意:不是任何一个十进制小数都能转换成有限位的二进制数。 + + (2)十进制转二进制:"除以2取余,逆序排列"(除二取余法) + 【例】:(89)10=(1011001)2 + 89÷2 ……1 + 44÷2 ……0 + 22÷2 ……0 + 11÷2 ……1 + 5÷2 ……1 + 2÷2 ……0 + 1 + 十进制小数转二进制数:"乘以2取整,顺序排列"(乘2取整法) + 【例】:(0.625)10= (0.101)2 + 0.625X2=1.25 ……1 + 0.25X2=0.50 ……0 + 0.50 X2=1.00 ……1 + +二进制与八进制: + 二进制数转换成八进制数:从小数点开始,整数部分向左、小数部分向右,每3位为一组用一位八进制数的数字表示,不足3位的要用"0"补足3位,就得到一个八进制数。 + 八进制数转换成二进制数:把每一个八进制数转换成3位的二进制数,就得到一个二进制数。 + + + 八进制数字与十进制数字对应关系如下: + 000 -> 0 | 004-> 4 | 010=8 + 001 -> 1 |005 -> 5 | 011=9 + 002 -> 2 |006 -> 6 | 012=10 + 003 -> 3 |007 -> 7 | 013=11 + 【例】:将八进制的37.416转换成二进制数: + 3 7 . 4 1 6 + 011 111 .100 001 110 + 即:(37.416)8 =(11111.10000111)2 + 【例】:将二进制的10110.0011 转换成八进制: + 0 1 0 1 1 0 . 0 0 1 1 0 0 + 2 6 . 1 4 + 即:(10110.0011)2 = (26.14)8 + +二进制与十六进制 + 二进制数转换成十六进制数:二进制数转换成十六进制数时,只要从小数点位置开始,向左或向右每四位二进制划分一组(不足四位数可补0),然后写出每一组二进制数所对应的十六进制数码即可。 + 十六进制数转换成二进制数:把每一个十六进制数转换成4位的二进制数,就得到一个二进制数。 + 十六进制数字与二进制数字的对应关系如下: + 0000 -> 0 | 0100 -> 4 | 1000 -> 8 | 1100 -> C + 0001 -> 1 | 0101 -> 5 | 1001 -> 9 | 1101 -> D + 0010 -> 2 | 0110 -> 6 | 1010 -> A | 1110 -> E + 0011 -> 3 | 0111 -> 7 | 1011 -> B | 1111 -> F + 【例】:将十六进制数5DF.9 转换成二进制: + 5 D F . 9 + 0101 1101 1111 .1001 + 即:(5DF.9)16 =(10111011111.1001)2{十六进制怎么会有小数点} + 【例】:将二进制数1100001.111 转换成十六进制: + 0110 0001 . 1110 + 6 1 . E + +​ 即:(1100001.111)2 =(61.E)16 + +**Python中进制转换** +2进制以0b开头: + +​ 如: 0b11 则表示十进制的3 +​ + +8进制以0或者0o开头: + +​ 如: 011则表示十进制的9 +​ + +16进制以0x开头: + +​ 如: 0x11则表示十进制的17 + +```python +# 10进制转为2进制 +>>> bin(10) +'0b1010' + +# 2进制转为10进制 +>>> int("1001",2) +9 + +# 10进制转为16进制 +>>> hex(10) +'0xa' + +# 16进制到10进制 +>>> int("ff", 16) +255 +>>> int('0xab', 16) +171 + +# 10进制转为8进制 两种方式 +>>> print ("%o" % 10) +12 +>>> oct(8) +'010' + +# 16进制到2进制 +>>> bin(0xa) +'0b1010' + +# 2进制到16进制 +>>> hex(0b1001) +'0x9' + +8进制转10进制 +print(0o10) +int('010',8) +int('0o10',8) +``` + +# 尝试用Python写自己的grep + +shell编写grep同等功能的命令 + + + + + + + + + + + + + + + + + + +