3.1.1 Tuple
- 不可变
- 用逗号分隔
最常用的方法就是
In [6]: tup=4,5,6
In [7]: tup
Out[7]: (4, 5, 6)
稍微复杂点的情况可以用括号隔开
In [8]: nested_tup=(4,5,6),(7,8)
In [9]: nested_tup
Out[9]: ((4, 5, 6), (7, 8))
序列和字符也可以转换成tuple
In [10]: tuple([4,0,2])
Out[10]: (4, 0, 2)
In [11]: tuple("strings")
Out[11]: ('s', 't', 'r', 'i', 'n', 'g', 's')
数据被设置成tuple以后就没法改变了,
In [18]: tup=tuple(["foo",[1,2],True])
In [19]: tup[2]=False
Traceback (most recent call last):
File "<ipython-input-19-e84077ea19c6>", line 1, in <module>
tup[2]=False
TypeError: 'tuple' object does not support item assignment
但是可以在其中部分成分水平上就行改变,比方说
In [20]: tup[1].append(3)
In [21]: tup
Out[21]: ('foo', [1, 2, 3], True)
也可以用+来连接两个tuple
In [22]: (4,None,"foo")+(6,0)+("bar",)
Out[22]: (4, None, 'foo', 6, 0, 'bar')
也可以用乘号
("foo","bar")*4
Out[23]: ('foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar')
3.1.1.1 tuple的分解
先定义一个tuple,然后分成a,b,c三个成分
In [24]: tup=(4,5,6)
In [25]: a,b,c=tup
In [26]: b
Out[26]: 5
In [27]: a
Out[27]: 4
In [28]: c
Out[28]: 6
也可以用来交换变量名,像下面那样a,b对换
In [29]: b,a=1,2
In [30]: a
Out[30]: 2
In [31]: b
Out[31]: 1
In [32]: b,a=a,b
In [33]: a
Out[33]: 1
In [34]: b
Out[34]: 2
分解的一般用途是用来对tuple或者list进行重复处理,比方说
seq=[(1,2,3),(4,5,6),(7,8,9)]
for a,b,c in seq:
print("a={0},b={1},c={2}".format(a,b,c))
a=1,b=2,c=3
a=4,b=5,c=6
a=7,b=8,c=9
3.1.2 List
list有以下特点
- 长度可变
- 内容可变
In [1]: a_list=[2,3,4,None]
In [2]: tup=("foo","bar","baz")
In [3]: b_list=list(tup)
In [4]: b_list
Out[4]: ['foo', 'bar', 'baz']
In [5]: b_list[1]="peekaboo"
In [6]: b_list
Out[6]: ['foo', 'peekaboo', 'baz']
3.1.2.1 追加和删除要素
使用append
In [7]: b_list.append("dwarf")
In [8]: b_list
Out[8]: ['foo', 'peekaboo', 'baz', 'dwarf']
也可以在指定位置插入指定内容
In [9]: b_list.insert(1,"red")
In [10]: b_list
Out[10]: ['foo', 'red', 'peekaboo', 'baz', 'dwarf']
删除用remove
In [14]: b_list.append("foo")
...: b_list
Out[14]: ['foo', 'red', 'dwarf', 'foo', 'foo']
In [15]: b_list.append("foo")
...: b_list
...: b_list.remove("foo")
Out[16]: ['red', 'dwarf', 'foo', 'foo', 'foo']
3.1.2.2 连接list
list的叠加也可以通过+来完成
In [18]: [4,None,"foo"]+[7,8,(2,3)]
Out[18]: [4, None, 'foo', 7, 8, (2, 3)]
或者extend,extend要比普通函数来的快速
In [21]: x=[4,None,"foo"]
In [22]: x.extend([7,8,(2,3)])
In [23]: x
Out[23]: [4, None, 'foo', 7, 8, (2, 3)]
3.1.2.3 sort
用来排序
In [28]: a=[7,2,5,1,4]
In [29]: a.sort()
In [30]: a
Out[30]: [1, 2, 4, 5, 7]
3.1.2.3 sort
sort用来排序
In [22]: a=[7,2,5,1,3]
In [23]: a.sort()
In [24]: a
Out[24]: [1, 2, 3, 5, 7]
sort这个函数也有option,比方说key=len,根据长度排序
In [26]: b=["saw","small","He","foxes","six"]
In [27]: b.sort(key=len)
In [28]: b
Out[28]: ['He', 'saw', 'six', 'small', 'foxes']
3.1.2.5 Slicing
这个概念比较搞,特别是对于经历过R和MATLAB的人
In [29]: seq=[7,2,3,7,5,6,0,1]
In [30]: seq[1:5]
Out[30]: [2, 3, 7, 5]
正如上图所示,索引值被安排在了箱体边缘。既可以正过来选择,也可以用负数进行逆向选择。
In [34]: seq[3:4]=[6,3]
In [35]: seq
Out[35]: [7, 2, 3, 6, 3, 5, 6, 0, 1]
::表示隔开,下面的例子就是每隔两个边缘,也就是一个项目,提取字母。
seq[::2]
Out[37]: [7, 3, 3, 6, 1]
反转列表
seq[::-1]
Out[36]: [1, 0, 6, 5, 3, 6, 3, 2, 7]
3.1.3 序列函数
3.1.3.1 enumerate
我们在对一个序列的数据进行逐次处理的时候一般需要保持这个序列的索引值,比方说
i=0
for value in collection:
# 使用value做点事
i += 1
其实python内置了这样的函数enumerate, 返回了(i, value)元组的序列,其中value是元素的值,i 是元素的索引。
for i, value in enumerate(collection):
当你需要对数据建立索引时,一种有效的模式就是使用enumerate建立字典。对每一个value(v)建立相对应的索引 i 。
In [49]: some_list=['foo','bar','baz']
...: mapping={}
...: for i, v in enumerate(some_list):
...: mapping[v]=i
...: mapping
Out[49]: {'foo': 0, 'bar': 1, 'baz': 2}
3.1.3.2 sorted
把序列进行排序并产生新的序列
In [50]: sorted([7,1,2,6,0,3,2])
Out[50]: [0, 1, 2, 2, 3, 6, 7]
3.1.3.3 zip
zip函数可以把多个list, tuple以及其他序列配对,组合成一个数据。
zip可以处理任意长度的序列,它生成的列表长度由最短的序列决定。
In [51]: seq1=['foo','bar','baz']
In [52]: seq2=['one','two','three']
In [53]: zipped=zip(seq1,seq2)
In [55]: list(zipped)
Out[55]: [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]
zip也可以和enumerate同时使用
In [61]: for i,(a,b) in enumerate(zip(seq1,seq2)):
...: print('{0}:{1},{2}'.format(i,a,b))
0:foo,one
1:bar,two
2:baz,three
对于一个已经配对的序列时,zip还可以对其进行拆分。这个语法非常匪夷所思,除了死记硬背也没有别的方法。
In [62]: pitchers=[('Nolan','Ryan'),('Roger','Clemens'),('Schilling','Curt')]
In [63]: first_names,last_names=zip(*pitchers)
In [64]: first_names
Out[64]: ('Nolan', 'Roger', 'Schilling')
In [65]: last_names
Out[65]: ('Ryan', 'Clemens', 'Curt')
3.1.4 字典
dict(字典)可能是python内建数据结构中最重要的。字典拥有灵活尺寸的键值对合集。key and value。用大括号{}
是创建字典的一种方式,在字典中用逗号将key and value分隔。
empty_dict={}
In [67]: d1={'a': 'some value', 'b': [1,2,3,4]}
In [68]: d1
Out[68]: {'a': 'some value', 'b': [1, 2, 3, 4]}
可以通过key来查阅对应的value
In [70]: d1['b']
Out[70]: [1, 2, 3, 4]
也可以进行简单的逻辑判断
In [71]: 'b' in d1
Out[71]: True
也可以添加key和value组
In [72]: d1[7]='an interger'
In [73]: d1
Out[73]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an interger'}
也可以用del或者pop来删除值,不一样的是pop在删除的同时会返回被删的值,可以保存,相当于抠出来
In [72]: d1[7]='an interger'
In [73]: d1
Out[73]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an interger'}
In [74]: d1[5]='what if'
In [75]: d1
Out[75]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an interger', 5: 'what if'}
In [76]: d1['dummy']='another value'
In [77]: del d1[5]
In [78]: d1
Out[78]:
{'a': 'some value',
'b': [1, 2, 3, 4],
7: 'an interger',
'dummy': 'another value'}
In [79]: ret=d1.pop('dummy')
In [80]: ret
Out[80]: 'another value'
In [81]: d1
Out[81]: {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an interger'}
可以用update将两个字典进行合并
In [82]: d1.update({'b':'foo','c':12})
In [83]: d1
Out[83]: {'a': 'some value', 'b': 'foo', 7: 'an interger', 'c': 12}
值得注意的是如果key值和之前的字典里的相同时,将会被覆盖。
3.1.4.1 从序列生成字典
一般情况下,如果有想要把两个序列匹配成字典,会有以下的想法,
mapping ={}
for key, value in zip(key_list, value_list):
mapping[key] = value
由于字典的本质是含有2个元素的元组的集合,所以字典会允许接受一个2元元组的列表作为参数。
In [84]: mapping =dict(zip(range(5),reversed(range(5))))
In [85]: mapping
Out[85]: {0: 4, 1: 3, 2: 2, 3: 1, 4: 0}
3.1.4.2 默认值
我们可以用if-esle给特定的key的value赋值,
if key in some_dict:
value = some_dict[key]
else:
value = default_value
除此以外,还可以用get来,
value = some_dict.get(key, default_value)
文中还介绍了setdefault
,说实话没有看懂,暂时跳过。
3.1.4.3 有效的字典键类型
跳过
3.1.5 集合
集合是一种无序且元素唯一的容器,可以通过set函数或者字母值集与大括号的语法来建立
In [6]: set([2,2,2,1,3,3])
Out[6]: {1, 2, 3}
In [7]: {2,2,2,1,3,3}
Out[7]: {1, 2, 3}
支持数学上的集合操作,比方说取合集
In [8]: a={1,2,3,4,5}
In [9]: b={3,4,5,6,7,8}
In [10]: a.union(b)
Out[10]: {1, 2, 3, 4, 5, 6, 7, 8}
In [11]: a|b
Out[11]: {1, 2, 3, 4, 5, 6, 7, 8}
或者取交集
In [12]: a.intersection(b)
Out[12]: {3, 4, 5}
In [13]: a&b
Out[13]: {3, 4, 5}
值得一提的是,合集里面的元素和字典类似,都是不可变的,如果想要包含列表型的元素,必须先转换为元组。
3.1.6 列表,集合和字典的推导式
列表推导式是最受欢迎的Python语言特性之一。它可以允许过滤一个容器的元素,用一种简明的表达式转换传递给过滤器的元素,从而形成一个新的列表。基本形式为:
[expr for val in collection if condition],
这个相当于以下的for循环
result=[ ]
for value in collection :
if condition:
result.append(expr)
例如给定一个字符串列表,我们可以通过过滤出长度大于2的字符串,并且将其改写成大写。
In [1]: strings=['a','as','bat','car','dove','python']
In [2]: [x.upper() for x in strings if len(x)>2]
Out[2]: ['BAT', 'CAR', 'DOVE', 'PYTHON']
字典和集合也是大同小异
- 字典
dict_comp={key-expr : value-expr for value in collection if condition} - 集合
和列表差不多,只不过是中括号变成了大括号
set_comp={expr for value in collection if condition}
假设我们想要得到一个集合,集合里包含了刚才列表中字符串的长度
In [3]: unique_lengths={len(x) for x in strings}
In [4]: unique_lengths
Out[4]: {1, 2, 3, 4, 6}
这个函数等价于
In [5]: set(map(len,strings))
Out[5]: {1, 2, 3, 4, 6}
接下来举个字典的例子
In [6]: loc_mapping={val: index for index, val in enumerate(strings)}
In [7]: loc_mapping
Out[7]: {'a': 0, 'as': 1, 'bat': 2, 'car': 3, 'dove': 4, 'python': 5}
3.2.3 函数是对象
假设我们在做数据清洗,需要把一些变形运用到如下的字符串列表中,
In [2]: states=[' Alabama','Georgia!','Georgia!','georgia','Fl0rIda',
...: 'south carolina##', 'West virginia?']
我们需要对这些数据进行如下操作,去除空格,移除标点符号,调整大小写。一种方式是可以调用内建的字符串方法,结合标准库中的正则表达re
IPdb [18]: def clean_strings(strings):
...: result=[]
...: for value in strings:
...: value = value.strip()
...: value = re.sub('[!#?]','',value)
...: value = value.title()
...: result.append(value)
...: return result
IPdb [19]: clean_strings(states)
['Alabama', 'Georgia', 'Georgia', 'Georgia', 'Fl0Rida', 'South Carolina', 'West Virginia']
虽然并不是能完全理解python的正则表达,但大概可以看懂这是写了一个函数,分别进行了三步处理。
还有一个方法就是在函数里套用函数,
# 自定义一个小函数
IPdb [20]: def remove_puncatuation(value):
...: return re.sub('[!#?]','',value)
# 把几个小函数合并成一个函数列表
IPdb [21]: clean_ops = [str.strip,remove_puncatuation,str.title]
# 字符和函数都用for循环连续处理起来
IPdb [22]: def clean_strings(strings,ops):
...: result = []
...: for value in strings:
...: for function in ops:
...: value = function(value)
...: result.append(value)
...: return result
IPdb [24]: clean_strings(states,clean_ops)
['Alabama', 'Georgia', 'Georgia', 'Georgia', 'Fl0Rida', 'South Carolina', 'West Virginia']
函数是python里最重要,最基础的代码组织和代码复用的方式。比方说如果你要多次重复相同或类似的代码,就可以写一个可复用的函数。
def my_function(x,y,z=1.5):
if z > 1:
return z*(x+y)
else:
return z/(x+y)
3.2.1 命名空间,作用域和本地函数
函数有两种连接变量的方式:全局,本地。在Python中另外一个更加贴切的描述变量作用域的名称是命名空间。在函数内部,任意变量都会默认分配到本地命名空间。本地命名空间实在函数被调用时生成的,并立即由函数的参数填充。当函数执行结束以后,本地命名空间就会被销毁。
def func():
a = []
for i in range(5):
a.append(i)
当调用func()
时,空的列表a会被建立,五个元素被添加到列表以后,a会在函数推出时销毁。
3.2.2 返回多个值
使用简单语法就可以从函数中返回多个值,如下
def f():
a=5
b=6
c=7
return a,b,c
a,b,c=f()
在数据分析和其他科研应用中,经常需要返回多个值,这里实质上是返回一个对象,也就是元组,而元组之后又被拆分为多个结果变量。刚才的例子也可以被以下的代码替换
return_value = f()
在这个例子中,return_value是一个包含3个元素的元组,像之前那样一次返回多个值还可以返回成字典模式
def f():
a=5
b=6
c=7
return{'a':a,'b':b,'c':c}
其实就是取决于你想做什么。
Lambda函数
210705
Python支持所谓的匿名lambda函数。lambda函数是一种通过单个语句生成函数的方式,其结果是返回值。匿名函数使用lambda关键字定义,该关键字表达在此声明一个函数。
def short_function(x):
return x*2
equiv_anon = lambda x: x*2
因为lambda函数简短易懂,所以会经常被使用。再举个例子,先定一个自定义函数,然后用lambda函数执行。
In [10]: def apply_to_list(some_list,f):
...: return[f(x) for x in some_list]
...: ints=[4,0,1,5,6]
...: apply_to_list(ints,lambda x: x*2)
Out[10]: [8, 0, 2, 10, 12]
另外再举一个例子,将lambda函数出给列表中的sort的方法:
In [15]: strings=['foo','card','bar','aaaa','abab']
In [16]: strings.sort(key=lambda x: len(set(list(x))))
In [17]: strings
Out[17]: ['aaaa', 'foo', 'abab', 'bar', 'card']
3.2.5 柯里化: 部分参数应用
用已有的函数衍生出新的函数。
def add_mumbers(x,y):
return x+y
使用这个函数,就衍生出了一个只有一个变量的新函数,add_five,可以给参数加上5
def add_mumbers(x,y):
return x+y
add_five = lambda y: add_numbers(5,y)
怎么样,是不是都连起来了。虽然也没有什么神奇的地方。