python 基础 (二)
一. 常量
Python里还会用到常量,那么常量是什么呢?
“常量”在程序运行时,不会被修改的量。换言之,常量虽然是为了硬件、软件、编程语言服务,但是它并不是因为硬件、软件、编程语言而引入;
另一层含义指它们的编码方法是不变的,比如字符'A'无论在硬件、软件还是各种编程语言中,它的信息编码即为0x41,在除C/C++的一些高级程序语言中,常量可以被称作,在一个变化过程中,始终不变的量。它们可以是不随时间变化的某些量和信息,也可以是表示某一数值的字符或字符串,常被用来标识、测量和比较。
常量区分为不同的类型,如25、0、-8为整形常量,6.8、-7.89为实型常量,‘a’‘b’为字符常量。常量一般从其字面形式即可判断。这种常量称为字面常量或直接常量。
------ 以上内容来自百度百科。
Python里没有对常量的检查,也就是一个常量,也能被重新赋值、改变,so 我们为了区分,要有一个规范。常量的定义,常量名大写,只要看到全大写的变量名,可以清楚的判断这是不可改变的变量(常量);
二 . 模块
1)标准库之Sys模块使用详解
sys 模块提供了许多函数和变量来处理 Python 运行时环境的不同部分。模块的文件名必须以.py为扩展名。
用途:使用sys模块获得脚本的参数、处理模块、使用sys模块操作模块搜索路径、使用sys模块查找内建模块、使用sys模块查找已导入的模块等...
我们利用import语句导入sys模块。
1、使用sys模块获得脚本的参数
sys.argv变量是一个字符串的列表(列表会在后面的章节详细解释)。特别地,sys.argv包含了命令行参数的列表,即使用命令行传递给你的程序的参数。
import sys
print ("script name is", sys.argv[0]) # 使用sys.argv[0]采集脚本名称 if len(sys.argv) > 1: print ("there are", len(sys.argv)-1, "arguments:") # 使用len(sys.argv)-1采集参数个数-1为减去[0]脚本名称 for arg in sys.argv[1:]: #输出除了[0]外所有参数 print (arg) else: print ("there are no arguments!")
2、处理模块
path 列表是一个由目录名构成的列表, Python 从中查找扩展模块( Python 源模块, 编译模块,或者二进制扩展).
启动 Python 时,这个列表从根据内建规则, PYTHONPATH 环境变量的内容, 以及注册表( Windows 系统)等进行初始化.
由于它只是一个普通的列表, 你可以在程序中对它进行操作。
- 使用sys模块操作模块搜索路径
import sys print ("path has", len(sys.path), "members") sys.path.insert(0, "samples") #将路径插入到path,[0]中 import sample sys.path = [] #删除path中所有路径 import random
3、使用sys模块查找内建模块
builtin_module_names 列表包含 Python 解释器中所有内建模块的名称
import sys
def dump(module): print (module, "=>",) if module in sys.builtin_module_names: #查找内建模块是否存在 print ("<BUILTIN>") else: module = _ _import_ _(module) #非内建模块输出模块路径 print (module._ _file_ _) dump("os") dump("sys") dump("string") dump("strop") dump("zlib") os => C:\python\lib\os.pyc sys => <BUILTIN> string => C:\python\lib\string.pyc strop => <BUILTIN> zlib => C:\python\zlib.pyd
4、使用sys模块查找已导入的模块
modules 字典包含所有加载的模块. import 语句在从磁盘导入内容之前会先检查这个字典.
Python 在处理你的脚本之前就已经导入了很多模块.
print (sys.modules.keys()) ['os.path', 'os', 'exceptions', '_ _main_ _', 'ntpath', 'strop', 'nt', 'sys', '_ _builtin_ _', 'site', 'signal', 'UserDict', 'string', 'stat']
5、使用sys模块获得当前平台
sys.platform 返回当前平台 出现如: "win32" "linux2" 等
6、处理标准输出/输入
标准输入和标准错误 (通常缩写为 stdout 和 stderr) 是内建在每一个 UNIX 系统中的管道。
当你 print 某些东西时,结果前往 stdout 管道;
当你的程序崩溃并打印出调试信息 (例如 Python 中的 traceback (错误跟踪)) 的时候,信息前往 stderr 管道
>>> for i in range(3): ... print('Dive in') Dive in Dive in Dive in >>> import sys >>> for i in range(3): ... sys.stdout.write('Dive in') Dive inDive inDive in >>> for i in range(3): ... sys.stderr.write('Dive in') Dive inDive inDive in
stdout 是一个类文件对象;调用它的 write 函数可以打印出你给定的任何字符串。
实际上,这就是 print 函数真正做的事情;它在你打印的字符串后面加上一个硬回车,然后调用 sys.stdout.write 函数。
在最简单的例子中,stdout 和 stderr 把它们的输出发送到相同的地方
和 stdout 一样,stderr 并不为你添加硬回车;如果需要,要自己加上。
stdout 和 stderr 都是类文件对象,但是它们都是只写的。
它们都没有 read 方法,只有 write 方法。然而,它们仍然是类文件对象,因此你可以将其它任何 (类) 文件对象赋值给它们来重定向其输出。
7、使用sys重定向输出
print ('Dive in') # 标准输出 saveout = sys.stdout # 终在重定向前保存stdout,这样的话之后你还可以将其设回正常 fsock = open('out.log', 'w') # 打开一个新文件用于写入。如果文件不存在,将会被创建。如果文件存在,将被覆盖。 sys.stdout = fsock # 所有后续的输出都会被重定向到刚才打开的新文件上。 print ('This message will be logged instead of displayed' ) # 这样只会将输出结果“打印”到日志文件中;屏幕上不会看到输出 sys.stdout = saveout # 在我们将 stdout 搞乱之前,让我们把它设回原来的方式。 fsock.close() # 关闭日志文件。
重定向错误信息
fsock = open('error.log', 'w') # 打开你要存储调试信息的日志文件。
sys.stderr = fsock # 将新打开的日志文件的文件对象赋值给stderr以重定向标准错误。
raise Exception, 'this error will be logged' # 引发一个异常,没有在屏幕上打印出任何东西,所有正常的跟踪信息已经写进error.log
还要注意你既没有显式关闭日志文件,也没有将 stderr 设回最初的值。
这样挺好,因为一旦程序崩溃 (由于引发的异常),Python 将替我们清理并关闭文件
打印到 stderr
向标准错误写入错误信息是很常见的,所以有一种较快的语法可以立刻导出信息
>>> print ('entering function') entering function >>> import sys >>> print >> sys.stderr, 'entering function' entering function
print 语句的快捷语法可以用于写入任何打开的文件 (或者是类文件对象)。
在这里,你可以将单个print语句重定向到stderr而且不用影响后面的print语句。
8、使用sys模块退出程序
import sys sys.exit(1)
注意 sys.exit 并不是立即退出. 而是引发一个 SystemExit 异常. 这意味着你可以在主程序中捕获对 sys.exit 的调用.
捕获sys.exit调用
import sys print ("hello") try: sys.exit(1) except SystemExit: # 捕获退出的异常 pass # 捕获后不做任何操作 print ("there")
hello there
如果准备在退出前自己清理一些东西(比如删除临时文件), 你可以配置一个 "退出处理函数"(exit handler), 它将在程序退出的时候自动被调用
另一种捕获sys.exit调用的方法
def exitfunc(): print ("world") sys.exitfunc = exitfunc # 设置捕获时调用的函数 print ("hello") sys.exit(1) # 退出自动调用exitfunc()后,程序依然退出了 print ("there") # 不会被 print hello world
2)系统库os模块功能
常用方法:
1、os.name
输出字符串指示正在使用的平台。如果是window 则用'nt'表示,对于Linux/Unix用户,它是'posix'。
2、os.getcwd()
函数得到当前工作目录,即当前Python脚本工作的目录路径。
3、os.listdir()
返回指定目录下的所有文件和目录名。
>>> os.listdir(os.getcwd()) ['Django', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'MySQL-python-wininst.log', 'NEWS.txt', 'PIL-wininst.log', 'python.exe', 'pythonw.exe', 'README.txt', 'RemoveMySQL-python.exe', 'RemovePIL.exe', 'Removesetuptools.exe', 'Scripts', 'setuptools-wininst.log', 'tcl', 'Tools', 'w9xpopen.exe'] >>>
4、os.remove()
删除一个文件。
5、os.system()
运行shell命令。
>>> os.system('dir') 0 >>> os.system('cmd') #启动dos
6、os.sep 可以取代操作系统特定的路径分割符。
7、os.linesep字符串给出当前平台使用的行终止符
>>> os.linesep '\r\n' #Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'。 >>> os.sep '\\' #Windows >>>
8、os.path.split()
函数返回一个路径的目录名和文件名
>>> os.path.split('C:\\Python25\\abc.txt') ('C:\\Python25', 'abc.txt')
9、os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。
>>> os.path.isdir(os.getcwd()) True >>> os.path.isfile('a.txt') False
10、os.path.exists()函数用来检验给出的路径是否真地存在
>>> os.path.exists('C:\\Python25\\abc.txt') False >>> os.path.exists('C:\\Python25') True >>>
11、os.path.abspath(name):获得绝对路径
12、os.path.normpath(path):规范path字符串形式
13、os.path.getsize(name):获得文件大小,如果name是目录返回0L
14、os.path.splitext():分离文件名与扩展名
>>> os.path.splitext('a.txt') ('a', '.txt')
15、os.path.join(path,name):连接目录与文件名或目录
>>> os.path.join('c:\\Python','a.txt') 'c:\\Python\\a.txt' >>> os.path.join('c:\\Python','f1') 'c:\\Python\\f1' >>>
16、os.path.basename(path):返回文件名
>>> os.path.basename('a.txt') 'a.txt' >>> os.path.basename('c:\\Python\\a.txt') 'a.txt' >>>
17、os.path.dirname(path):返回文件路径
>>> os.path.dirname('c:\\Python\\a.txt') 'c:\\Python'
三. python 生成的.pyc 是什么?
这是用一个过程,,哈哈!!
当执行的程序,存在导入的模块时才会生产.pyc,手动执行不会生成.pyc文件;
不要急,,我们先说下python的运行过程,自然就明白了。
四. python 的运行过程
1. Python是一门解释型语言?
初学Python,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下去,直到发现了*.pyc文件的存在。如果是解释型语言,那么生成的*.pyc文件是什么呢?c应该是compiled的缩写才对啊! 为了防止其他学习Python的人也被这句话误解,那么我们就在文中来澄清下这个问题,并且把一些基础概念给理清。
2. 解释型语言和编译型语言
计算机是不能够识别高级语言的,所以当我们运行一个高级语言程序的时候,就需要一个“翻译机”来从事把高级语言转变成计算机能读懂的机器语言的过程。这个过程分成两类,第一种是编译,第二种是解释。 编译型语言在程序执行之前,先会通过编译器对程序执行一个编译的过程,把程序转变成机器语言。运行时就不需要翻译,而直接执行就可以了。最典型的例子就是C语言。 解释型语言就没有这个编译的过程,而是在程序运行的时候,通过解释器对程序逐行作出解释,然后直接运行,最典型的例子是Ruby。 通过以上的例子,我们可以来总结一下解释型语言和编译型语言的优缺点,因为编译型语言在程序运行之前就已经对程序做出了“翻译”,所以在运行时就少掉了“翻译”的过程,所以效率比较高。但是我们也不能一概而论,一些解释型语言也可以通过解释器的优化来在对程序做出翻译时对整个程序做出优化,从而在效率上超过编译型语言。 此外,随着Java等基于虚拟机的语言的兴起,我们又不能把语言纯粹地分成解释型和编译型这两种。 用Java来举例,Java首先是通过编译器编译成字节码文件,然后在运行时通过解释器给解释成机器文件。所以我们说Java是一种先编译后解释的语言。 再换成C#,C#首先是通过编译器将C#文件编译成IL文件,然后在通过CLR将IL文件编译成机器文件。所以我们说C#是一门纯编译语言,但是C#是一门需要二次编译的语言。同理也可等效运用到基于.NET平台上的其他语言。
3. Python到底是什么?
其实Python和Java/C#一样,也是一门基于虚拟机的语言,我们先来从表面上简单地了解一下Python程序的运行过程吧。 当我们在命令行中输入python hello.py时,其实是激活了Python的“解释器”,告诉“解释器”:你要开始工作了。可是在“解释”之前,其实执行的第一项工作和Java一样,是编译。 熟悉Java的同学可以想一下我们在命令行中如何执行一个Java的程序: javac hello.java java hello 只是我们在用Eclipse之类的IDE时,将这两部给融合成了一部而已。其实Python也一样,当我们执行python hello.py时,他也一样执行了这么一个过程,所以我们应该这样来描述Python,Python是一门先编译后解释的语言。
4. 简述Python的运行过程
在说这个问题之前,我们先来说两个概念,PyCodeObject和pyc文件。 我们在硬盘上看到的pyc自然不必多说,而其实PyCodeObject则是Python编译器真正编译成的结果。我们先简单知道就可以了,继续向下看。 当python程序运行时,编译的结果则是保存在位于内存中的PyCodeObject中,当Python程序运行结束时,Python解释器则将PyCodeObject写回到pyc文件中。 当python程序第二次运行时,首先程序会在硬盘中寻找pyc文件,如果找到,则直接载入,否则就重复上面的过程。 所以我们应该这样来定位PyCodeObject和pyc文件,我们说pyc文件其实是PyCodeObject的一种持久化保存方式。
6. pyc的目的是重用
编译型语言的优点在于,我们可以在程序运行时不用解释,而直接利用已经“翻译”过的文件。也就是说,我们之所以要把py文件编译成pyc文件,最大的优点在于我们在运行程序时,不需要重新对该模块进行重新的解释。 所以,我们需要编译成pyc文件的应该是那些可以重用的模块,这于我们在设计软件类时是一样的目的。所以Python的解释器认为:只有import进来的模块,才是需要被重用的模块。
7. pyc的过期时间
说完了pyc文件,可能有人会想到,每次Python的解释器都把模块给持久化成了pyc文件,那么当我的模块发生了改变的时候,是不是都要手动地把以前的pyc文件remove掉呢? 当然Python的设计者是不会犯这么白痴的错误的。而这个过程其实就取决于PyCodeObject是如何写入pyc文件中的。 写入pyc文件的时候,写了一个Long型变量,变量的内容则是文件的最近修改日期,其实每次在载入之前都会先检查一下py文件和pyc文件保存的最后修改日期,如果不一致则重新生成一份pyc文件。
8. 最后写点想法
其实了解Python程序的执行过程对于大部分程序员,包括Python程序员来说意义都是不大的,那么真正有意义的是,我们可以从Python的解释器的做法上学到什么,我认为有这样的几点:
A. 其实Python是否保存成pyc文件和我们在设计缓存系统时是一样的,我们可以仔细想想,到底什么是值得扔在缓存里的,什么是不值得扔在缓存里的。
B. 在跑一个耗时的Python脚本时,我们如何能够稍微压榨一些程序的运行时间,就是将模块从主模块分开。(虽然往往这都不是瓶颈)
C. 在设计一个软件系统时,重用和非重用的东西是不是也应该分开来对待,这是软件设计原则的重要部分。
D. 在设计缓存系统(或者其他系统)时,我们如何来避免程序的过期,其实Python的解释器也为我们提供了一个特别常见而且有效的解决方案。
五. Python运算符使用
5.1)Python语言支持有以下几种类型:
-
算术运算符
-
比较(即关系)运算符
-
赋值运算符
-
逻辑运算符
-
位运算符
-
会员操作符
-
标识操作符
5.2)Python算术运算符:
假设变量a持有10和变量b持有20,则:
操作符 描述符 例子 + 加法 - 对操作符的两侧增加值 a + b = 30 - 减法 - 减去从左侧操作数右侧操作数 a - b = -10 * 乘法 - 相乘的运算符两侧的值 a * b = 200 / 除 - 由右侧操作数除以左侧操作数 b / a = 2 % 模 - 由右侧操作数和余返回除以左侧操作数 b % a = 0 ** 指数 - 执行对操作指数(幂)的计算 a**b = 10 的幂 20 // 地板除 - 操作数的除法,其中结果是将小数点后的位数被除去的商。 9//2 = 4 而 9.0//2.0 = 4.0
5.3)Python的比较操作符:
假设变量a持有10和变量b持有20,则:
运算符 描述 示例 == 检查,两个操作数的值是否相等,如果是则条件变为真。 (a == b) 不为 true. != 检查两个操作数的值是否相等,如果值不相等,则条件变为真。 (a != b) 为 true. <> 检查两个操作数的值是否相等,如果值不相等,则条件变为真。 (a <> b) 为 true。这个类似于 != 运算符 > 检查左操作数的值是否大于右操作数的值,如果是,则条件成立。 (a > b) 不为 true. < 检查左操作数的值是否小于右操作数的值,如果是,则条件成立。 (a < b) 为 true. >= 检查左操作数的值是否大于或等于右操作数的值,如果是,则条件成立。 (a >= b) 不为 true. <= 检查左操作数的值是否小于或等于右操作数的值,如果是,则条件成立。 (a <= b) 为 true.
5.4)Python赋值运算符:
假设变量持有10和变量b持有20,则:
运算符 描述 示例 = 简单的赋值运算符,赋值从右侧操作数左侧操作数 c = a + b将指定的值 a + b 到 c += 加法AND赋值操作符,它增加了右操作数左操作数和结果赋给左操作数 c += a 相当于 c = c + a -= 减AND赋值操作符,它减去右边的操作数从左边操作数,并将结果赋给左操作数 c -= a 相当于 c = c - a *= 乘法AND赋值操作符,它乘以右边的操作数与左操作数,并将结果赋给左操作数 c *= a 相当于 c = c * a /= 除法AND赋值操作符,它把左操作数与正确的操作数,并将结果赋给左操作数 c /= a 相当于= c / a %= 模量AND赋值操作符,它需要使用两个操作数的模量和分配结果左操作数 c %= a is equivalent to c = c % a **= 指数AND赋值运算符,执行指数(功率)计算操作符和赋值给左操作数 c **= a 相当于 c = c ** a //= 地板除,并分配一个值,执行地板除对操作和赋值给左操作数 c //= a 相当于 c = c // a
5.5)Python位运算符:
位运算符作用于位和位操作执行位。假设,如果a =60;且b =13;现在以二进制格式它们将如下:
a = 0011 1100
b = 0000 1101
-----------------
a&b = 0000 1100
a|b = 0011 1101
a^b = 0011 0001
~a = 1100 0011
Python语言支持下位运算符
操作符 描述 示例 & 二进制和复制操作了一下,结果,如果它存在于两个操作数。 (a & b) = 12 即 0000 1100 | 二进制或复制操作了一个比特,如果它存在一个操作数中。 (a | b) = 61 即 0011 1101 ^ 二进制异或运算符的副本,如果它被设置在一个操作数而不是两个比特。 (a ^ b) = 49 即 0011 0001 ~ 二进制的补运算符是一元的,并有“翻转”位的效果。 (~a ) = -61 即 1100 0011 以2的补码形式由于带符号二进制数。 << 二进位向左移位运算符。左操作数的值左移由右操作数指定的位数。 a << 2 = 240 即 1111 0000 >> 二进位向右移位运算符。左操作数的值是由右操作数指定的位数向右移动。 a >> 2 = 15 即 0000 1111
5.6)Python逻辑运算符:
Python语言支持以下逻辑运算符。假设变量a持有10和变量b持有20则:
运算符 描述 示例 and 所谓逻辑与运算符。如果两个操作数都是真的,那么则条件成立。 (a and b) 为 true. or 所谓逻辑OR运算符。如果有两个操作数都是非零然后再条件变为真。 (a or b) 为 true. not 所谓逻辑非运算符。用于反转操作数的逻辑状态。如果一个条件为真,则逻辑非运算符将返回false。 not(a and b) 为 false.
5.7)Python成员运算符:
除了前面讨论的运算符,Python成员运算符,在一个序列中成员资格的测试,如字符串,列表或元组。有两个成员运算符解释如下:
操作符 描述 示例 in 计算结果为true,如果它在指定找到变量的顺序,否则false。 x在y中,在这里产生一个1,如果x是序列y的成员。 not in 计算结果为true,如果它不找到在指定的变量顺序,否则为false。 x不在y中,这里产生结果不为1,如果x不是序列y的成员。
5.8)Python标识运算符:
标识符比较两个对象的内存位置。两个运算符标识解释如下:
运算符 描述 例子 is 计算结果为true,如果操作符两侧的变量指向相同的对象,否则为false。 x是y,这里结果是1,如果id(x)的值为id(y)。 is not 计算结果为false,如果两侧的变量操作符指向相同的对象,否则为true。 x不为y,这里结果不是1,当id(x)不等于id(y)。
5.9)Python运算符优先级:
下表列出了所有运算符从最高优先级到最低。
运算符 描述 ** 幂(提高到指数) ~ + - 补码,一元加号和减号(方法名的最后两个+@和 - @) * / % // 乘,除,取模和地板除 + - 加法和减法 >> << 左,右按位转移 & 位'AND' ^ | 按位异'或`'和定期`或' <= < > >= 比较运算符 <> == != 等式运算符 = %= /= //= -= += *= **= 赋值运算符 is is not 标识运算符 in not in 成员运算符 not or and 逻辑运算符