Python基础

Python官方给出的5个资料点:

使用python -c command [arg]...来仅执行command命令,然后退出。Python可以在同一行中用分号分割多个语句,但不是推荐的做法。如下代码所示:

1
python -c 'print "xyz"; import sys; print sys.argv' 1 2 3

传递给Python的参数被放在sys.agrv中,sys.agrv[0]总是脚本文件的名字,其它参数从索引1开始,用len(sys.argv)获取参数的数目。下划线(_)在解释器中有特别的含义,表示最后一个表达式的值。可以使用字符串格式操作符(%)来实现字符串替换功能,这个功能称为字符串插入(string interpolation)。如:

1
print "%s is number %d!" % ("Python", 1)

Python用%d替换整数,%f替换浮点数,%s替换字符串,不过也可以不严格的使用%s来替换整数或浮点数。除此之外还有 format 函数,以及在 Python 3.x 中的 f 字符串都可以执行字符串插入。

在Python交互解释器(interactive interpreter)中有两种方式来输出对象,print和直接输入变量名,print将调用str()方法来显示,而直接输入变量名将调用repr()来显示。其实,Python在str(x)方法的背后会调用对象的x.__str__()魔法方法,而repr(x)的背后调用x.__repr__方法。对于字符串来说,print将不输出包围的引号,而直接输入变量名会输出引号。

在Python中,print是一个表达式而不是函数,调用print时不需要用括号,可以同时输出多个参数,用逗号隔开就行。print尾部加入逗号,可以抑制自动添加的换行符。

1
2
3
4
print 'I like to use the Internet for:'
for item in ['e-mail', 'net-surfing', 'homework', 'chat']:
     print item,
print

在Python 3.x 中,print被改为了一个函数,而不再是表达式,这是为了语言的统一。从Python2.0开始可以用符号>>将print重定向到文件对象中,如:

1
2
3
4
5
6
import sys
print >> sys.stderr, 'Fatal error: invalid input!'

logfile = open('./mylog.txt', 'a')
print >> logfile, 'Fatal error: invalid input!'
logfile.close()

可以用raw_input(promote_string)来函数获取用户的命令行输入,并返回一个字符串。如果想将字符串转为整数就使用int()内建函数。

1
2
num = raw_input('Now enter a number: ')
print 'Doubling your number: %d' % (int(num) * 2)

对函数不熟悉的时候可以在交互解释器中调用help(func_name)获得函数的帮助信息,如help(raw_input)。推荐的写程序的方式是不在函数中处理输入输出,将函数作为纯净的处理数据的地方,而将与用户的交互放在外部去做。这将最大化函数的可移植性。

Python源码的默认编码是UTF-8,可以通过#-*- coding: encoding -*-来指定文件的编码,参考PEP 263 源文件编码。Python中只能用#做单行的注释,Python有一种特殊的注释叫文档字符串,你可以在模块、类、函数的开始添加一个字符串,起到在线文档的功能,它们可以在运行时被访问。

1
2
3
def foo():
    "This is a doc string"
    return True

Python支持乘方运算(**),具有最高的优先级。Python在执行from __future__ import division之后,除法(/)将执行真正的除法,不管除数和被除数是否为整数都将除尽,跟Lua中的除法一样。而没有import将执行传统除法,整数舍去小数部分。地板除法(//)则不管是否为整数都执行舍去小数部分。Python中没有C风格的||&&!的逻辑操作符,相反提供andornot,and和or执行这样的运算,如果前面的值为True,and返回后面的值,or返回True;如果前面的值为False,and返回False,or返回后面的值。

这里需要重点说明一下复合赋值(augmented assignment)操作符+= *= -= /= %= **= <<=,我们知道在Python中一切都是对象,复合赋值对于可变对象是直接改变此对象,对于不可变对象将生成一个新对象来替换原对象因而A+=BA=A+B是一样的。但从外部看起来其实是一样的。

1
2
aList = [123, 'xyz']
aList += [45.6e7]

Python支持多元赋值,但与Lua中有所不同。Python并不真正支持多元赋值,这里的多元赋值的两边其实是元组(tuple),如下代码所示:

1
2
x, y, z = 1, 2, 'a string'
(x, y, z) = (1, 2, 'a string')

推荐的做法是总是加上圆括号来明确表示是元组。在Python中支持如下写法来交换变量引用:

1
x, y = y, x

在Python中所有变量在使用前都必须定义,否则将会抛出NameError,Python是动态类型语言,因而不需要预先声明变量的类型,变量的类型和值在赋值那一刻被初始化。在Python中赋值是语句不是表达式,意味着赋值语句本身没有返回值,代码y = (x = x + 1)是非法的,但链式赋值是允许的,即y = x = x + 1。Python不支持C风格的自增、自减操作符。

Python支持长整型和复数。Python的长整型类可以支持无限长度,从Python2.3开始,不会报整数溢出的错误,结果会自动转为长整型,这是为统一int和long类型。布尔值是特殊的整型,如果将布尔值放到一个数值上下文环境中,True会被当做整型值1,而False会被当做0。Python2.4之后支持在导入decimal模块的情况下支持完全精度的十进制小数(decimal),加入的缘由在于float无法精确表示常用的浮点数。

Python支持使用成对的单引号或双引号的字符串,三引号(三个连续的单引号或双引号)可以用来包含换行符。Python没有字符类型。加号(+)用于字符串连接运算,星号(*)则用于字符串重复。字符串是不可变类型,任何对字符串的操作都是返回新的字符串。字符串支持索引([])和切片([:])操作,负数索引表示从尾部回溯,其中-1表示尾部元素。切片操作符的第二个索引是结尾不包含索引。

1
2
3
4
5
6
7
pystr = 'Python'
iscool = 'is cool!'
print pystr[0]
print pystr[2:5]
print iscool[:2]
print iscool[3:]
print iscool[-1]

列表元素用中括号([])包裹,元素的个数及元素的值可以改变,元组元素用小括号(())包裹,不可以改变,元组可以看成是只读的列表。列表和元组都可以包含不同类型的值。

1
2
3
4
5
6
7
8
9
aList = [1, 2, 3, 4]
print aList[0]
print aList[2:]
print aList[:3]
aList[1] = 5

aTuple = ('robots', 77, 93, 'try')
print aTuple[:3]
print aTuple[-2:-1]

字典是Python中映射数据类型。由键-值(key-value)对构成,几乎所有类型的Python对象都可以用作键,不过一般以数字或字符串最为常见。

1
2
3
4
5
6
7
aDict = {'host':'earth'}
aDict['port'] = 80
print aDict
print aDict.keys()
print aDict['host']
for key in aDict:
    print key, aDict[key]

Python语句一般是一行一个语句,一行语句过长可以使用反斜杠(\)分解成几行。只有在使用闭合操作符时(小括号、中括号、花括号)才能不使用反斜线跨行。

1
2
3
4
5
6
7
8
9
weather_is_hot = 1
shark_warnings = 0
if (weather_is_hot == 1) and \
    (shark_warnings == 0):
    print "go here"

if ((weather_is_hot == 1) and
    (shark_warnings == 0)):
    print "go here"

Python跟别的语言的最大的区别就在于Python使用缩进来代表代码块的,缩进相同的一组语句构成一个代码块。像if、while、def和class这样的复合语句,首行以关键字开始,以冒号(:)结束,该行之后的一行或多行构成代码组。Python语言不支持switch/case语句,跟Lua一样。if、while的判断表达式是不需要括号的。

if语句:

1
2
3
4
5
6
if expression1:
    if_suite
elif expression2:
    elif_suite
else:
    else_suite

while语句:

1
2
while expression:
    while_suite

Python的for循环与传统for循环不一样,不能用数字进行循环,而是接受一个可迭代对象作为其参数,每次迭代其中一个元素。for循环可以迭代字符串,每次遍历一个元素,用enumerate()函数可以得到列表的List的元素和索引。

1
2
3
4
5
foo = 'abc'
for c in foo:
    print c
for i, ch in enumerate(foo):
    print ch, '(%d)' % i

Python支持列表解析(List Comprehensions)来很方便的得到列表。如:

1
2
squared = [x ** 2 for x in range(4)]
sqdEvens = [x ** 2 for x in range(8) if not x % 2]

Python支持对文件对象进行迭代,如下代码所示:

1
2
3
4
5
filename = raw_input('Enter file name: ')
fobj = open(filename, 'r')
for eachLine in fobj:
    print eachLine
fobj.close()

Python提供了类似open()的file()工厂方法来得到一个file对象。

Python支持异常处理,语法格式如下:

1
2
3
4
5
try:
    filename = "not_exist_file"
    fobj = open(filename, 'r')
except IOError, e:
    print 'file open error:', e

Python的函数在调用前必须被定义,函数不需要声明返回值类型,如果return关键字后没有值,默认返回None类型值(类似于其它语言中的NULL值)。Python的函数支持默认参数,但不支持函数重载。Python函数语法格式:

1
2
3
def function_name([arguments]):
    """optinal documentation string"""
    function_suite

Python支持面向对象编程,其中特殊方法__init__是对象创建后执行的第一个方法。创建一个类的实例就像调用一个函数一样用foo1 = FooClass()。Python的重要特性就是不一定需要用面向对象编程,给开发者更大的选择权。所有的新式类都必须是object的子类。所有的实例方法都必须以self为第一个参数。实例字段是不需要声明的,而静态字段必须在类的头部声明。self就是类实例的句柄(handle)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class FooClass(object):
    version = 0.1

    def __init__(self, nm='John Doe'):
        self.name = nm

    def showname(self):
        print 'Your name is', self.name
        print 'My name is', self.__class__.__name__

    def showver(self):
        print self.version

    def addMe2Me(self, x):
        return x + x

PEP(Python Enhancement Proposal)叫Python增强提案,提供新特性的完整描述,以及添加这些新特性的理由,以及语法、技术实现细节、向后兼容信息等。比如:PEP 20 – The Zen of Python,PEP 7 – Style Guide for C Code,PEP 8 – Style Guide for Python Code,PEP 263 – Defining Python Source Code Encodings 等等。其中PEP 20可以在解释器中调用import this呼出。

Python中调用type(obj)可以得到一个对象的类型对象。调用dir([obj])显示对象的属性或者在没有参数的情况下显示全局变量。

关于Python模块的笔记请参考:Python的模块

请记住在Python中一切都是对象,包括数字,所有的赋值本质上都是拷贝引用而非变量的值。参考:Python的面向对象

1
x = y = z = 1

以上赋值语句将1对象的引用赋值给了x y z三个变量,数字在这里是不可变对象。

Python内部是通过引用计数来跟踪程序中的对象的,赋值(变量或对象属性赋值)、作为参数传递(函数、方法、类实例方法)或者作为容器(List或Dict)的一部分都可以增加对象的引用。减少引用的方式有:函数执行完成自动变量消失,用del明确销毁,将变量赋值给别的对象,从容器中删除,容器本身消失。当对象的引用变为0时,将成为垃圾回收的候选对象。垃圾回收器同时对循环引用的对象进行回收。

所有的内建函数都来自于builtins模块,这个模块在任何用户代码执行前被自动导入到程序中,并且在程序的任何地方都可以使用,除非它们被别的标识符遮蔽了。如xrange type file list long next raw_input str isinstance issubclass iter help dir等,通过dir(__builtins__)查看整个列表。

除了这些内建函数之外,还有 _xxx __xxx__ __xxx 等特殊标识符,_xxx 表示不被 from module import * 导入,__xxx__ 是系统特殊名字不应该自定义,__xxx 是类中的私有名字。这在以后将专门介绍Python中的特殊方法。