美文网首页
python 入门 第4篇: 数据类型2 - 字符串类型

python 入门 第4篇: 数据类型2 - 字符串类型

作者: apksec | 来源:发表于2018-04-06 16:39 被阅读0次

    1. 字符串的定义方式

    在python中, 定义字符串可以使用以下几种方式:

    • 以双引号开头、双引号结尾, 中间的就是字符串的内容
    • 以单引号开头、单引号结尾, 中间的就是字符串的内容
    • 以三个双/单引号开头、三个双/单引号结尾, 中间的就是字符串的内容
    • 将其他数据类型通过str/unicode的构造方法生成一个新的字符串对象

    为了让输出的结果更加明显, 我们再学习一个python的内置方法:

    • repr: 该方法可以将python中的任何对象转化为供解释器读取的形式
    # -*- coding: utf-8 -*-
    
    #1. 以双引号开头、双引号结尾, 中间的就是字符串的内容
    s1 = "Hello World"
    print s1
    #输出: Hello World
    print type(s1)
    #输出: <type 'str'
    print repr(s1)
    #输出: 'Hello World'
    
    #2. 以单引号开头、单引号结尾, 中间的就是字符串的内容
    s2 = 'Hello World'
    print s2
    #输出: Hello World
    print type(s2)
    #输出: <type 'str'
    print repr(s2)
    #输出: 'Hello World'
    
    #3. 以三个双/单引号开头、三个双/单引号结尾, 中间的就是字符串的内容
    s3 = '''Hello World'''
    print s3
    #输出: Hello World
    print type(s3)
    #输出: <type 'str'
    print repr(s3)
    #输出: 'Hello World'
    
    #4. 将其他数据类型通过str的构造方法生成一个新的字符串对象
    i = 1000
    s4 = str(i)
    print s4
    #输出: 1000
    print type(s4)
    #输出: <type 'str'
    print repr(s4)
    #输出: '1000'
    
    #需要注意的是, 双引号、单引号、三引号必须成对使用, 不能相互混合使用
    s5 = 'ab"
    #报错: EOL while scanning string literal
    

    2. 字符串的编码方式

    在学习python字符串的时间, 是一定会提到字符编码的问题, 尤其是在python2中

    那么到底什么是字符编码? 感兴趣的朋友可以阅读下 字符编码: Ascii、GB2312、UTF-16、UTF-8

    简单的说, 字符串中的最小单位是字符, 字符串也就是一个一个字符的集合. 字符编码是指对于字符集中的字符将其编码为特定二进制数(010101)的方法, 以便计算机处理. 常见的字符编码有 ASCII 编码、UTF-8 编码、GBK 编码等

    在python2中默认的编码方式为: ASCII编码, 而在python3中默认的编码方式则为: UNICODE编码, 我们可以通过使用下面的两行代码来检测当前版本中python解释器的默认编码方式

    import sys
    print sys.getdefaultencoding()
    
    2.1 python2中的字符串编码方式

    在python2中, 字符串有两种类型: str 和 unicode, 其中str包含了很多种编码方式, 默认情况下是ASCII编码, 还有GBK编码、UTF-8编码等. 不同编码之间不能直接进行转换, 如gbk编码转换成utf-8编码, 必须先将其转换为unicode编码后在转换为最终的编码, 如下图所示:

    python2字符串类型相互转换

    从一种编码方式转换为UNICODE编码方式的过程叫做decode(解码), 从UNICODE编码方式转换为另一种编码方式的过程叫做encode(编码), python在字符串类方法中提供了这两个方法用于进行不同编码之间的转换

    #在这种情况下, 中字使用的是当前系统中的默认编码, Windows中文版默认系统编码为GBK
    s = '中'
    print type(s)
    #输出: <type 'str'
    print repr(s)
    #输出: '\xd6\xd0'
    
    #我们尝试将GBK编码的中字转换为UTF-8编码的中字
    #上面介绍过说当str的一种编码方式要转换为str的另一种编码方式时需要两步
    #1. 首先将其转换为UNICODE编码
    s_unicode = s.decode('gbk')
    print type(s_unicode)
    #输出: <type 'unicode'
    print repr(s_unicode)
    #输出: u'\u4e2d'
    
    #2. 将UNICODE编码再转换为最终需要的编码方式
    s_utf8 = s_unicode.encode('utf-8')
    print type(s_utf8)
    #输出: <type 'str'
    print repr(s_utf8)
    #输出: '\xe4\xb8\xad'
    

    在对字符串进行decode(解码)时, 需要指定当前字符串的编码方式, 因为解释器必须要使用正确的编码方式去解码才能接出正确的信息来. 这就好比说, 你家的门只有你自己的钥匙可以打开, 用我的钥匙无法打开你家的门一个道理, 如果给一个错误的编码方式, 我们来看一下会怎么样

    #在这种情况下, 中字使用的是当前系统中的默认编码, Windows中文版默认系统编码为GBK
    s = '中'
    print type(s)
    #输出: <type 'str'
    print repr(s)
    #输出: '\xd6\xd0'
    
    #这时我们非要告诉编译器说原先的字符串编码方式为utf-8
    #运行解码时将直接报错
    #UnicodeDecodeError: 'utf8' codec can't decode byte 0xd6 in position 0: invalid continuation byte
    s_unicode = s.decode('utf-8')
    
    #报错这还是好的, 有的不会报错, 看下面例子
    #下面的 苑 字在当前Windows系统中也是使用GBK编码的
    s1 = '苑'
    
    #这时我们非要告诉编译器说原先的字符串编码方式为utf-8
    s1_unicode = s1.decode('utf-8')
    print type(s1_unicode)
    #输出: <type 'unicode'
    print repr(s1_unicode)
    #输出: u'\u0537'
    print s1_unicode
    #输出: Է
    
    #为什么上面的会直接报错, 而下面的不报错也成功转为UNICODE编码了, 但输出却是乱码了呢?
    #这是就是因为给错了原先字符串的编码方式, 解释器很傻的, 你跟它说什么它就信什么
    #你跟它说这个字符串是UTF-8编码的, 那么它就会去以UTF-8的编码方式去解码为UNICODE
    #解不出来就报错, 能解出来就解出来了, 但是解来的是乱码而已
    #我们按照GBK去编码, 它去按照UTF-8去解码, 两套完全不同的编码规则怎么可能解出正确的信息呢?
    

    而当我们在py文件开头增加了# -- coding: utf-8 --后这一切又变了

    # -*- coding: utf-8 -*-
    
    s = '中'
    print type(s)
    #输出: <type 'str'
    print repr(s)
    #输出: '\xe4\xb8\xad'
    
    s_unicode = s.decode('utf-8')
    print type(s_unicode)
    #输出: <type 'unicode'
    print repr(s_unicode)
    #输出: u'\u4e2d'
    print s_unicode
    #输出: 中
    

    按照我们之前的说法, 此时应该报错啊? 为什么不但没有报错, 还能正确的输出最终的信息呢?

    还记得在 python 入门 第1篇: 基本语法规范 中提到的coding: utf-8的作用吗? 它是用来用来定义源代码文件编码的, 当我们在源文件开头指明了说该文件以什么方式来编码时, python解释器在加载源代码文件内容到内存的时间就会以这种编码方式存储到内存中, 而当没有指明编码方式时, 解释器也不知道此时应该用什么编码方式将内容存储到内存中, 就只能以当前系统的默认编码方式来存储了

    所以, 为了验证我们所说的是不是对的, 我们只需要告诉解释器一个错误的编码方式看看它会不会报错就行了

    # -*- coding: utf-8 -*-
    
    #此时由于头部指明了源文件的编码方式, 所以此时 中 将会以utf-8的编码方式存放在内存中
    s = '中'
    print type(s)
    #输出: <type 'str'
    print repr(s)
    #输出: '\xe4\xb8\xad'
    
    #首先我们以utf-8去解码为UNICODE还会不会报错, 可以发现没有问题
    s_unicode = s.decode('utf-8')
    print type(s_unicode)
    #输出: <type 'unicode'
    print repr(s_unicode)
    #输出: u'\u4e2d'
    print s_unicode
    #输出: 中
    
    #此时我们告诉解释器一个错误的编码方式, 看它会报错不
    #一运行立马报错
    #UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 2: incomplete multibyte sequence
    s1_unicode = s.decode('gbk')
    

    这就是为什么有时我们从一个文件中读取内容显示出来的中文内容是乱码的原因. 那是因为你读取时所使用的编码方式与保存在文件中的编码方式不同所造成的, 所以一定要按照存储在文件时的编码方式去读取才不会出现乱码

    2.2 python中Unicode字符串的定义方式

    说了半天, 在python中字符串的解码、编码都离不开Unicode编码, 那么我们在python如何直接定义一个Unicode类型的字符串呢? 很简单, 在引号的前面加u即可

    # -*- coding: utf-8 -*-
    
    #定义了一个Unicode类型的字符串
    s = u'你好'
    print s
    #输出: 你好
    print type(s)
    #输出: <type 'unicode'
    print repr(s)
    #输出: u'\u4f60\u597d'
    
    #由于s已经是Unicode编码的了, 所以当我们想转换为str的其他编码时将会非常方便, 直接转就行
    s_gbk = s.encode('gbk')
    print type(s_gbk)
    #输出: <type 'str'
    print repr(s_gbk)
    #输出: '\xc4\xe3\xba\xc3'
    
    s_utf8 = s.encode('utf-8')
    print type(s_utf8)
    #输出: <type 'str'
    print repr(s_utf8)
    #输出: '\xe4\xbd\xa0\xe5\xa5\xbd'
    

    在使用python2进行开发时, 我们强烈建议程序的内部编码全部使用Unicode类型, 当外部需要转换为其他编码时简直太方便了, 想转直接去转就好了

    2.3 python3中的字符串编码方式

    在开始的时间也介绍过了, python3默认的编码已经是Unicode类型了, 所以在python3下开发, 使用字符串时不会像python2那样一不小心就出现了乱码、就出现了解码/编码异常的问题

    python3中字符串也有两种类型: str和 bytes, 而在python3中的str类型与python2中的str类型并不一样, python3中的str类型就是Unicode类型, bytes类型才与python2中的str类型一样

    python2_3中的字符串类型

    也就是说, 在python3中bytes类型中包含了像ASCII编码, 还有GBK编码、UTF-8编码等编码方式, 所以在python3中不用类型的编码方式间相互转换就变成了这样

    python3字符串类型相互转换
    # -*- coding: utf-8 -*-
    
    #python3中默认编码为str(unicode)
    s = '你好'
    print(type(s))
    #输出: <class 'str'
    print(repr(s))
    #输出: '你好'
    
    #通过强制指明说要定义一个unicode类型的字符串可以发现, 与没有指明输出结果是一致的
    #这也就说明了python3中默认编码就是unicode编码
    s1 = u'大家好'
    print(type(s1))
    #输出: <class 'str'
    print(repr(s1))
    #输出: '大家好'
    
    
    #将其转换为utf-8编码, 由于自身已经是unicode了, 所以直接编码转就好
    s_utf8 = s.encode('utf-8')
    print(type(s_utf8))
    #输出: <class 'bytes'
    print(repr(s_utf8))
    #输出: b'\xe4\xbd\xa0\xe5\xa5\xbd'
    
    #现在我们尝试直接将utf-8编码的转换为gbk编码, 看看会怎么样
    #将会直接报错: builtins.AttributeError: 'bytes' object has no attribute 'encode'
    #s_gbk = s_utf8.encode('gkb')
    
    #所以如果要将bytes中的一种编码类型转换为另一种bytes中的编码类型, 还是需要借助unicode中转一下
    #1. 先将utf-8转换为str(unicode)
    s_unicode = s_utf8.decode('utf-8')
    print(type(s_unicode))
    #输出: <class 'str'
    print(repr(s_unicode))
    #输出: '你好'
    
    #2. 再将str(unicode)转换为gbk
    s_gbk = s_unicode.encode('gbk')
    print(type(s_gbk))
    #输出: <class 'bytes'
    print(repr(s_gbk))
    #输出: b'\xc4\xe3\xba\xc3'
    

    3. 字符串的基本操作

    基本操作指的就是字符串对象中都内置了一些什么方法, 我们目前需要了解的就是通过这些方法可以实现什么效果就可以了, 方法比较多, 我们重点说一些常用的方法. 在数据类型1时已经介绍过了, 可以通过python内置方法dir来查看某个对象中都内置了什么方法, 并且可以使用help方法来查看某个方法的功能描述,先来看一下

    # -*- coding: utf-8 -*-
    
    s = 'Hello World'
    print dir(s)
    
    '''
    输出:
    ['__add__',
    '__class__',
    '__contains__',
    '__delattr__',
    '__doc__',
    '__eq__',
    '__format__',
    '__ge__',
    '__getattribute__',
    '__getitem__',
    '__getnewargs__',
    '__getslice__',
    '__gt__',
    '__hash__',
    '__init__',
    '__le__',
    '__len__',
    '__lt__',
    '__mod__',
    '__mul__',
    '__ne__',
    '__new__',
    '__reduce__',
    '__reduce_ex__',
    '__repr__',
    '__rmod__',
    '__rmul__',
    '__setattr__',
    '__sizeof__',
    '__str__',
    '__subclasshook__',
    '_formatter_field_name_split',
    '_formatter_parser',
    'capitalize',
    'center',
    'count',
    'decode',
    'encode',
    'endswith',
    'expandtabs',
    'find',
    'format',
    'index',
    'isalnum',
    'isalpha',
    'isdigit',
    'islower',
    'isspace',
    'istitle',
    'isupper',
    'join',
    'ljust',
    'lower',
    'lstrip',
    'partition',
    'replace',
    'rfind',
    'rindex',
    'rjust',
    'rpartition',
    'rsplit',
    'rstrip',
    'split',
    'splitlines',
    'startswith',
    'strip',
    'swapcase',
    'title',
    'translate',
    'upper',
    'zfill']
    '''
    
    #查看lower方法的作用
    print help(s.lower)
    '''
    输出:
    Help on built-in function lower:
    
    lower(...)
        S.lower() - string
        
        Return a copy of the string S converted to lowercase.
    
    None
    '''
    

    可以发现确实包含了很多方法, 以__开头和__结尾的方法我们先不看, 等学习到类的时间再说这些, 我们只看剩下的当中一些常用的方法:

    方法(函数) 功能
    capitalize 字符串内容的第一个字符变大写其余字符全部变小写
    center 字符串内容按照指定的宽度居中并可以设置空白处填充的内容
    count 统计字符串内容有多少个子串
    decode 将字符串内容按照指定的编码格式转换为Unicode编码 (encoding -> Unicode)
    encode 将字符串内容转换为指定的编码格式 (Unicode -> encoding)
    startswith 判断当前字符串是否以指定的子串开头
    endswith 判断当前字符串是否以指定的子串结尾
    find 查找指定子串在字符串内容中的第一次起始位置
    lower 字符串内容全部转换为小写
    upper 字符串内容全部转换为大写
    split 以指定的内容分割字符串
    replace 将指定的字符串内容替换为新的内容

    3.1 capitalize

    定义(省略了self): str/unicode capitalize()

    功能: 字符串内容的第一个字符变大写其余字符全部变小写

    s = 'heLlo woRld'
    s1 = s.capitalize()
    print s
    #输出: heLlo woRld
    print id(s)
    #输出: 42315040
    print s1
    #输出: Hello world
    print id(s1)
    #输出: 42314592
    

    通过输出可以发现, capitalize方法并不会修改原先字符串的内容, 而是返回新的修改后的字符串


    3.2 center

    定义(省略了self): str/unicode center(width, fillchar=None)

    功能: 字符串内容按照指定的宽度居中并可以设置空白处填充的内容

    参数:

    • (int) width: 设置内容的宽度是多少
    • (char) fillchar: 设置空白处填充的内容是什么, 该参数只能是单个字符(长度为1的字符串), 不能是字符串或者其他
    s = 'heLlo woRld'
    #第一个参数width设置内容的宽度是多少
    s1 = s.center(20)
    print s
    #输出: heLlo woRld
    print id(s)
    #输出: 39628064
    print s1
    #输出:     heLlo woRld                                 
    print id(s1)
    #输出: 44909152
    print repr(s1)
    #输出: '    heLlo woRld     '
    
    #通过第二个参数设置空白处填充的内容
    #第二个参数只能是单个字符(长度为1的字符串), 不能是字符串或者其他
    s2 = s.center(20, '*')
    print s2
    #输出: ****heLlo woRld*****
    print id(s2)
    #输出: 47202960
    print repr(s2)
    #输出: '****heLlo woRld*****'
    

    3.3 count

    定义(省略了self): int count(sub, start=None, end=None)

    功能: 统计字符串内容有多少个子串

    参数:

    • (str/unicode) sub: 统计的子串内容
    • (int) start: 指定统计的范围, start为起始下标位置, 默认None, 即全串统计
    • (int) end: 指定统计的范围, end为结束下标位置, 默认None, 即全串统计
    # -*- coding: utf-8 -*-
    
    s = 'heLlo woRld world'
    #指定了统计范围, 此时相当于从字符串为heLlo woRld 中查找子串
    #所以个数为1
    print s.count('wo', 0, 12)
    #输出: 1
    
    #不指定统计范围, 此时从全串中查找子串, 所以个数为2
    print s.count('wo')
    #输出: 2
    
    #查找不存在的子串
    print s.count('abc')
    #输出: 0
    

    3.4 decode

    定义(省略了self): unicode decode(encoding=None, errors=None)

    功能: 将字符串内容按照指定的编码格式转换为Unicode编码 (encoding - Unicode)

    参数:

    • (str) encoding: 指定原字符串的编码方式, 默认为None, 即使用python默认编码方式, python2中就是ascii, python3中就是unicode
    • (str) errors: 指定解码出错时的处理方式, 默认为None, 即'strict', 严格的, 在这种方式下, 解码出错将直接抛出异常, 还有另外两种处理方式: 'ignore' 和 'replace', 从字面也可以理解意思, 一个是忽略错误, 此时将会返回空字符串, 另一个是相当于默认值, 当失败时就以默认值去替代字符串的内容

    这个方法在上面介绍python编码方式时已经介绍过了, 我们具体看一下解码错误时的一些操作

    #当前字符串是gbk编码方式
    s = '你好'
    
    #首先看一下, 什么都不指定的情况下
    #UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)
    #可以看到, 当不指定编码方式时, 将使用解释器的默认编码方式, python2中即ascii
    #print s.decode()
    
    #然后指定一个错误的编码方式
    #UnicodeDecodeError: 'utf8' codec can't decode byte 0xc4 in position 0: invalid continuation byte
    #print s.decode('utf-8')
    
    #下面试一下第二个参数, 将其设置为ignore看一下效果
    s1 = s.decode(errors='ignore')
    print s1
    #输出: 空
    print type(s1)
    #输出: <type 'unicode'
    print repr(s1)
    #输出: u''
    
    #再试一下将第二个参数设置为replace的效果
    s2 = s.decode('ascii', 'replace')
    print type(s2)
    #输出: <type 'unicode'
    print repr(s2)
    #输出: u'\ufffd\ufffd\ufffd\ufffd', 即python2中解码出错时默认使用它来替换
    

    3.5 encode

    定义(省略了self): (encoding)str encode(encoding=None, errors=None)

    功能: 将字符串内容转换为指定的编码格式 (Unicode - encoding)

    参数:

    • (str) encoding: 指定字符串的编码方式, 默认为None, 即使用python默认编码方式, python2中就是ascii, python3中就是unicode
    • (str) errors: 指定解码出错时的处理方式, 默认为None, 即'strict', 严格的, 在这种方式下, 解码出错将直接抛出异常, 还有另外两种处理方式: 'ignore' 和 'replace', 从字面也可以理解意思, 一个是忽略错误, 此时将会返回空字符串, 另一个是相当于默认值, 当失败时就以默认值去替代字符串的内容

    这个方法在上面介绍python编码方式时也已经介绍过了, 我们具体看一下解码错误时的一些操作

    #直接定义一个unicode编码的字符串
    s = u'你好'
    
    #不支持编码方式, 使用默认, 即python2中的ascii
    #UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
    #直接报错, 因为ascii无法表示中文, 最终会编码失败
    #s1 = s.encode()
    
    s2 = s.encode('ascii', errors='replace')
    print type(s2)
    #输出: <type 'str'
    print repr(s2)
    #输出: '????', 即python2中编码出错时默认使用它来替换
    

    3.6 startswith

    定义(省略了self): bool startswith(prefix, start=None, end=None)

    功能: 判断当前字符串是否以指定的子串开头

    参数:

    • (str) prefix: 指定的子串内容
    • (int) start: 指定字符串的范围, start为起始, 默认None
    • (int) end: 指定字符串的范围, end为结束, 默认None
    s = 'Hello World'
    
    #判断s是否已He开头
    print s.startswith('He')
    #输出: True
    
    #判断s是否已he开头
    print s.startswith('he')
    #输出: False, 可以发现是区分大小写的
    
    #判断在指定范围是否已W开头
    #先输出指定范围内的字符串内容, 看看长什么样
    print s[6:9]
    #输出: Wor
    print s.startswith('W', 6, 9)
    #输出: True, 这里也就相当于判断字符串Wor是否以W开头了
    

    3.7 endswith

    定义(省略了self): bool endswith(suffix, start=None, end=None)

    功能: 判断当前字符串是否以指定的子串结尾

    参数:

    • (str) prefix: 指定的子串内容
    • (int) start: 指定字符串的范围, start为起始, 默认None
    • (int) end: 指定字符串的范围, end为结束, 默认None

    用法与上面的startswith完全一样, 只不过这个是判断结尾

    s = 'Hello World'
    
    #判断s是否已d结尾
    print s.endswith('d')
    #输出: True
    
    #判断s是否已D开头
    print s.endswith('D')
    #输出: False, 可以发现是区分大小写的
    
    #判断在指定范围是否已r结尾
    #先输出指定范围内的字符串内容, 看看长什么样
    print s[6:9]
    #输出: Wor
    print s.endswith('r', 6, 9)
    #输出: True, 这里也就相当于判断字符串Wor是否以r结尾了
    

    3.8 切片 (重点)

    切片用于提取序列中指定范围的内容, 在python中以下数据类型都属于序列(即都支持切片操作):

    • 字符串
    • 列表
    • 元组

    切片是按照不同类中的最小单位来进行的, 切片后返回的结果与切片时的类型一致(即对字符串切片操作后返回的结果也是字符串类型). 比如说现在的字符串类型, 它的最小单位就是字符, 那么像列表、元组类型中的最小单位则是元素(等介绍到的时间就会明白了)

    像上面在介绍字符串的startswith、endswith方法时就使用了切片操作, 下面来看一下切片的用法

    # -*- coding: utf-8 -*-
    
    s = 'Hello World'
    
    '''
    切片的语法结构:
    
    序列对象[起始位置:结束位置:步长(递增单位)]
    Sequence Object[start:end:step]
    
    起始位置: 用来指定切片的起始位置
    结束位置: 用来指定切片的结束位置
    通过起始位置和结束位置就标识了当前需要切片的范围
    步长(递增单位): 用来指定切片时的递增单位
    
    备注:
    基本在所有的编程语言中, 索引的开头第一个元素都是以0来表示, 而非1
    使用上述s字符串为例, 最开头的字符H的起始位置是0, 而非1
    
    H e l l o   W o r l d
    0 1 2 3 4 5 6 7 8 9 10
    '''
    
    #输出s字符串的最开始的H字符
    print s[0]
    #输出: H
    
    #提取s字符串中ello World内容, 即不要最开始的H字符
    s1 = s[1:11]
    print s1
    #输出: ello World
    print type(s1)
    #输出: str
    
    #通常步长都是省略的, 省略的情况下步长为1, 下面为指定步长的情况
    #步长表示的就是说从当前位置 + 多少个单位到下一个位置
    #下面的的代码指定了步长为2, 即每次加2个单位到下一个位置
    s2 = s[1:11:2]
    print s2
    #输出: el ol
    
    #通常为了省事, 如果从开头开始切片或者切片的结束位置是结尾, 那么标识开头、结尾位置可以省略
    #从头开始切
    s3 = s[:3]
    print s3
    #输出: Hel
    
    #切到结尾
    s4 = s[6:]
    print s4
    #输出: World
    
    #从头切到尾
    s5 = s[:]
    print s5
    #输出: Hello World
    
    #从头切到尾, 步长为2
    s6 = s[::2]
    print s6
    #输出: HloWrd
    
    #在切片操作中如果指定的范围无效, 执行时并不会报错
    #你可以发现s并没有100这么长, 但是执行不但没有报错, 还返回结果了
    #当范围无效时, 切片只会到最后一个有效的范围, 把有效范围的结果返回
    s7 = s[:100]
    print s7
    #输出: Hello World
    
    #再看一个更奇葩的, 没有有效范围时返回什么
    #可以看到, 返回''(空)字符串
    s8 = s[100:1000]
    print s8
    #输出: ''
    print repr(s8)
    #输出: ''
    
    #切片的起始、结束位置、步长不但可以正数, 也可以是负数
    #正数表示从头向后的位置, 负数则表示从后向前的位置
    s9 = s[-3:-1]
    print s9
    #输出: rl
    
    s10 = s[-100:-1]
    print s10
    #输出: Hello Worl
    

    3.9 find

    定义(省略了self): int find(sub, start=None, end=None)

    功能: 查找指定子串在字符串内容中的第一次起始位置

    参数:

    • (str) sub: 指定的子串内容
    • (int) start: 指定字符串的范围, start为起始, 默认None
    • (int) end: 指定字符串的范围, end为结束, 默认None

    如果字符串内容中存在需要查找的子串, 则返回该子串在字符串内容中的第一次起始位置, 如果不存在子串则返回-1

    # -*- coding: utf-8 -*-
    
    s = 'Hello World'
    
    '''
    H e l l o   W o r l d
    0 1 2 3 4 5 6 7 8 9 10
    '''
    
    #查找llo子串的起始位置
    pos = s.find('llo')
    print pos
    #输出: 2
    
    #查找123子串的起始位置
    pos = s.find('123')
    print pos
    #输出: -1
    
    #查找l子串的起始位置, 指定位置和不指定位置
    pos1 = s.find('l')
    print pos1
    #输出: 2
    
    #查找子串W之后中的l子串起始位置
    pos2 = s.find('l', 6)
    print pos2
    #输出: 9
    

    3.10 lower

    定义(省略了self): str/unicode lower()

    功能: 字符串内容全部转换为小写

    参数: 无

    该方法并不会直接在原始字符串上修改, 而是返回一个新的修改后的字符串

    s = 'Hello World'
    s1 = s.lower()
    print s
    #输出: Hello World
    print s1
    #输出: hello world
    

    3.11 upper

    定义(省略了self): str/unicode upper()

    功能: 字符串内容全部转换为大写

    参数: 无

    该方法并不会直接在原始字符串上修改, 而是返回一个新的修改后的字符串

    s = 'Hello World'
    s1 = s.upper()
    print s
    #输出: Hello World
    print s1
    #输出: HELLO WORLD
    

    3.12 split

    定义(省略了self): list split(sep=None, maxsplit=None)

    功能: 以指定的内容分割字符串

    参数:

    • (str) sep: 指定的分割符内容, 默认为None, 以空格作为分隔符
    • (int) maxsplit: 最大分割次数, 默认为None, 遇到分割符就分割

    该方法的返回结果为list(列表)类型, 下一篇马上介绍该类型

    # -*- coding: utf-8 -*-
    
    s = 'Hello World'
    
    #首先使用默认分隔符分割, 默认为空格
    l1 = s.split()
    print l1
    #输出: ['Hello', 'World']
    print type(l1)
    #输出: <type 'list'
    
    #使用自定义分隔符分割
    '''
    He l l o Wor l d
    '''
    l2 = s.split('l')
    print l2
    #输出: ['He', '', 'o Wor', 'd']
    #上面输出了一个空字符串, 应该是应为已分割过的分隔符会被替换成空字符串, 即在Hel[l]时造成的
    print type(l2)
    #输出: <type 'list'
    
    #指定最大分割次数
    l3 = s.split('l', 1)
    print l3
    #输出: ['He', 'lo World']
    #指定了分割次数后, 后面的l就没有再进行分割了
    

    3.13 replace

    定义(省略了self): str/unicode replace(old, new, count=None)

    功能: 将指定的字符串内容替换为新的内容

    参数:

    • (str) old: 需要被替换的字符串内容
    • (str) new: 以该内容替换需要被替换的字符串内容
    • (int) count: 最多替换个数, 默认为None, 即有多少个就替换多少个

    该方法并不会直接在原始字符串上替换, 而是返回一个新的替换后的字符串

    # -*- coding: utf-8 -*-
    
    s = 'Hello World'
    
    s1 = s.replace('el', '111111')
    print s
    #输出: Hello World
    print s1
    #输出: H111111lo World
    
    #指定最多替换个数
    s2 = s.replace('l', '2', 2)
    print s
    #输出: Hello World
    print s2
    #输出: He22o World
    #可以看到, 指定了最多替换个数后, 最后的一个l没有被替换掉
    

    3.14 字符串拼接 (重点)

    我们平常在使用字符串时难免会有拼接多个字符串的需求, 此时就需要使用字符串的拼接功能了, 在使用字符串拼接时需要注意的是: 相同编码类型的字符串拼接时没有问题的, 但当出现不同编码类型的字符串进行拼接时, 首先会隐式的尝试编码转化(即尝试转换为统一的编码类型), 如果可以转换则拼接成功, 如果不可以转换, 则将会出现decode/encode的错误, 这些错误在使用字符串时经常会出现

    在python中, 字符串的拼接有以下几种常用的方法:

    • 使用 + 号运算符
    • 使用字符串对象format方法
    • 使用字符串对象join方法
    • 使用%号格式化

    针对不同的字符串操作需求选择不同的字符串拼接方法, 在平常开发中一般用后三个方法比较多, 因为比较灵活, %号格式化时不仅可以接受字符串类型, 还可以接受其他的类型

    # -*- coding: utf-8 -*-
    
    s1 = 'Hello'
    s2 = 'World'
    
    #+号运算符的方式拼接字符串是最常用的
    #+号运算符也是效率最低的, 至于为什么效率低感兴趣的可以先自行百度一下, 以后会以python源码的视角去看为什么效率低
    s = s1 + s2
    print s
    #输出: HelloWorld
    print type(s)
    #输出: <type 'str'
    
    #使用字符串format方法
    s = '{0}{1}'.format(s1, s2)
    print s
    #输出: HelloWorld
    
    #使用字符串join方法
    s = ''.join([s1, s2])
    print s
    #输出: HelloWorld
    
    #使用%号格式化
    s = '%s%s' % (s1, s2)
    print s
    #输出: HelloWorld
    
    #使用%号格式化时有其他类型
    s = '%s%s%d' % (s1, s2, 100)
    print s
    #输出: HelloWorld100
    
    #不同编码类型之间拼接会出现错误
    s3 = u'你好'
    s4 = '呵呵'
    #UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)
    #出现该错误的原因是, 当s3 + s4时, 解释器发现两者编码不一致, 所以尝试将"低"类型转换为"高"类型(即将s4转换为unicode编码)
    #我们知道, str类型转换为unicode类型, 使用的是decode方法, 该方法需要指明原先字符串编码方式, 如果没有指明则使用默认python编码(即ascii编码)
    #所以最后肯定会解码失败, 就提示了UnicodeDecodeError, 也就是在转换Unicode编码类型时发生了错误
    #s = s3 + s4
    
    s5 = 'Hello'
    #这里没有出错是因为s5本身就是ascii编码, 所以在隐式转换为unicode编码时是不会出错的
    #通过最后输出的type类型页可以看到, 解释器在内部确实做了隐式的类型转换
    s = s3 + s5
    print s
    #你好Hello
    print type(s)
    #输出: <type 'unicode'
    

    通过上面的demo可以发现在不同编码类型之间拼接时一不小心就会出现错误, 所以我们一般建议在python2开发中, 程序内部统一使用unicode编码方式, 编码类型统一了, 在拼接时自然也就不会出现demo中的错误了

    相关文章

      网友评论

          本文标题:python 入门 第4篇: 数据类型2 - 字符串类型

          本文链接:https://www.haomeiwen.com/subject/jfsshftx.html