对于大多数程序员来说,有了一定功底,就会觉得语言大同小异,再学习动态语言,也不会觉得是难事。因此,我只做一些简单的记录,记录会跟静态语言混淆的地方。
数据类型,变量
python中同一个变量,可以反复赋值,而且可以是不同类型的变量。这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错,笔记java.
1
2
3
4a = 123 # a是整数
print a
a = 'ABC' # a变为字符串
print a通常用全部大写,表示常量。Python根本没有任何机制保证PI不会被改变,所以,用全部大写的变量名表示常量只是一个习惯上的用法
list
Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素
用索引来访问list中每一个位置的元素,记得索引是从0开始的,这点跟lua有区别1
2
3nameList = ['xiaoming','xiaoli','xiaozhang']
print nameList
print len(nameList)如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素,以此类推,可以获取倒数第2个、倒数第3个:
1
2nameList[-1]
nameList[-2]要删除list末尾的元素,用pop()方法
- 要删除指定位置的元素,用pop(i)方法,其中i是索引位置
tuple
元组,跟list的区别是,元组是不能修改的,不能赋值成其他的元素,1
nameList = ('xiaoming','xiaoli','xiaozhang')
dic
字典,普遍用法
判断key是否存在
1
2
3'key' in dict
或者
dict.get('key')删除key:pop(key)
set
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
s = set([1, 2, 3])
重复元素在set中自动被过滤:
1
2
3>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
set([1, 2, 3])通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果
通过remove(key)方法可以删除元素:
- set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
1
2
3
4
5
6>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
set([2, 3])
>>> s1 | s2
set([1, 2, 3, 4])
字符编码
- 支持中文,需要在开头添加
1 | # -*- coding: utf-8 -*- |
- 在Python中,采用的格式化方式和C语言是一致的,用%实现,举例如下:
1 | a = 'Hi ,%s,you have 钱数:%d' % ('Hammercui',10000) |
函数
- abs()绝对值函数
- cmp(x,y)比较函数
- int() 转int函数
- 声明函数:
def
,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
1 | def my_abs(x): |
- 默认参数
1 | def power(x, n=2): |
- fact(n)阶乘函数。递归不做优化的话,会导致栈溢出
slice切片操作符
L[0:3]表示从list L中取出索引0到3,不包括3的元素,返回list
前10个数,每两个取一个:1
2 L[:10:2]
[0, 2, 4, 6, 8]
- 字符串’xxx’或Unicode字符串u’xxx’也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:
1 | >>> 'ABCDEFG'[:3] |
迭代
判断是否能是迭代
1
2
3
4
5
6
7>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整数是否可迭代
False如果要对list实现类似Java那样的下标循环怎么办?Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:
1
2
3# 模仿java写法
for i,value in enumerate(['a','b','c']):
print i,value
列表生成式
但如果要生成[1x1, 2x2, 3x3, …, 10x10]怎么做?方法一是循环,方法二如下:1
2>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
可以增加条件1
2>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
还可以双层循环1
2>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
生成器generator
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)
定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。这样就保证了,每次next都是从上次的结果之后执行的。
高阶函数
指函数名也是变量,可以把函数作为参数传递。
把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式
map函数
接收两个参数,第一个函数,第二个序列(可以是list,tuple),返回结果list
比如,把一个int类型的list转成string类型的list1
2
3map(str,[1,2,3,4])
结果:
['1','2','3','4']
reduce函数
接收两个参数,第一函数,但这个函数必须接收2个参数,第二个序列,返回list。
reduce与map的区别是1
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
相当于每次传入2个参数,把结果作为新的参数,跟下一个参数再传入
filter函数
传入两个参数,和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
例如,在一个list中,删掉偶数,只保留奇数,可以这么写:1
2
3
4
5
6def is_odd(n):
return n % 2 == 1
filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
结果
# 结果: [1, 5, 9, 15]
sorted函数
与其他相反,序列在前,函数在后
匿名函数
比如函数1
2def f(x)
return x*x
可以写作lambda x:x*x
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
装饰器
假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
偏函数
当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
比如二进制转换成int1
2
3
4
5
6def int2(x, base=2):
return int(x, base)
int2('1000000')
结果
64
使用偏函数写法就是1
2
3
4
5import functools
int2 = functools.partical(int,base=2)
int2('1000000')
结果
64