需要写一个处理文件读取的脚本,之前一直没有接触过python
很适合我这种半道出家的,有空要好好学学python,也算多了一个本事,嗯嗯,先把简明语法贴来,没事参考只用!
感谢总结的原作者,找不到原文出处...
1. 关于python的启动
除了直接启动进入解释器之外(不要忘记文件结束符是^Z(win)和^D(*nix/Mac)),另外两种方法也很常用:
python -c "a=int(raw_input('a=')); print a*3"
这是直接执行python语句而不必事先写程序。注意整体用双引号,python语言内部用单引号以免引起混淆。
python -i test.py
执行完后回到解释器。注意-i必须在test.py之前。这个方法也适合-c的情形,如:
python -i -c "a=3"
需要注意的是不要用重定向 python < test.py,原因懒得说了。
2. 脚本的命令行参数
存在sys.argv里。这是一个list.
3. 注释
以#开头,类似于C的//,为单行注释。
4. 输出
用print. 注意复杂类型也可以直接打印,例如list. 比如
import sys
print sys.argv
最后加个逗号可以避免换行。注意每个逗号后实际被追加了一个空格。
print 'a',
print 'b'
由于python有自省功能,也可以打印变量的类型。
print type(sys.argv)
利用解释器学习python的时候可以多用type(_)来确认上一次运行结果的类型。
5. 赋值
和一般的语言一样,且可以是多重的,如
x = y = z = 0
6. 数值类型
整数、浮点数和复数都是支持的。
* 整数没有大小限制:
print 111111111*111111111
print int('12345678987654321')
* 浮点数使用硬件IEEE浮点类型。
print 1.0/3
print float('0.123') # constructor
print 0.1+0.1+0.1-0.3 # not zero!
* 高精度十进制浮点数在decimal模块的Decimal类:
import decimal;
from decimal import Decimal
print Decimal(1)/Decimal(7)
decimal.getcontext().prec = 100 # change precision. default is 28
print Decimal(1)/Decimal(7)
print Decimal('0.1')+Decimal('0.1')+Decimal('0.1')-Decimal('0.3') # exactly zero
* 复数的实部和虚部都是float. 虚数单位用j或者J表示。
a=3+4j
print a.real
print a.imag
print abs(a)
7. 字符串
字符串常量可以用单引号、双引号括起来,也可以用raw字符串r""或者多行串(用"""或者'''包围)。
字符串是不可变的。
print 'a' + 'b' # ab
print 'a' * 3 # aaa
print 'abcd'[2] # c
print len('asdf') # 4
其中第3种用法在C里是无效的。
slicing总是从左到右的,且都是左闭右开区间,因此[-2:]是最后两个字符。
8. 字符串方法分类
判断类
* isalnum()/isalpha()/isdigit()/islower()/isspace()/istitle()/isupper()
查找类
* endswith/startswith(s[,star[,end]]) # 返回bool型
* find/rfind/count(sub[,start[,end]])
变换
* expandtabs([tabsize]) # tabsize默认为8
* replace(old,new[,count]) # 替换所有。如果有count, 则只替换前count个
* ljust/rjust(width[,fillchar])
* lower()/upper()/capitalize()/swapcase()/title()
* lstrip([chars])/rstrip([chars])/strip([chars])
Token处理类
* partition/rpartition(sep) # 从第一次/最后一次出现处分开 e.g 'abc!=12'.partition('!=') returns ('abc','!=','12')
* split/rsplit(sep[,maxsplit]) # 'a--b---c'进行左/右split的结果不一样. 默认是strip后用连续空格隔开
* join(seq) # e.g '-'.join(['a','b','c']) returns 'a-b-c'
8. 字符串格式化
格式化运算符为%,适用于str和unicode,格式为format % values。当要求单参数时values必须是非元组对象,否则
values必须是一个元组(个数和format的需要保持一致),或一个映射(如字典)。例:
print '%(language)s has %(#)03d quote types.' % \
{'language': "Python", "#": 2}
9. 序列操作
参考:Library Reference的3.6节.
python有六种序列类型:str, unicode, list, tuple, buffer, xrange.
大多数序列都有以下操作:x in s, x not in s, s+t, s*n, n*s, s[i], s[i:j], s[i:j:k], len(s), min(s), max(s). i,j,n是整数。
注意乘法(重复操作)是浅拷贝,因此lists=[[]]*3;lists[0].append(3)后得到的是[[3],[3],[3]].
str的in/not in操作可以用来作模式匹配,而不仅仅用来查找单个字符。
10. 列表
列表(lists)是最常用的序列类型,它的各个元素不必有相同的类型。
列表是可变的,甚至可以对它的slice赋值。一些经典的例子。
>>> # Replace some items:
... a[0:2] = [1, 12]
>>> a
[1, 12, 123, 1234]
>>> # Remove some:
... a[0:2] = []
>>> a
[123, 1234]
>>> # Insert some:
... a[1:1] = ['bletch', 'xyzzy']
>>> a
[123, 'bletch', 'xyzzy', 1234]
>>> # Insert (a copy of) itself at the beginning
>>> a[:0] = a
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
>>> # Clear the list: replace all items with an empty list
>>> a[:] = []
>>> a
[]
11. 基本控制流
注意python是靠的缩进而不是begin/end或者{}来指定的语句块。语句块至少要有一条语句,如果实在不需要的话用pass
* while语句
while b > 0:
b--
* if-elif-else语句
注意,没有C中的switch。
if x < 0:
y = -x
elif x == 0:
y = 0
else:
y = x
* for语句
是在一个序列中迭代。
a = ['cat', 'dog', 'bird']
for x in a:
print x, len(x)
注意在迭代的时候修改list很不安全,这时可以迭代它的一个备份,如:
>>> for x in a[:]: # make a slice copy of the entire list
... if len(x) > 6: a.insert(0, x)
...
>>> a
['defenestrate', 'cat', 'window', 'defenestrate']
如果要迭代下标,经常用range函数:
for i in range(len(a)):
print i, a[i]
* break和continue
break和continue的用法一样,但是从break退出和自然推出(for的元素迭代完毕; while的条件为假)是
不一样的。自然退出将执行else语句,这里是一个很好的例子:
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print n, 'equals', x, '*', n/x
break
else:
# loop fell through without finding a factor
print n, 'is a prime number'
另一部分:
1. 函数定义
很简单,就是
def fib(n): # write Fibonacci series up to n
"""Print a Fibonacci series up to n."""
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b
* docstring
注意第一行如果是字符串,则被看做函数的docstring,可以这样查看
print fib.__doc__
* 返回值
什么都可以,比如list. 如果不return将返回None,不带参数的return也会返回None
* lambda函数
f = lambda x: x*x;
print f(5) # 25
* 缺省参数
必须在最前面。它们只被计算一次。例如
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
将打印出
[1]
[1, 2]
模拟如下:
1. 计算缺省值[]:new一个新list(不妨称它为X)并赋值为[]
2. f(1),L=X。注意赋值的是引用,因此L.append(a)实际上修改了X
3. f(2),L=X。注意这个时候X没有重新初始化为[],显然这个时候X已经有一个元素1了...
如果希望每次打印出的都是[1],应该这样写:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
2. 函数调用
* 关键字参数
规则:先位置参数,再关键字参数,且不能给一个参数指定多个值
* 位置参数列表
def fprintf(file, format, *args):
file.write(format % args)
就把第三个参数开始的其他参数包装成一个tuple
调用时,range(*[3,6])相当于range(3,6)
* 关键字参数集合
这里有个和起来的例子
def fun(name, *arguments, **keywords):
print "Hello", name, "!"
# print arguments
print "Arguments: "
for arg in arguments: print arg
keys = keywords.keys()
keys.sort()
# print keywords
print "Keywords:"
for kw in keys: print kw, ':', keywords[kw]
下面是一个调用的例子:
fun('srbga', 1, 'ok', [3,4,7], age=24, gender='male')
下面是另一种调用方式:
fun('srbga', *(1, 'ok', [3,4,7]), **{"age":24, "gender":'male'})
3. 作用域规则
与函数随之而来的问题就是作用域规则。
函数在执行时将引入一个新的符号表。
* assignment. 一定保存在local
* reference. 先看local,再global,最后built-in.
要给global赋值必须用global语句。
函数调用时,实际参数总是放在local符号表中,它们总是对象引用。
4. 再谈列表
* 常用函数:
append(x)/extend(L) # 尾部添加
insert(i,x)/remove(x)/pop([i]) # 插入/删除
index(x)/count(x) # 查找/计数
sort()/reverse() # 排序/反转
* 常用数据结构
Stack. 用append()和不带参数的pop()
Queue. 用append()和pop(0)
5. 用于list的FP方法
* 可以用filter筛选元素。
filter(lambda x:x%2!=0 and x%3!=0, range(2,25)) # [5, 7, 11, 13, 17, 19, 23]
* 可以用map进行映射。甚至可以是多个list的对应元素的运算。
map(lambda x:x*x*x, range(1,5)) # [1, 8, 27, 64]
map(lambda x,y:x+y, range(5), range(5)) # [0, 2, 4, 6, 8]
* 可以用reduce反复对list的前两个元素进行一个运算,直到变成一个元素。
reduce(lambda x,y:x+y, range(1,100)) # 1+2+...+99=4950
reduce(lambda x,y:x*y, range(1,10), 1) # 10!=3628800
* 利用list comprehension可以构造出更为简单的程序
vec=[2,4,6]
[3*x for x in vec] # [6, 12, 18]
[3*x for x in vec if x > 3] # [12, 18]
[[x,x**2] for x in vec] # [[2, 4], [4, 16], [6, 36]]
注意元组必须用括号,例如[x, x**2 for x in vec]是非法的。
甚至可以用二重循环,例如
vec1=[2,4,6]
vec2=[4,3,-9]
[x*y for x in vec1 for y in vec2] # [8, 6, -18, 16, 12, -36, 24, 18, -54]
[vec1[i]*vec2[i] for i in range(len(vec1))] # [8, 12, -54]
还有一个有趣的例子:
[str(round(355/113.0, i)) for i in range(1,6)] # ['3.1', '3.14', '3.142', '3.1416', '3.14159']
6. 元组
元组最大的特点就是不可变。注意元素个数为0或1的表示
empty=()
singleton=1,
另外,多重赋值是一个packing+unpacking的例子,其中packing的结果必须是元组,
而任何sequence都可以unpacking.
7. 集合
可以由序列创建集合,例如
seq=[1,2,3,1,2,4]
s1=set(seq) # set([1,2,3,4])
s2=set([2,4,5]) # set([2,4,5])
1 in s1 # True
a-b # difference. set([1,3])
a|b # union. set([1,2,3,4,5])
a&b # intersection. set([2,4])
a^b # symmetric difference. set([1,3,5])
8. 字典
字典是关联存储器,用不可变对象做关键字,如number, string和tuple。
del b # delete previously defined b
b={} # now b is a mapping
a=[1,2] # a is a list
b[a]=3 # invalid!
a=tuple(a) # now tuple
b[a]=3 # this is ok
b # {(1,2): 3}
b['ok']='yes'
b # {(1,2):3, 'ok':'yes'}
b.keys() # [(1,2), 'ok']
del b[a]
b # {'ok':'yes'}
b.has_key(a) # False
构造函数非常有用:
dict([(x, x**2) for x in (2, 4, 6)]) # {2:4, 4:16, 6:36}
dict(a=1,b=2) # {'a':1, 'b':2}
9. 枚举
除了for x in s外还可以同时用到key和value,或者index和value,如
for k, v in some_dict.iteritems():
print k, v
for i, v in enumerate(some_sequence):
print i, v
还有一个经典的例子是:
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print 'What is your %s? It is %s.' % (q, a)
在for中可以用reversed()或者sorted()修饰。如果还需要去掉重复的话,可以
for f in sorted(set(seq)):
print f
10. 条件
注意条件不见得是Boolean型。0和None是假,其他为真。
* in / not in
* is / is not
* a < b == c
* A and not B or c 等价于 (A and (not B)) or c
* and和or是短路运算符,当用于其他类型的运算时,返回最后一个计算出来的表达式。例如
'a' or 'b' or 'c' # 'a'
'' or '' or 'a' or 'b' # 'a'
'a' and 'b' and 'c' # 'c'
'a' and 'b' and '' and 'c' # ''
条件中不能有赋值,因此if a = 2: exit()是非法的
11. 比较
同类sequence的比较为字典序比较,元素本身是序列时递归比较。
可以比较不同类的序列,结果按照type的字典序比较,因此list<string<tuple。数值型按照数值大小排序,因此0==0.0
12. 模块
一个包含定义和语句的文件称为模块(module),主文件名就是模块名,在模块内部用__name__表示。
import一个完成模块将把该模块本身引入到符号表中,例如
import sys
print sys.argv
而如果用from的话是直接把它的符号表中的一个或多个符号引入,例如
from sys import argv
print argv
这样做有个潜在危险就是引入的符号和现有符号相冲突。甚至可以引入*(不包含以下划线开始的符号)
模块搜索路径放在PYTHONPATH环境变量中,启动后和其他一些系统相关的路径混合后放在sys.path中。注意自定义模块不要和系统模块重名,不然很可能出错。另外,关于编译后的pyc和pyo,不会提高执行效率,只会减少启动时间。它们是系统无关的,可以不依赖于.py而单独存在。
可以用dir()来查看模块的符号表,注意内置函数在__builtin__中。
import __builtin__
dir(__builtin__)
13. 包
有了模块,你不必担心你的程序中的变量和其他程序中的变量冲突;有的包,你不必担心你的模块名
和其他模块名冲突。包的管理和Java类似,每个目录中需要有一个__init__.py,import的时候最后一项
之前的必须都为包名(最后一项可以是包名或者模块名,但不能是符号名)