Python for genomics class day03

1 数据类型

Data types and manipulations:dictionary, set

Conditional statements:if, elif, else, break, continue

Comments and style:[https://realpython.com/python-pep8/]


# Python style
#
# PEP8
# https://realpython.com/python-pep8/
# https://www.python.org/dev/peps/pep-0008/
#
# Python history
#
# Guido van Rossum, creator in 1989. He retired last month. Final job was with Dropbox.
# https://en.wikipedia.org/wiki/Python_(programming_language)

a = 1
b = 1.0
c = '1'
d = [1, 2]
e = (1, 2)
f = { 'x':1, 'y':2}
g = {1, 2}

#a是int整数型
print('a =', type(a))
#b是浮点型(float)
## a = <class 'int'>
print('b =', type(b))
#c是字符串型(str)
## b = <class 'float'>
print('c =', type(c))
#d是列表,可以看到列表使用中括号创建
## c = <class 'str'>
print('d =', type(d))
#e是元组(tuple),使用小括号创建
## d = <class 'list'>
print('e =', type(e))
#f是字典类型(dict),使用大括号创建
## e = <class 'tuple'>
print('f =', type(f))
#g是集合类型,也是使用大括号创建,但是没有key
## f = <class 'dict'>
print('g =', type(g))
## g = <class 'set'>

对几个重要的类型做一个详细解释.具体内容参考Python基础教程这本书

1.1 列表(list)和元组(tuple)

列表和元组是非常类似的,不同点在于列表可以修改而元组不可以.

1.1.1 创建列表

可以使用中括号[]来创建列表

edward = ['Edward Gumby', 42]
john = ['John Smith', 50]
database = [edward, john]
database
## [['Edward Gumby', 42], ['John Smith', 50]]

同样的,列表中的元素也可以是列表,就像上面的例子所展示的.

test = ["shen"]
type(test)
## <class 'list'>
test[0]
## 'shen'

1.1.2 列表通用的操作

有几种操作适用于所有序列,包括索引,切片,相加,相乘和成员资格检查.另外,Python还提供了一些内置函数,可用于确定序列的长度以及找出序列中最大和最小的元素.

1.1.2.1 索引(index)

与R类型,列表都有序号,但是需要注意的是,python中的序号都是从0开始的.

greeting = 'Hello'
greeting[0]
## 'H'
greeting[1]
## 'e'

注意上面例子中greeting的类型是str,也就是说python中的str也可以通过序号进行提取某个字符.

这就称之为索引,其中使用-1代表最后一个元素.

greeting[-1]
## 'o'

1.1.2.2 切片(slicing)

切片是用来访问特定范围内的元素.为此,可使用两个索引,并用冒号分隔.

test = ["shen", "wang", "zhao", "qian", "sun"]
test[0]
## 'shen'
test[0:1]
## ['shen']
test[1:3]
## ['wang', 'zhao']
test[1:-1]
## ['wang', 'zhao', 'qian']
test[1:]
## ['wang', 'zhao', 'qian', 'sun']

通过上面例子可以看到,对于切片的两个索引,出来的结果包含左边索引的结果,而不包含右边index的结果.如果需要包含某一边的所有结果,则只需要将冒号的某一边空出来即可.

当然也可以使用负数来进行索引,因为我们知道-1是最后一个元素,-2是倒数第二个元素.

test = [1,2,3,4,5]
test[-3:-1]
## [3, 4]
test[-3:0]
## []
test[-3:]
## [3, 4, 5]

可以看到如果执行切片操作时,第一个索引指定的元素位于第二个索引指定的元素后面,结果就为空序列.

1.1.2.3 序列相加

可以使用加法运算符来拼接序列.

[1, 2, 3] + [4, 5, 6]
## [1, 2, 3, 4, 5, 6]
'Hello,' + 'world!'
## 'Hello,world!'

从错误消息可知,不能拼接列表和字符串,,虽然它们都是序列.一般而言,不能拼接不同类型的序列.

1.1.2.4 乘法

将序列与数x相乘时,将重复这个序列x次来创建一个新序列:

'python' * 5
## 'pythonpythonpythonpythonpython'
[1,2,3] * 5
## [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

None,空列表和初始化

空列表是使用不包含任何内容的两个方括号([])表示的.如果要创建一个可包含10个元素的列表,但没有任何有用的内容,可像前面那样使用[42]*10.但更准确的做法是使用[0]*10,这将创建一个包含10个零的列表.但是更为准确合适的作发是使用None,在python中,None代表什么都没有.

None
[None]
## [None]
sequence = [None] * 10
sequence
## [None, None, None, None, None, None, None, None, None, None]

1.1.2.5 成员资格

要检查特定的值是否存在与序列中,可以使用判断运算符in.返回值为逻辑值,满足时返回为True,不满足时返回False.

permisions = "rw"

'w' in permisions
## True
'T' in permisions
## False
users = ["shen", "wang"]#一个列表
'wang' in users
## True
'tao' in users
## False

1.1.2.6 长度,最大值和最小值

使用内置函数可以得到一个列表的长度,最大值及最小值.

number = [1,2,3,4]#列表
len(number)
## 4
max(number)
## 4
min(number)
## 1
string = ["a", 1 ,2,3]
string
# len(string)
# max(string)
## ['a', 1, 2, 3]
len("shen")
## 4
len(["shen"])
## 1

1.1.3 列表,Python的主力

列表是Python中使用非常广泛的类型.

1.1.3.1 list()函数

list()函数可以用来简历列表.

list("shen")
## ['s', 'h', 'e', 'n']
list([1,2,3])
## [1, 2, 3]

列表是可以改变的.

1.1.3.2 列表的基本操作

列表的最大有点在于它是可以修改的.

1.1.3.2.1 修改列表:给元素赋值
x = [1,2,3]
x
## [1, 2, 3]
x[2] = 5
x
## [1, 2, 5]
1.1.3.2.2 删除列表中的元素

使用del语句可以删除列表中的某个元素.

names = ["alice", "beth", "cecil"]
del names[1]
names
## ['alice', 'cecil']
1.1.3.2.3 使用切片对多个元素进行修改
name = list("name")
name
## ['n', 'a', 'm', 'e']
name[2:] = list("shen")
name
## ['n', 'a', 's', 'h', 'e', 'n']
name[4:] = list("wa")
name
## ['n', 'a', 's', 'h', 'w', 'a']

需要注意的是,使用切片进行赋值或者修改,是可以将其替换为不同长度的东西的.

test = list("wang")
test
## ['w', 'a', 'n', 'g']
test[2:] = list("shen")
test
## ['w', 'a', 's', 'h', 'e', 'n']
test[2:3]
## ['s']
test[2:3] = list("shen")
test
## ['w', 'a', 's', 'h', 'e', 'n', 'h', 'e', 'n']

还可以使用这个特性进行元素的插入:

numbers = [1, 5]
numbers
## [1, 5]
numbers[1:1]##这是一个空列表
## []
numbers[1:1] = [2, 3, 4]#在第二个位置开始,插入新的list
numbers
## [1, 2, 3, 4, 5]

当然,还可以利用这个特性删除切片.

numbers
## [1, 2, 3, 4, 5]
numbers[1:4]
## [2, 3, 4]
numbers[1:4] = []
numbers
## [1, 5]

当然,删除仍然可以使用del语句实现,最后结果是一致的.

1.1.3.2.4 列表方法

方法是与某列对象联系紧密的函数,一般使用下列方法进行调用:

object.method(arguments)

这也是跟R不同的一点,R中并没有这类方法.

  1. append

用于将一个对象添加到列表末尾.

test = [1,2,3]
test
## [1, 2, 3]
test.append(2)
test
## [1, 2, 3, 2]
test.append([5,6,7])
test
## [1, 2, 3, 2, [5, 6, 7]]
test.append(10)
test
## [1, 2, 3, 2, [5, 6, 7], 10]
test + [20]
## [1, 2, 3, 2, [5, 6, 7], 10, 20]
test + [10,20]
## [1, 2, 3, 2, [5, 6, 7], 10, 10, 20]
  1. clear

用来清空列表的内容.

test = [1,2,3]
test.clear()
test
## []

完全清空所有的内容.

  1. copy

用来复制列表.在Python中,直接使用=将一个列表赋值给另外一个对象名,其实只是关联而已,也就是说其实同一个列表关联到了两个名字而已.

a = [1,2,3]
b = a
b[1] = 10
b
## [1, 10, 3]
a##a也会改变,和b保持一致
## [1, 10, 3]

想要把a和b指向两个独立的不同的列表,需要使用copy,将b关联到a的副本.

a = [1,2,3]
b = a.copy()
b[1] = 10
b
## [1, 10, 3]
a
## [1, 2, 3]
  1. count

用来统计指定的元素在列表中出现的次数.

a = [1,2,3,4,4]
a.count(1)
## 1
a.count(4)
## 2

count()一共有两个参数,第一个参数为’self’,也就是前面的对象,后买你的参数为value指定要统计的元素.

  1. extend

这个方法跟append的区别在于,它可以将一个独立的列表添加到列表后面.

a = [1,2,3]
b = [4,5,6]
a.extend(b)
a
## [1, 2, 3, 4, 5, 6]
a.append(b)
a
## [1, 2, 3, 4, 5, 6, [4, 5, 6]]
a + b
## [1, 2, 3, 4, 5, 6, [4, 5, 6], 4, 5, 6]
a
## [1, 2, 3, 4, 5, 6, [4, 5, 6]]

需要注意这几种方法的区别.

  1. index

用于查找列表中指定值第一次出现的索引.

test = list("shen")
test
## ['s', 'h', 'e', 'n']
test.index("h")
## 1
  1. insert

将一个对象插入到列表中.

a = [1,2,3]
a
## [1, 2, 3]
a.insert(1, "four")
a
## [1, 'four', 2, 3]
a.insert(0, [1, "shen"])
a
## [[1, 'shen'], 1, 'four', 2, 3]

insert第一个参数用来指定需要插入的位置(索引),第二个参数用来指定需要插入的内容.插入的内容可以是单个元素,也可以是列表.

  1. pop

删除一个元素,默认为最后一个.修改原列表,并返回删除的元素.

x = [1,2,3]
x.pop()
## 3
x
## [1, 2]

当然,也可以使用index'参数,指定需要删除的元素.

  1. remove

用于删除第一个为指定值的元素.

test = list("shen")
test.remove("h")
test
## ['s', 'e', 'n']

需要注意的是,只删除第一个符合要求的元素,其他的不会删除.

  1. reverse

将元素顺序按相反顺序重新排列.

  1. sort

对列表元素重新进行排列.

x = ['aardvark', 'abalone', 'acme', 'add', 'aerate', "shen", "wang", "china", "us"]
x.sort()
x
## ['aardvark', 'abalone', 'acme', 'add', 'aerate', 'china', 'shen', 'us', 'wang']

sort函数还可以通过设置key参数来自定义排列规则,如可以将key设置为函数len,从而将列表按照元素的长度进行排序.

x.sort(key = len)
x
## ['us', 'add', 'acme', 'shen', 'wang', 'china', 'aerate', 'abalone', 'aardvark']

1.1.3.3 元组(tuple):不可修改的序列

元组也是序列,但是跟列表不同的是,元组是不能修改的.

1.1.3.3.1 创建元组

使用小括号(())可以创建元组.

x = (1,2,3)
x
## (1, 2, 3)
type(x)
## <class 'tuple'>
()#空元组
## ()

创建只含有一个元素的元组比较特殊,需要在元素后面加上逗号.如果不加逗号,不能常见元组.

x = (42)
x
## 42
type(x)
## <class 'int'>
y = (x, )
y
## (42,)
type(y)
## <class 'tuple'>
3 * (10+3)
## 39
3 * (10+3,)
## (13, 13, 13)

看了上面的例子,可以很好的明白为什么需要加上逗号,因为小括号在数学运算中还表示运算优先级的意思,所以需要使用逗号来区分是进行数学运算,还是要创建元组.

当然,和列表一样,我们还可以使用tuple()函数来创建元组.

tuple([1, 2, 3])
## (1, 2, 3)
tuple("shen")
## ('s', 'h', 'e', 'n')

你可能意识到了,元组并不太复杂,而且除创建和访问其元素外,可对元组执行的操作不多.元组的创建及其元素的访问方式与其他序列相同.

那为什么要单独出来一个元组类型呢?有两个原因:

  1. 它们用作映射中的键(以及集合的成员),而列表不行.

  2. 有些内置函数和方法返回元组,这意味着必须跟它们打交道.只要不尝试修改元组,与元组打交道通常意味着像处理列表一样处理它们(需要使用元组没有的index和count等方法时例外).

1.1.4 总结

新的函数:

Function Meaning
len(seq) 返回序列长度
list(seq) 将序列转换为列表
max(args) 返回序列或者一组参数中的最大值
min(args) 返回序列或者一组参数中的最小值
reversed(seq) 反向排列序列
sorted(seq) 对列表或者序列进行排序
tuple(seq) 将序列转换为元组

列表(list)的方法

Method Meaning
append 将一个对象附加到列表末尾
clear 清空列表的内容
copy 复制列表
count 计算指定的元素在列表中出现了多少次
extend 同时将多个值附加到列表末尾
index 在列表中查找指定值第一次出现的索引
insert 将一个对象插入列表
pop 从列表中删除一个元素(默认为最后一个元素)
remove 用于删除第一个为指定值的元素
reverse 按相反的顺序排列列表中的元素
sort 对列表进行排序

1.2 字符串

1.2.1 字符串的基本操作

所有的标准序列操作(索引,切片,乘法,成员资格检查,长度,最小值和最大值)都适用于字符串.但是注意字符串是不可变的.

1.2.1.1 字符串格式

将值转换为字符串并设置其格式是一个重要的操作,需要考虑众多不同的需求,因此随着时间的流逝,Python提供了多种字符串格式设置方法.以前,主要的解决方案是使用字符串格式设置运算符——百分号.这个运算符的行为类似于C语言中的经典函数printf:在%左边指定一个字符串(格式字符串),并在右边指定要设置其格式的值.指定要设置其格式的值时,可使用单个值(如字符串或数字),可使用元组(如果要设置多个值的格式),还可使用字典,其中最常见的是元组.

format = "Hello, %s. %s enough for ya?"
format
## 'Hello, %s. %s enough for ya?'
values = ('world', 'Hot')
values
## ('world', 'Hot')
format % values
## 'Hello, world. Hot enough for ya?'

上述格式字符串中的%s称为转换说明符,指出了要将值插入什么地方.s意味着将值视为字符串进行格式设置.如果指定的值不是字符串,将使用str()将其转换为字符串.其他说明符将导致其他形式的转换.例如,%.3f将值的格式设置为包含3位小数的浮点数.

更为常用的是使用字符串方法format.使用这种方法时,每个替换字段都用花括号括起,其中可能包含名称,还可能包含有关如何对相应的值进行转换和格式设置的信息.

"{}, {} and {}".format("first", "second", "third")
## 'first, second and third'
"{0}, {1} and {2}".format("first", "second", "third")
## 'first, second and third'
"{3} {0} {2} {1} {3} {0}".format("be", "not", "or", "to")
## 'to be or not to be'

在大括号中的数字代表着format中的内容的索引,如果不写,则默认按照先后顺序替换.

当然,也可以使用命名的方法来提示如何替换.

"{name} is a {position:s}.".format(position="postdoc", name="Japser Shen")
## 'Japser Shen is a postdoc.'

1.2.1.2 字符串方法

字符串的方法要多得多,很多都是从模块string那继承过来的.

介绍一些比较常用的.

1.2.1.2.1 center

通过在两边添加填充字符(默认为空格)让字符串居中.

"The Middle by Jimmy Eat World".center(40)
## '     The Middle by Jimmy Eat World      '
"The Middle by Jimmy Eat World".center(40, "*")
## '*****The Middle by Jimmy Eat World******'
1.2.1.2.2 find

在字符串中查找子串,如果找到,就返回字串的第一个字符的索引,否则返回-1.

'With a moo-moo here, and a moo-moo there'.find('moo')
## 7
'With a moo-moo here, and a moo-moo there'.find('shen')
## -1

你还可指定搜索的起点和终点.

subject = '$$$ Get rich now!!! $$$'
subject
## '$$$ Get rich now!!! $$$'
subject.find('$$$')
## 0
subject.find('$$$', 1) # 只指定了起点
## 20
subject.find('!!!', 0, 16) # 同时指定了起点和终点
## -1

请注意,起点和终点值(第二个和第三个参数)指定的搜索范围包含起点,但不包含终点.这是Python惯常的做法.

另外的和find相关的方法还包括:

rfind,index,rindex,count,startswithendswith.

1.2.1.2.3 join

join是一个非常重要的字符串方法,其作用与split相反,用于合并序列的元素.

seq = list("shen")
seq
## ['s', 'h', 'e', 'n']
sep = '+'
sep
## '+'
sep.join(seq)
## 's+h+e+n'

这个方法跟R中的paste函数非常类似.

注意,所合并序列的元素必须都是字符串.如果list元素都是数字,是会报错的.

1.2.1.2.4 lower

返回字符串的小写版本.

'Trondheim Hammer Dance'.lower()
## 'trondheim hammer dance'

类似或者同一类方法还有:

islower,istitle,isupper,translate,capitalize,casefold,swapcase,title,upper.

1.2.1.2.5 replace

将指定子串都替换为另一个字符串,并返回替换后的结果.

'This is a test'.replace('is', 'eez')
## 'Theez eez a test'

一共两个参数,第一个是需要替换的内容,第二个是替换之后的内容.

到这里应该发现,其实这就是R中的stringr包所要做的工作.

另外还需要参考的函数:

tranlateexpandtabs.

1.2.1.2.6 split

其和join作用相反,用于将字符串拆分为序列.

'1+2+3+4+5'.split('+')
## ['1', '2', '3', '4', '5']
'Using the default'.split()
## ['Using', 'the', 'default']

可以看到,默认拆分的标识符是空格( ).

1.2.1.2.7 strip

用于将字符串的开头和末尾的空白删除.

' internal whitespace is kept '.strip()
## 'internal whitespace is kept'

当然,还可以通过设置参数,来指定删除的字符类型.

'*** SPAM * for * everyone!!! ***'.strip(' *!')
## 'SPAM * for * everyone'

但是还是只能删除开头和末尾.

相似函数或者方法:

lstriprstrip.

1.2.1.2.8 translate

方法translatereplace一样替换字符串的特定部分,但不同的是它只能进行单字符替换.这个方法的优势在于能够同时替换多个字符,因此效率比replace高.

使用translate前必须创建一个转换表.这个转换表指出了不同Unicode码点之间的转换关系.要创建转换表,可对字符串类型str调用方法maketrans,这个方法接受两个参数:两个长度相同的字符串,它们指定要将第一个字符串中的每个字符都替换为第二个字符串中的相应字 符.

table = str.maketrans('cs', 'kz')
table
## {99: 107, 115: 122}
type(table)
## <class 'dict'>

可以看到,转换表是一个字典类型.

'this is an incredible test'.translate(table)
## 'thiz iz an inkredible tezt'
1.2.1.2.9 判断字符串是否满足某些特定的条件

很多字符串方法都以is打头,如isspace,isdigitisupper,它们判断字符串是否具有特定的性质(如包含的字符全为空白,数字或大写).如果字符串具备特定的性质,这些方法就返回True,否则返回False.

参考其他函数:

isalnum,isalpha,isdecimal,isdigit,isidentifier,islower,isnumeric,isprintable,isspace,istitle,isupper.

1.2.1.3 总结

将字符串的方法总结如下:

Method Meanings
string.capitalize() 返回字符串的副本,但将第一个字符大写.
string.casefold() 返回经过标准化后的字符串,标准化类似于转换为小写,但更适合用于对Unicode字符串进行不区分大小写的比较
string.center(width[, fillchar]) 返回一个长度为(len(string), width)的字符串.这个字符串的中间包含当前字符串,但两端用fillchar指定的字符(默认为空格)填充
string.count(sub[, start[, end]]) 计算子串sub出现的次数,可搜索范围限定为string[start:end]
string.encode([encoding[,errors]]) 返回使用指定编码和errors指定的错误处理方式对字符串进行编码的结果,参数errors的可能取值包含’strict’,‘ignore’,’replace’等
string.endswith(suffix[,start[,end]]) 检查字符串是否以suffix结尾,还可使用索引start和end来指定匹配范围
string.expandtabs([tabsize]) 返回将字符串中的制表符展开为空格后的结果,可指定可选参数tabsize(默认为8)
string.find(sub[, start[, end]]) 返回找到的第一个子串sub的索引,如果没有找到这样的子串,就返回-1;还可将搜索范围限制为string[start:end]
string.format(...) 实现了标准的Python字符串格式设置.将字符串中用大括号分隔的字段替换为相应的参数,再返回结果
string.format_map(mapping) 类似于使用关键字参数调用format,只是参数是以映射的方式提供的
string.index(sub[, start[, end]]) 返回找到的第一个子串sub的索引,如果没有找到这样的子串,将引发ValueError异常;还可将搜索范围限制为string[start:end]
string.isalnum() 检查字符串中的字符是否都是字母或数
string.isalpha() 检查字符串中的字符是否都是字母
string.isdecimal() 检查字符串中的字符是否都是十进制数
string.isdigit() 检查字符串中的字符是否都是数字
string.isidentifier() 检查字符串是否可用作Python标识符
string.islower() 检查字符串中的所有字母都是小写的
string.isnumeric() 检查字符串中的所有字符是否都是数字字符
string.isprintable() 检查字符串中的字符是否都是可打印的
string.isspace() 检查字符串中的字符是否都是空白字符
string.istitle() 检查字符串中位于非字母后面的字母都是大写的,且其他所有字母都是小写的
string.isupper() 检查字符串中的字母是否都是大写的
string.join(sequence) 将string与sequence中的所有字符串元素合并,并返回结果
string.ljust(width[, fillchar]) 返回一个长度为max(len(string),width)的字符串,其开头是当前字符串的副本,而末尾是使用fillchar指定的字符(默认为空格)填充的
string.lower() 将字符串中所有的字母都转换为小写,并返回结果
string.lstrip([chars]) 将字符串开头所有的chars(默认为所有的空白字符,如空格,制表符和换行符)都删除,并返回结果
str.maketrans(x[,y[,z]]) 一个静态方法,它创建一个供translate使用的转换表.如果只指定了参数x,它必须是从字符或序数到Unicode序数或None(用于删除)的映射;也可使用两个表示源字符和目标字符的字符串调用它;还可提供第三个参数,它指定要删除的字符
string.partition(sep) 在字符串中搜索sep,并返回元组(sep前面的部分, sep, sep后面的部分)
string.replace(old,new[,max]) 将字符串中的子串old替换为new,并返回结果;还可将最大替换次数限制为max
string.rfind(sub[,start[,end]]) 返回找到的最后一个子串的索引,如果没有找到这样的子串,就返回-1;还可将搜索范围限定为string[start:end]
string.rindex(sub[,start[,end]]) 返回找到的最后一个子串sub的索引,如果没有找到这样的子串,就引发ValueError异常;还可将搜索范围限定为string[start:end]
string.rjust(width[,fillchar]) 返回一个长度为max(len(string),width)的字符串,其末尾为当前字符串的拷贝,而开头是使用fillchar指定的字符(默认为空格)填充的
string.rpartition(sep) 与partition相同,但从右往左搜索
string.rstrip([chars]) 将字符串末尾所有的chars字符(默认为所有的空白字符,如空格,制表符和换行符)都删除,并返回结果
string.rsplit([sep[, maxsplit]]) 与split相同,但指定了参数maxsplit,从右往左计算划分次数
string.split([sep[, maxsplit]]) 返回一个列表,其中包含以sep为分隔符对字符串进行划分得到的结果(如果没有指定参数sep,将以所有空白字符为分隔符进行划分);还可将最大划分次数限制为maxsplit
string.splitlines([keepends]) 返回一个列表,其中包含字符串中的所有行;如果参数keepends为True,将包含换行符
string.startswith(prefix[,start[,end]]) 检查字符串是否以prefix打头;还可将匹配范围限制在索引start和end之间
string.strip([chars]) 将字符串开头和结尾的所有chars字符(默认为所有空白字符,如空格,制表符和换行符)都删除,并返回结果
string.swapcase() 将字符串中所有字母的大小写都反转,并返回结果
string.title() 将字符串中所有单词的首字母都大写,并返回结果
string.translate(table) 根据转换表table(这是使用maketrans创建的)对字符串中的所有字符都进行转换,并返回结果
string.upper() 将字符串中所有的字母都转换为大写,并返回结果
string.zfill(width) 在字符串左边填充0(但将原来打头的+或-移到开头),使其长度为width

1.2.2 字典

需要将一系列值组合成数据结构并通过编号来访问各个值时,列表很有用.本章介绍一种可通过名称来访问其各个值的数据结构.这种数据结构称为映射(mapping).字典是Python中唯一的内置映射类型,其中的值不按顺序排列,而是存储在键下.键可能是数,字符串或元组.

在很多情况下,使用字典都比使用列表更合适.下面是一些字典的用途:

  1. 表示棋盘的状态,其中每个键都是由坐标组成的元组;

  2. 存储文件修改时间,其中的键为文件名;

  3. 数字电话/地址簿.

1.2.2.1 创建和使用字典

phonebook = {'Alice':'2341', 'Beth':'9102', 'Cecil':'3258'}
phonebook
## {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}

字典由键(key)及其相应的值(value)组成,这种键-值对称为项(item).在前面的示例中,键为名字,而值为电话号码.每个键与其值之间都用冒号(:)分隔,项之间用逗号分隔,而整个字典放在花括号内.空字典(没有任何项)用两个花括号表示,类似于下面这样:{}.

注意:

在字典(以及其他映射类型)中,键必须是独一无二的,而字典中的值无需如此.

1.2.2.1.1 使用dict函数
items = [('name', 'Gumby'), ('age', 42)]
items
## [('name', 'Gumby'), ('age', 42)]
type(items)
## <class 'list'>
d = dict(items)
d
## {'name': 'Gumby', 'age': 42}
type(d)
## <class 'dict'>
d["name"]
## 'Gumby'
d["age"]
## 42

items是一个列表,然后包含两个元组,每个元组都包含两个元素,然后每个元组的第一个元素作为键,第二个元素作为值.

还可以使用另外一种形式,使用dict创建字典.

d = dict(name='Gumby', age=42)
d
## {'name': 'Gumby', 'age': 42}
len(d)
## 2
1.2.2.1.2 字典的基本操作

字典的基本行为在很多方面都类似于序列.

  1. len(d)返回字典d包含的项(键-值对)数.
  2. d[k]返回与键k相关联的值.
  3. d[k] = v将值v关联到键k.
  4. del d[k]删除键为k的项.

虽然字典和列表有多个相同之处,但也有一些重要的不同之处.

  1. 键的类型:字典中的键可以是整数,但并非必须是整数.字典中的键可以是任何不可变的类型,如浮点数(实数),字符串或元组.
  2. 自动添加:即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项.然而,如果不使用append或其他类似的方法,就不能给列表中没有的元素赋值.
d = dict(name='Gumby', age=42)
d
## {'name': 'Gumby', 'age': 42}
d["sex"] = "male"
d
## {'name': 'Gumby', 'age': 42, 'sex': 'male'}
  1. 成员资格:表达式k in d(其中d是一个字典)查找的是键而不是值,而表达式v in l(其中l是一个列表)查找的是值而不是索引.这看似不太一致,但你习惯后就会觉得相当自然.毕竟如果字典包含指定的键,检查相应的值就很容易.

  2. k in d检查字典d是否包含键为k的项.

创建空的字典,使用大括号进行.

x = {}
x
## {}
x['name'] = "shen"
x
## {'name': 'shen'}
x = {"name":"shen", "age":29}
x
## {'name': 'shen', 'age': 29}
1.2.2.1.3 适用于字典的方法
  1. clear

方法clear删除所有的字典项,这种操作是就地执行的(就像list.sort一样),因此什么都不返回(或者说返回None).

d = {}
d['name'] = 'Gumby'
d['age'] = 42
d
## {'name': 'Gumby', 'age': 42}
d.clear()
d
## {}
  1. copy

方法copy返回一个新字典,其包含的键-值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本).

x = {'username':'admin', 'machines':['foo', 'bar', 'baz']}
x
## {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
y = x.copy()
y
## {'username': 'admin', 'machines': ['foo', 'bar', 'baz']}
y['username'] = 'mlh'
y['machines'].remove('bar')
x
## {'username': 'admin', 'machines': ['foo', 'baz']}
y
## {'username': 'mlh', 'machines': ['foo', 'baz']}

如你所见,当替换副本中的值时,原件不受影响.然而,如果修改副本中的值(就地修改而不是替换),原件也将发生变化,因为原件指向的也是被修改的值(如这个示例中的’machines’列表所示).

为避免这种问题,一种办法是执行深复制,即同时复制值及其包含的所有值,等等.为此,可使用模块copy中的函数deepcopy.

from copy import deepcopy
d = {}
d['names'] = ['Alfred', 'Bertrand']
d
## {'names': ['Alfred', 'Bertrand']}
c = d.copy()
dc = deepcopy(d)
d['names'].append('Clive')
d
## {'names': ['Alfred', 'Bertrand', 'Clive']}
c
## {'names': ['Alfred', 'Bertrand', 'Clive']}
dc
## {'names': ['Alfred', 'Bertrand']}
  1. fromkeys

方法fromkeys创建一个新字典,其中包含指定的键,且每个键对应的值都是None.

{}.fromkeys(['name', 'age'])
## {'name': None, 'age': None}

这个示例首先创建了一个空字典,再对其调用方法fromkeys来创建另一个字典.

  1. get

方法get为访问字典项提供了宽松的环境.通常,如果你试图访问字典中没有的项,将引发错误.

d = {}
print(d['name'])

而使用get不会这样:

print(d.get('name'))
## None
d.get('name', 'N/A')
## 'N/A'
  1. items

方法items返回一个包含所有字典项的列表,其中每个元素都为(key, value)的形式.字典项在列表中的排列顺序不确定.

d = {'title':'Python Web Site', 'url':'http://www.python.org', 'spam':0}
d
## {'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0}
d.items()
## dict_items([('title', 'Python Web Site'), ('url', 'http://www.python.org'), ('spam', 0)])
test = d.items()
test
## dict_items([('title', 'Python Web Site'), ('url', 'http://www.python.org'), ('spam', 0)])
type(test)
## <class 'dict_items'>

返回值属于一种名为字典视图的特殊类型.字典视图可用于迭代.另外,你还可确定其长度以及对其执行成员资格检查.其中每一个元素都是一个元组.

it = d.items()
it
## dict_items([('title', 'Python Web Site'), ('url', 'http://www.python.org'), ('spam', 0)])
len(d)
## 3
len(it)
## 3
  1. kyes

方法keys返回一个字典视图,其中包含指定字典中的键.

d
## {'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0}
d.items()
## dict_items([('title', 'Python Web Site'), ('url', 'http://www.python.org'), ('spam', 0)])
d.keys()
## dict_keys(['title', 'url', 'spam'])
  1. pop

方法pop可用于获取与指定键相关联的值,并将该键-值对从字典中删除.

d = {'x':1, 'y':2}
d
## {'x': 1, 'y': 2}
d.pop('x')
## 1
d
## {'y': 2}
  1. popitem

方法popitem类似于list.pop,但list.pop弹出列表中的最后一个元素,而popitem随机地弹出一个字典项,因为字典项的顺序是不确定的,没有“最后一个元素”的概念.如果你要以高效地方式逐个删除并处理所有字典项,这可能很有用,因为这样无需先获取键列表.

d = {'url':'http://www.python.org', 'spam':0, 'title':'Python Web Site'}
d
## {'url': 'http://www.python.org', 'spam': 0, 'title': 'Python Web Site'}
d.popitem()
## ('title', 'Python Web Site')
d
## {'url': 'http://www.python.org', 'spam': 0}
  1. setdefault

方法setdefault有点像get,因为它也获取与指定键相关联的值,但除此之外,setdefault还在字典不包含指定的键时,在字典中添加指定的键-值对.

d = {}
d.setdefault('name', 'N/A')
## 'N/A'
d
## {'name': 'N/A'}
d['name'] = 'Gumby'
d.setdefault('name', 'N/A')
## 'Gumby'
d
## {'name': 'Gumby'}
  1. update

方法update使用一个字典中的项来更新另一个字典.

d = {
 'title':'Python Web Site',
 'url':'http://www.python.org',
 'changed':'Mar 14 22:09:15 MET 2016'
}
d
## {'title': 'Python Web Site', 'url': 'http://www.python.org', 'changed': 'Mar 14 22:09:15 MET 2016'}
x = {'title':'Python Language Website'}
d.update(x)
d
## {'title': 'Python Language Website', 'url': 'http://www.python.org', 'changed': 'Mar 14 22:09:15 MET 2016'}

对于通过参数提供的字典,将其项添加到当前字典中.如果当前字典包含键相同的项,就替换它.

  1. values

方法values返回一个由字典中的值组成的字典视图.不同于方法keys,方法values返回的视图可能包含重复的值.

d = {"a":1, "b":2, "c":3}
d
## {'a': 1, 'b': 2, 'c': 3}
d.values()
## dict_values([1, 2, 3])

1.2.2.2 总结

1.2.2.2.1 新的函数
Function Meaning
dict(seq) 从键-值对,映射或关键字参数创建字典
1.2.2.2.2 适用于字典的方法
Method Meaning
clear 删除所有的字典项,是就地执行的,不返回任何值
copy 返回一个新字典,其包含的键值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本.如果想要深复制,即同时复制值及其包含的所有值,可使用模块copy中的函数deepcopy
fromkeys 创建一个新字典,其中包含指定的键,且每个键对应的值都是None.
get 获得字典种的值
items 返回一个包含所有字典项的列表
keys 返回一个字典视图,其中包含指定字典中的键.
pop 用于获取与指定键相关联的值,并将该键值对从字典中删除.
setdefault 有点像get,因为它也获取与指定键相关联的值,但除此之外,setdefault还在字典不包含指定的键时,在字典中添加指定的键-值对.
update 使用一个字典中的项来更新另一个字典.
values 返回一个由字典中的值组成的字典视图.不同于方法keys,方法values返回的视图可能包含重复的值.

2 条件,循环及其他语句

2.1 条件和条件语句

# test which values are True and False
# The rule:What is True? Anything that is not False!
values = [False, None, 0, 0.0, "", '', [], {}, (), True, 'str', "0", -1, 3, 1000, '\'\'']

for v in values:
    if (v):
        print("True :", v)
    else:
        print("False:", v)
## False: False
## False: None
## False: 0
## False: 0.0
## False: 
## False: 
## False: []
## False: {}
## False: ()
## True : True
## True : str
## True : 0
## True : -1
## True : 3
## True : 1000
## True : ''

3 Day03作业

读取fasta文件.

3.1 fasta文件的格式

>Example_Sequence-1
TCGGGACAGCTTGTTGCCCCATCCATGGGGGTCTGCTCTAAGACCCTTTAATAATAGCGG
TTATTTTCGCAGGCAGGCACTGATCCTTAATACGGAAGCTACAACCCACAATCTGCCTAG
CCGTGATAAACCTTCGCCCCGTGCCTGGTCTACCATCTACTCAGGAAGTTGACCGGTCGG
TTACCTACCTCATGGCGTATGATTGTCCCGGACAGTGCTCCTATGGCTTGGAACCTAACG
CTCACGGGTTGCTAT
>Example_Sequence-2
CTACCGAGAGGTGCCGTCAAATTCTGCCTTTAACCCCCACATGTAGCTCAGTAACTGAGC
GGCTTGACGGCCCAGGTGCAGAGACGTACGATGCGTGAGCCTGCACAATAACCCACCATT
TAGACCATTCAAAAGCTTCCAGACAGTCTAGCTCGAAGAAATTT

可以看到fasta文件每个sequence都是以>开头,所以这可以作为识别每个sequence的标志.

3.2 read_fasta函数

def read_fasta(fasta_filename):
    '''
    Go through file, reading one line at a time, using a
    dictionary to store the DNA sequence for each of the FASTA
    entries (Gavin Sherlock, November 28, 2019)
    '''    
    with open(fasta_filename, mode='r') as fasta_file:

        sequences = {}#创建一个空字典
        
        for line in fasta_file:#对每一行进行读取
            line = line.rstrip()#除去每行的右边的空格
            if line.startswith('>'):# 如果这一行是以`>`开头,则是一个新的sequence
                line = line.lstrip('>')#将这行的`>`标志去除掉
                sequences[line] = '' # intialize dictionary for this entry
                currSeqName = line
            else:
                sequences[currSeqName] += line
    return(sequences)

3.2.1 open函数

open(name[, mode[, buffering]])

参数说明:

  1. name:一个包含了你要访问的文件名称的字符串值.

  2. mode:mode决定了打开文件的模式:只读,写入,追加等.所有可取值见如下的完全列表.这个参数是非强制的,默认文件访问模式为只读(r).

  3. buffering:如果buffering的值被设为0,就不会有寄存.如果 buffering的值取1,访问文件时会寄存行.如果将 buffering的值设为大于1的整数,表明了这就是的寄存区的缓冲大小.如果取负值,寄存区的缓冲大小则为系统默认.

不同模式打开文件的完全列表:

Mode Meaning
r 以只读方式打开文件.文件的指针将会放在文件的开头.这是默认模式.
rb 以二进制格式打开一个文件用于只读.文件指针将会放在文件的开头.这是默认模式.
r+ 打开一个文件用于读写.文件指针将会放在文件的开头.
rb+ 以二进制格式打开一个文件用于读写.文件指针将会放在文件的开头.
w 打开一个文件只用于写入.如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除.如果该文件不存在,创建新文件.
wb 以二进制格式打开一个文件只用于写入.如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除.如果该文件不存在,创建新文件.
w+ 打开一个文件用于读写.如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除.如果该文件不存在,创建新文件.
wb+ 以二进制格式打开一个文件用于读写.如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除.如果该文件不存在,创建新文件.
a 打开一个文件用于追加.如果该文件已存在,文件指针将会放在文件的结尾.也就是说,新的内容将会被写入到已有内容之后.如果该文件不存在,创建新文件进行写入.
ab 以二进制格式打开一个文件用于追加.如果该文件已存在,文件指针将会放在文件的结尾.也就是说,新的内容将会被写入到已有内容之后.如果该文件不存在,创建新文件进行写入.
a+ 打开一个文件用于读写.如果该文件已存在,文件指针将会放在文件的结尾.文件打开时会是追加模式.如果该文件不存在,创建新文件用于读写.
ab+ 以二进制格式打开一个文件用于追加.如果该文件已存在,文件指针将会放在文件的结尾.如果该文件不存在,创建新文件用于读写.

3.2.2 with语句

可以参考下面的帖子:

https://blog.csdn.net/u012609509/article/details/72911564

Avatar
Xiaotao Shen
Postdoctoral Research Fellow

Metabolomics, Multi-omics, Bioinformatics, Systems Biology.

Related

Next
Previous
comments powered by Disqus