轻轻松松搞定python--2

序列

序列是一种有序的集合,就是诸如数组、链表或者对外呈现类似结构的数据结构,特点就是拥有一串的元素,并且这些元素的存放是有顺序的。
python内置多种序列类型,对所有这些序列类型,有一些通用的操作方法可以调用(见后面'序列的一般操作'章节),同时各种序列类型各自还有一些特有方法。

字符串

字符串str是一种字符序列,每个元素是一个字符,python没有单个字符类型,只有字符串类型,一个字符也是字符串。
python对字符串的支持非常强大,使用起来很方便。

字符串字面量

字符串字面量(literal)就是字符串常量的书写方式,包括单引号、双引号、三引号,raw字符多种方式

  • 单引号
    用单引号把一串字符包起来,就构成一个字符串,特殊字符需要用转义,转义方法和c语言基本类似。

    >>> string = 'life is short, you need python' 
    >>> print(string)         #print是内置打印函数,类似c语言的printf,注意print函数默认会自动添加换行
    life is short, you need python
    >>> 
    >>> string = 'life is short, \nyou need python\n'  
    >>> print(string)
    life is short, 
    you need python
    
    >>> 
    >>> len(string)    #内置函数len可以获取字符串长度即字符个数,注意不像c语言的字符串,python字符串是不需要'\0'结尾的
    32
    
  • 双引号
    双引号和单引号的用法类似,但双引号里可以包含单引号,单引号里可以包含双引号而不需要转义。

    >>> string = "life is short, 'you need python'"
    >>> print(string)
    life is short, 'you need python'
    >>> 
    >>> string = 'life is short, "you need python"' 
    >>> print(string)
    life is short, "you need python"
    >>>
    
  • 三引号
    三引号支持多行, 换行、tab等特殊字符可以直接输入,所见即所得。三引号字符串也同样可以使用转义字符。

    >>> string = '''life is short, 
    ... \tyou need python'''       # 在python命令中换行时,会显示‘...’, 表示可以继续输入
    >>> print(string) 
    life is short, 
            you need python
    >>> 
    
  • raw字符串
    raw字符串用于禁止转义, 用小写r和和大写R作前缀,可以和前面的几种引号组合

    >>> string = r'life is short, \nyou need python\n'
    >>> print(string)
    life is short, \nyou need python\n
    >>> 
    
格式化字符串

字符串的格式化不需要调用函数,直接使用 % 实现

>>> string = 'string = %s' % 'abc'
>>> print(string)
string = abc
>>> 
>>> string = '%s = %d' % ('abc', 123)       #多个参数要使用括号
>>> print(string)                    
abc = 123
字符串编码

字符在内存中是用16位unicode表示的,因此字符可以不只是ascii字符,还可以包括中文、日文、德文等世界上几乎所有的语言字符。可以用内置函数 ord 获取单个字符的unicode值,用内置函数 chr 把单个unicode值转成单个字符,还可以用16进制unicode值直接书写字符串。

>>> ord('a')  
97
>>> chr(97)
'a'
>>> 
>>> ord('我')
25105
>>> chr(25105)
'我'
>>> 
>>> string = '\u6211\u662f\u8c01'
>>> print(string)
我是谁
>>> 

字符串在python内存中的编码方式是unicode,每个字符固定2字节编码,处理速度快但浪费存储空间。一般各种文档为了节省存储空间,使用的编码不是直接用unicode,而是用诸如ASCII(纯英文)、国标GB2312(汉字)、UTF-8(通用)等其他编码,这些编码对不同字符采用不同长度的编码,可节省存储空间。
python解析器解析代码时,默认是以UTF-8编码来读取的,因此若非有特殊原因,python代码文件建议用UTF-8编码保存。

字符串通过 encode 方法把unicode编码转成其他编码方式,生成字节串,生成的字节串可以用于传输或写到文件中。
注意:原始的字符串并没有被改变,返回的字节串是新生成的

>>> 'who am i'.encode(encoding="utf-8")
b'who am i'
>>> 
>>> 'who am i'.encode(encoding="ascii")
b'who am i'
>>> 
>>> 'who am i, 我是谁'.encode(encoding="utf-8")
b'who am i, \xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81'
>>> 
>>> 'who am i, 我是谁'.encode(encoding="gb2312")
b'who am i, \xce\xd2\xca\xc7\xcb\xad'
>>> 

编码后的字节串可以通过 decode 方法解出字符串,还可以通过内置函数 str 解出字符串
注意:原始的字节串并没有被改变,返回的字符串是新生成的

>>> b'who am i'.decode(encoding="utf-8")
'who am i'
>>> 
>>> b'who am i'.decode(encoding="ascii")
'who am i'
>>> b'who am i, \xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81'.decode(encoding="utf-8")
'who am i, 我是谁'
>>> 
>>> b'who am i, \xce\xd2\xca\xc7\xcb\xad'.decode(encoding="gb2312")            
'who am i, 我是谁'
>>> 
>>> str(b'who am i, \xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81', encoding="utf-8")
'who am i, 我是谁'
>>> 
字符串方法

字符串内置很多方法(字符串其实是对象,python里一切皆对象),以下罗列出常用的方法并简要说明,需要用到时可以再查阅python文档。

  • 统计

    方法 说明
    str.count(sub[, start[, end]]) 统计子字符串
  • 编码

    方法 说明
    str.encode(encoding="utf-8", errors="strict") 编码,转成字节串bytes
  • 查找和替换

    方法 说明
    str.startswith(prefix[, start[, end]]) 检查字符串前缀
    str.endswith(suffix[, start[, end]]) 检查字符串后缀
    str.find(sub[, start[, end]]) 正序(即左查找)查找字符串,返回第一个找到的位置,没找到则返回-1
    str.rfind(sub[, start[, end]]) 右查找
    str.index(sub[, start[, end]]) 和find的唯一区别是,没找到抛出ValueError异常
    str.rindex(sub[, start[, end]]) 和rfind的唯一区别是,没找到抛出ValueError异常
    str.replace(old, new[, count]) 替换字符串
    str.expandtabs(tabsize=8) 把tabs转成空格,注意并不是每个tab都转成tabsize个空格,而是跟列对齐有关
  • 格式化

    方法 说明
    str.format(*args, **kwargs) 格式化
    str.format_map(mapping) 格式化,参数是个字典
  • 检查字符串

    方法 说明
    str.isalnum() 是否由字母和数字组成
    str.isalpha() 是否只由字母组成
    str.isdecimal() 是否是10进制数
    str.isdigit() 是否只包含‘0’~‘9’
    str.isidentifier() 是否是有效的Python标识符
    str.islower() 是否全是小写
    str.isnumeric() 是否是数字,可以不只包括数字字符‘0’~‘9’, 甚至可以包括汉字‘一’、‘二’、‘三’等
    str.isprintable() 是否全是可打印字符
    str.isspace() 是否全是空白字符
    str.istitle() 是否是标题,标题的每个单词的首字母大写
    str.isupper() 是否全是大写
  • 对齐处理

    方法 说明
    str.center(width[, fillchar]) 居中处理
    str.ljust(width[, fillchar]) 左对齐, 并使用空格填充至长度width
    str.rjust(width[, fillchar]) 右对齐, 并使用空格填充至长度width
    str.zfill(width) 右对齐, 并使用‘0’填充至长度width
  • 大小写处理

    方法 说明
    str.capitalize() 把首字母变成大写,其余变成小写
    str.casefold() 变成小写,不仅仅针对英文字母,也包括其他字母,如德文
    str.lower() 转为全小写
    str.upper() 转为全大写
    str.swapcase() 翻转大小写
    str.title() 标题化,每个单词首字母大写
  • 去头去尾处理

    方法 说明
    str.lstrip([chars]) 去头
    str.rstrip([chars]) 去尾
    str.strip([chars]) 去头去尾
  • 映射处理

    方法 说明
    static str.maketrans(x[, y[, z]]) 创建字符映射表, 是个静态方法
    str.translate(table) 根据映射表,转换字符串
  • 连接和分割处理

    方法 说明
    str.join(iterable) 用字符串作为分隔符,把序列中的元素连接起来
    str.partition(sep) 正序分离字符串,sep为第一个
    str.rpartition(sep) 反序分离字符串,sep为最后一个
    str.split(sep=None, maxsplit=-1) 正序分割字符串,可以指定最多分割次数,从左到右查找sep
    str.rsplit(sep=None, maxsplit=-1) 反序分割字符串,可以指定最多分割次数
    str.splitlines([keepends]) 按行分割

二进制字节串

二进制字节串有两种类型,bytes和bytearray,bytes是不可变的,一旦初始化就不可修改,对其修改都是生成新字节串,bytearray的元素可以修改,并且长度也是可变的。

  • bytes字面量
    bytes常量用 b 前缀加上ascii字符串或小于256的16进制或8进制数表示

    >>> a = b'\x10\x11\x12'  #每个元素用2位16进制数表示
    >>> 
    >>> a = b'\20\21\022\347' #每个元素用2或3位8进制数表示, 个人建议不要用8进制,比如b'\378', 最后的8不是8进制数的一部分,晕吧?
    >>> 
    >>> a = b'abc'  #每个元素用1个asciii字符表示
    >>> 
    >>> a = b'\x10\x11\x12abc' #混合使用16进制数和ascii字符
    >>>
    >>> len(a) #获取字节串长度
    6
    
  • 字节串创建

    >>> a = bytes()
    >>> a
    b''         #不是None
    >>> 
    >>> a = bytearray()
    >>> a
    bytearray(b'')      #不是None
    >>> 
    >>> a = bytes(10)
    >>> a
    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'     #元素默认为0
    >>> 
    >>> a = bytearray(10)
    >>> a
    bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')  ##元素默认为0
    >>> 
    >>> a = bytes(range(10))
    >>> a
    b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'
    >>> 
    

    实际上,bytes或bytearray可以通过bytes(obj)或bytearray(obj)创建,只要obj支持buffer protocol。至于什么是buffer protocol可以查阅python规范

  • 字节串方法
    str的方法几乎都有对应的bytes和bytearray方法,这里只列出几个特殊的。

    >>> bytes.fromhex('2Ef0F1f2') #
    b'.\xf0\xf1\xf2'
    >>> 
    >>> b'.\xf0\xf1\xf2'.hex()
    '2ef0f1f2'
    >>> 
    

列表和元组

列表和元组的每个元素可以是不同的数据类型,元组是不可变的,一旦初始化就不可更改,列表是可变的。

  • 创建
    列表用中括号或内置函数list创建,元组用圆括号或内置函数tuple创建。

    >>> a = []  # 空列表
    >>> a
    []
    >>> b = ()  # 空元组
    >>> b
    ()
    >>> 
    >>> a = (1,2,'aaa', None)  # 初始化值
    >>> a
    (1, 2, 'aaa', None)
    >>> 
    >>> b = [1,2,'aaa', None] # 初始化值
    >>> b
    [1, 2, 'aaa', None]
    >>> 
    >>> a = [1, 2, [3, 4], (5, 6)] # 元素甚至可以是列表或元组
    >>> a
    [1, 2, [3, 4], (5, 6)]
    
  • 列表推导
    即List Comprehensions,是指创建列表时,列表的每一个元素通过一个表达式来推导,表达式一般是个for循环, 可以带if表达式,还可以是多重循环。
    使用列表推导可以精简代码,减少代码行,但不建议写太复杂的推导表达式,可读性太差。
    注意元组没有类似推导,如果写成'元组推导',实际生成的不是元组,而是另一种东西,叫生成器(generator),后面会讲。

    [x*x for x in range(1, 11)]                # 列表为:[1x1, 2x2, 3x3, ..., 10x10]
    
    [x*x for x in range(1, 11) if x % 2 == 0]  # 列表为:[2x2, 4x4, ..., 10x10], 只有偶数部分
    
    a = (1, 2, 3)
    b = (4, 5, 6)
    [x*y for x in a for y in b]                # 列表为:[4, 5, 6, 8, 10, 12, 12, 15, 18]
    
    (x*x for x in range(1, 11))                # 生成的不是元组,是生成器
    
  • 列表排序
    列表内建排序 sort(, key=None, reverse=None)* 方法,使用 '<' 比较元素,排序是在原列表上直接操作的,如果某个元素比较失败,则整个排序失败,并且已经被修改的元素不会还原。
    参数 key:一个函数,用来预处理每个比较 key, 比如 key=str.lower
    参数 reverse:是否反序,True则反序。
    元组没有排序方法,因为元组是不可变的。

range

range用来生成一个数序列, 一般用在 for 循环中,range是不可变的,一旦生成后就不可更改,range的每个元素是在访问到时才生成的,因此就算是一个很大整数的range也不会占用太多内存。这点和元组不同,也是为什么有元组了为何还需要range类型的原因。

>>> range(10)
range(0, 10)
>>> a = range(10)
>>> a
range(0, 10)
>>> 
>>> list(range(10))      
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> 
>>> list(range(0, 10, 2))
[0, 2, 4, 6, 8]

序列的一般操作

字符串、字节串、元组、列表等序列类型有一些通用的操作。

  • 通用操作

    操作 说明
    x in s 检查序列中是否有元素等于x,有为True,否则为False
    x not in s 以上面刚好相反
    s + t 连接两个序列, 注意:如果是不可变序列,则返回新的序列,不是修改原序列
    s[i] 第i个元素, i可以为负数,-1表示最后一个,-2为倒数第二个,以此类推
    s[i:j] 子序列切片:第i到第j-1元素, i,j可以为负数,-1表示最后一个,-2为倒数第二个,以此类推
    len(s) 序列长度
    s * n or n * s 相当于序列重复n次
    s[i] 第i个元素
    s[i:j] 子序列切片:第i到第j-1元素
    s[i:j:k] 子序列切片:第i到第j-1元素,间隔为k
    min(s) 元素最小值
    max(s) 元素最大值
    s.index(x[, i[, j]]) 从[i:j]中第一个值等于x的元素的索引
    s.count(x) 值等于x的元素个数
  • 可变序列特有的操作
    可变序列是指序列的元素在是可以修改的,列表是可变序列,字符串、字节串、元组、range是不可变序列

    操作 说明
    s[i] = x 第i个元素改写为x
    s[i:j] = t 用t[0:j-i]替换s[i:j],t不一定是序列,只要是可迭代对象就行
    del s[i:j] 删除第i到第j-1元素,也可以写成 s[i:j] = []
    s[i:j:k] = t 跟s[i:j] = t类似,指定间隔
    del s[i:j:k] 跟del s[i:j]类似,指定间隔
    s.append(x) 把x加入到序列的尾部
    s.clear() 清空序列s 也可以写成 del s[:]
    s.copy() 浅拷贝 也可以写成 s[:]
    s.extend(t) or s += t 把序列t加入到序列s的尾部
    s *= n 相当于序列s重复n次,直接修改原序列s
    s.insert(i, x) 把x插入到i位置 也可以写成 s[i:i] = [x]
    s.pop([i]) 弹出i元素,即返回i元素,并从序列中删除i元素
    s.remove(x) 删除序列中等于x的元素,如果有多个,则只删除第一个
    s.reverse() 第一个元素和最后一个对调,第二个和倒数第二个对调,以此类推
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容