Python 编程快速上手
2012 下半年, 想学一种新的编程语言吗? 选择 Python 吧!
学习一门新语言, 有两种方式: 1. 怀空杯心态, 尽量使用该语言的地道表达方式, 避免受原有语言思路的影响; 2. 将新语言与原有语言关联对比, 从而在最快时间内能够掌握基础知识,编写出有用的程序。一般这种情况下,是项目需求所致。
学习Python 有如下理由: 1. 表达能力强大, 不逊于C,C++,JAVA这些主编程语言 这是必要条件; 2. 它是类脚本语言, 这意味着简化了程序的编写, 用更少的代码完成用主编程语言可能语法繁琐的各种任务; 3. 格式严谨, 有利于代码风格的训练和软件代码的可读性,项目代码的管理; 4. 库、框架多,可以快速建立应用。 有此四条足矣,赶紧上路吧,别比来比去了!
我采用的思路是将 Python 与 Java 关联起来, 学习 Python 基础. 所以,本文不打算细述 Python 的语法, 而是通过对比差别来增强对Python 的认识, 当然, 大量的编程练习是必要的,最好能够结合一个小项目,并通过不断试错。 我是通过公司的一个实际项目边学边用而学习使用 Python 的。
1. Python 的代码缩进: 这是首先要提到的。 用括号括起来的代码块, 将通过 冒号加 正确缩进(同一层次的代码块必须使用完全相同的缩进) 来表达 , 条件语句中的括号通常可省略。 语句末的分号可有可无。写python 代码块时一定要注意加上冒号和正确的缩进, 这是经常容易犯的错误。例如:
while ( i < 100) { i += 2 printf("%d",x) }
用 python 写是这样:
while i < 100 : i += 2 // 这里正确的缩进是必要的,否则报语法错误。 # print x ## Error: unexpected indent , 同一层次的代码必须采用完全相同的缩进, 多一个或少一个空格都不行。
2. 变量在使用前一定要进行初始化和赋值,否则解释器无法识别该变量。一个变量均可以存储多种类型的值,不强调类型。 函数定义时不强调类型。 这是脚本语言的特点, 方便程式的编写。 比如
def func(x) : return x*2 x = 2 y = func(x) print x , " ", y x = ' now changed to an string ' print x, " " , y , ' OMG' # 松散的打印格式 , 双引号和单引号均可表示字符串 # print zzz 会报错: NameError : name 'zzz' is not defined.
3. 控制流 : if , if-elif-...-else , for ... in ... , while , continue, break ; 还有一个 pass 语句表示空执行, 即相当于空块,或者 NOP
4. 单行注释用 # 号, 多行注释用三个单引号
''' these are more lines. '''
5. 强大的内置动态数据结构: list , set, tuple, dictionary . list 主要方法有: append(x) , extend(List), insert(x), sort(), reversed(), pop([i]), insert(i, x), 等。 这些动态的数据结构很容易组合成更强大的数据结构工具。 关于这些结构的使用,网上有很多文章,这里就不细述了。
mylist = [ ] # 建立空列表 mylist = [1 , 3 , 'good'] print mylist mylist[1] = [('this is a tuple'), ['nested list']] print mylist
set 有成员检测功能:
myset = [1 , 2 ,1 ,1 , 2] # 建立集合 ===> myset = [1 ,2] x = 1 if x in myset : print myset, " has member : ", x else: print x , " is not found in ", myset mydict = {1 : ('zs', 'good', 25) , 2 : ('ww', 'right', 30) } print mydict mydict['city'] = 'hangzhou' for k, v in mydict.iteritems() : print k, v print mydict.keys()
元组 tuple 与列表类似, 但元组是不可变的, 这意味着无法修改元组的值。 引用元组的值采用下标方式
mytuple = (1, 2, 3, 4) print mytuple[2] # Error : mytuple[0] = 0
6. 模块。 一个 python 文件就是一个模块, 以 .py 为后缀。 当你在 func.py 中编写了函数 sign(x) 后, 要在其他文件中引用,则采用如下方式:
[1] import func
func.sign(x) # 模块名.函数名
[2] from func import sign(x)
sign(x) # 直接引用
7. 作用域。 这里主要给出一个基本的理解。 如上所述,
a. 一个 Python 文件就是一个模块,该模块的变量的作用域主要可分为全局作用域,本地作用域以及内置作用域。
b. 代码块(例如, try块,if-else, for , while 等),函数中定义的变量,方法,类等属于本地作用域, 可以通过 locals() 查询,作用范围在创建时到代码块或函数退出为止; 函数之外的变量,方法,类等属于全局作用域,作用范围从创建时到整个文件末尾为止,可以通过 globals() 查询。
c. 当全局作用域的变量与本地作用域的变量冲突时,会优先采用本地作用域中的变量,查找不到时再到全局作用域中查找。要使用全局作用域的变量,必须先声明 global var. 声明global var 之前不能出现同名变量 var. 请看:
x = 2
def fun1() :
x = 3
print "[1] x = " , x // 使用局部变量x 打印 [1] x = 3
print "init: x = " , x // 使用全局变量x 打印 init x = 2
fun1()
print "after [1] x = ", x // 不会改变全局变量x 打印 after [1] x = 2
def fun2() :
global x // 声明使用全局变量 x
x = 3
fun2()
print "after fun2 : x = ", x // 打印 after fun2: x = 3
def fun3() :
x = 0
#ERROR global x : 语法错误: x 不能既是全局变量又是局部变量。也就是说,
print "[3] x = ", x : 要使用全局变量,不可以出现在同名的局部变量之后。
fun3()
内置作用域是python 语言所定义的系统变量,方法,类等的作用域, 可以直接使用。 例如, type 函数可以打印对象的类型。
print type(x) // 打印 <type 'int'>
def type(x) :
print "my type(): "
return x*2
print type(x) // 打印 6
因此,可以得到又一条结论: 如果定义了与内置方法同名的方法, 会优先采用自定义的方法。 事实上, 作用域的优先级:
本地作用域 》 全局作用域 》 内置作用域
8. 异常机制。 try-except , try-except-else, try-finally, try-except-finally 四种。
9. if __name__ == '__main__' : do something ; __name__ 是python模块的内置属性。每个python模块都是一个.py文件,既可以从命令行运行,又可以导入其他模块。当从命令行运行时,__name__ == ‘__main__’ , do something 会执行; 当导入其他模块时, __name__ 的值为模块的名称, 不等于‘ __main__ ’, do something 不会执行。也就是说,该模块存在某些语句,当自身单独运行时,期望被执行,而作为支持模块导入其他模块时,却不希望执行。 因此, 这条语句通常可用于单独运行和测试该模块。
10. 下面的例子演示了Python 提供的一些基本语言特性: 缩进,内置数据结构, 控制流, 读写文件,重定向, 导入模块, 类定义, 异常机制,日志,正则表达式。代码本身没有什么创新之处,但整合到一起,可以演示Python 的大部分基本语言特性。
dupkeys.py
################################################################## # # validate if the input text file contains duplicated keys. # the input.txt should like below: # key1 value1 # key2 value2 # ... # # the result is stored into a hashtable: # {key: [count, [value1, value2,..,valueN]]} # ################################################################## import sys import re from thelog import initlog from exc import NotMatchedException patt = re.compile(r'^\s*(\w+)\s+(\w+)[\s\r\n]+$') total_items = 0 count = { } def proc(line) : matched = patt.match(line) try : if matched : global total_items total_items += 1 key = matched.group(1) value = matched.group(2) if key in count : valuelist = (count[key])[1] valuelist.append(value) count[key] = [(count[key])[0]+1, valuelist] else : count[key] = [1, [value]] else : raise NotMatchedException('The line Not matched: %s' % line) except (NotMatchedException, Exception), args: dupkeysLog.error(args) if len(sys.argv) != 2 : print "usage: python dupkeys.py filename.txt " sys.exit(1) logfile = 'dupkeys.log' dupkeysLog = initlog(logfile) resfile = open('result.txt', 'w') sysStdout = sys.stdout sys.stdout = resfile # redirect stdout into file result.txt filename = sys.argv[1] inputfile = open(filename) for line in inputfile : proc(line) print "total items in file %s : %d" % (filename, total_items) dupkeysLog.error("Keys duplicated: ") for k, v in count.iteritems() : print k, v if v[0] > 1 : dupkeysLog.error( ' %s %s ' % (k, v) ) if inputfile: inputfile.close() if resfile : resfile.close() sys.stdout = sysStdout
thelog.py
import logging LOG_LEVELS = { 'DEBUG': logging.DEBUG, 'INFO': logging.INFO, 'WARN': logging.WARNING, 'ERROR': logging.ERROR, 'CRITICAL': logging.CRITICAL } def initlog(filename) : logger = logging.getLogger() hdlr = logging.FileHandler(filename) formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s") hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(LOG_LEVELS['ERROR']) return logger if __name__ == '__main__' : errlog = initlog("errlog.log") errlog.info('this is an ordinary info') errlog.warn('this is a warning') errlog.error('this is an error that should be handled') errlog.critical('this is an severe error')
exc.py
class MyException(Exception) : pass class MsgException(MyException) : def __init__(self, msg) : self.msg = msg def __str__(self) : return repr(self.msg) class NotMatchedException(MsgException) : pass