Python基础之字符串(一)

前言

  随着计算机发展日益加快,就算对于非计算机专业人士也通过键盘、鼠标等IO组件与计算机进行沟通。我们手指的每一次敲击,都传送给计算机输入某个“字符”的信号,字符与字符串不仅是编程语言的基本组成元素,更是我们与计算机交流的桥梁
  对于Python 这门现代编程语言,字符串的操作也是重中之重,接下来让我们一起学习有关字符串的内容吧

什么是字符串

字符串的创建

  • 对于较早的C语言等,字符一般而言指acsii规定的128个字符,包括英文字母、数字、一些控制字符,而由这些字符组成的一串字符被形象地称作字符串
    char c = 'a';
    char str[10] = "abcde";
  • Python3采用了号称万国码的Unicode字符集,可以表示包括中文、阿拉伯文等多国文字在内的若干字符,当然通过Python内置的编码、解码函数可以实现utf-8ascii等其他编码方式之间的互相转换,当然这是后话了
    这里放一个编码的链接
  • Python中没有字符和字符串的明显区别,字符串可以使用'或者"定义,甚至对于多行字符串,可以使用"""或者'''来包含多行文本而不用在字符串间换行位置使用换行符\n,甚至允许使用\来拼接多行字符串为一行
    # Python中没有字符和字符串的区分
    char_one = 'a'
    char_two = "a"
    chars = 'abcde'
    print(char_one)
    print(char_two)

    # 多行字符串
    lines = """this is a long string
    that spans multiple lines"""
    lines_single = '''this is also a long
    string
    that spans mutiple lines too'''
    print(lines)
    print(lines_single)

    # 拼接多行字符
    new_lines = "this is a long string"\
    "that over"\
    "multiple lines"
    print(new_lines)
    输出内容
    a
    a
    this is a long string
    that spans multiple lines
    this is also a long string
    that spans multiple lines
    this is a long string that over multiple lines

字符串不可变性

  • Python中所有数据都是通过引用传递与使用的,这意味着我们一般只管理指向数据的引用(大概是Python不用写数据类型的原因之一),传递数据一般也只是传递数据的引用而非数据本身(除深浅拷贝外)
    # 简单数据类型
    a = 12
    b = a # b接收的是a的引用

    # 复杂数据类型
    str_a = "1234"
    str_b = str_a # 同理接收的是引用
  • 这时,小熊饼干突然想修改str_b的值便加入了一系列指令
    print("展示修改前地址:")
    print(id(str_a))
    print(id(str_b))
    print("展示修改前值:")
    print(str_a)
    print(str_b)

    str_b += "5"

    print("展示修改后地址:")
    print(id(str_a))
    print(id(str_b))
    print("展示修改后值:")
    print(str_a)
    print(str_b)
    运行结果
    展示修改前地址:
    140123456789056
    140123456789056
    展示修改前值:
    1234
    1234
    展示修改后地址:
    140123456789056
    342453543545131
    1234
    12345
    我们惊奇地发现str_b指向的地址在修改前后发生了变化,这是因为字符串是一种不可变类型 ,任何针对字符串内容的改变都是不被允许的,所以我们进行修改str_b的操作str_b += "5"时,Python直接创建了一个新的变量"12345"然后将这个变量的地址赋给str_b
    什么是可变类型呢

    对于strtuplebyte不可变类型数据,一旦创立就无法修改其内容,而对于listdict可变类型我们允许在创立后继续修改其内容,如下

    • 甲方要求小熊饼干写一个复制一份list的Python文件,于是他写下如下代码
      list_a = [1, 2, 3, 4, 5]
      list_b = list_a
      就在他写完时,甲方要求他在复制的副本中加入其他几个元素,睡眼朦胧的小熊饼干草草地写完了代码,没想到第二天代码出了问题,原始数据list遭到篡改,小熊饼干因此下岗了,呜呜呜
      print("打印修改前地址:")
      print(id(list_a))
      print(id(list_b))
      print("打印修改前值:")
      print(list_a)
      print(list_b)

      list_b.append(5)
      list_b.append(6)
      print("打印修改后地址:")
      print(id(list_a))
      print(id(list_b))
      print("打印修改后值:")
      print(list_a)
      print(list_b)
      打印修改前地址:
      140123456789056
      140123456789056
      打印修改前值:
      [1, 2, 3, 4]
      [1, 2, 3, 4]
      打印修改后地址:
      140123456789056
      140123456789056
      打印修改后值:
      [1, 2, 3, 4, 5, 6]
      [1, 2, 3, 4, 5, 6]
      $Attention:$小熊饼干通过赋值手段使list_alist_b指向同一对象,又因为list类型是可变类型,所以对于其内容的修改是被允许的,这时我们可以通过list_a或者list_b中的某一个引用修改原对象内容,也就导致指向该对象的所有引用的“值”同时变化

字符串的简单操作

索引

如果你曾经学习过C语言,一定记得字符串(字符数组)使用下标索引的场景(熟悉而美好,那么当然,Python提供了更为强大的索引功能

chars = "abcdefg"
char = chars[0] # a
char = chars[4] # d
char = chars[-1] # g
char = chars[-2] # f

不仅提供了正向索引还有反向的,以后获得尾部的某些字符就轻松多了

切片

Python中提供的一种相较于一般索引更加高级的索引方式,可以灵活地处理字符串一般格式为str[start:end:step]

  • start:切片的起始索引值,缺省为字符串开头
  • end:切片的结束索引值(不包括),缺省为字符串结束后(即包括字符串最后一个字符)
  • step:切片的步长,默认为1
    # 正向索引
    test_str = "人生苦短,我用Python"
    chars = test_str[1:3] # "生苦"
    chars = test_str[:6] # "人生苦短,我"
    chars = test_str[6:] # "用Python"

    # 整段切片
    chars = test_str[:] # "人生苦短,我用Python"
    chars = test_str[::2] # "人苦,用yhn"

    # 倒排索引(雾
    chars = test_str[::-1] # "nohtyP用我,短苦生人"
    chars = test_str[5:1:-1] # "我,短苦"
    chars = test_str[:-7:-1] # ”nohtyP“

str类

相信学习过任何一门具有面向对象特性的编程语言的同学对这个词都不会陌生,简而言之,在面向对象设计中,万物都为“对象”;具有相同属性和行为的一群对象分为一个“类”,这个类抽象出对象群体共同的特性(属性)和行为(方法)

  • 在这里,各种不同的字符串都是对象,他们共同构成了类str,因为他们有某些共同的特性,如编码方式,有可以对所有字符串对象使用的方法,如查找子串,请你跟随小熊饼干,一起学习blog中讲解的第一个类str
  • 因为某些原因,我们将构造方法和一些魔术方法放在后续内容中介绍,敬请关注

内置方法(普通)

去除字符(熟练掌握)

  • str.strip(sub_string)
    • 从字符串左右去除所给字符串中的所有字符,缺省为空去除空白字符
  • str.rstrip(sub_string)
    • 从字符串右去除所给字符串中的所有字符,缺省为空去除空白字符
  • str.lstrip(sub_string)
    • 从字符串左去除所给字符串中的所有字符,缺省为空去除空白字符
  • 都只会去除连续匹配的字符,若有不匹配,则立即停止
    s = "  hello  "
    print(s.strip())
    print(s.strip(" h"))

    s = " hello "
    print(s.lstrip())
    print(s.lstrip(" h"))

    s = " hello "
    print(s.rstrip())
    print(s.rstrip(" o"))

    s = "abc123cba"
    print(s.strip("abc"))

    空格使用下滑线表示

    hello
    ello
    hello____
    ello___
    ___hello
    ___hell
    123

查找与计数(熟练掌握)

  • str.find(sub_string)
    • 从字符串左端开始查找,返回第一个匹配子串的索引值,没有返回-1
  • str.rfind(sub_string)
    • 从字符串右端开始查找,返回第一个匹配子串的索引值,没有返回-1
  • str.index(sub_string)
    • 从字符串左端开始查找,返回第一个匹配子串的索引值,没有抛出异常
  • str.rindex(sub_string)
    • 从字符串右端开始查找,返回第一个匹配子串的索引值,没有抛出异常
  • str.count(sub_string, [start, end])
    • []在函数注解中代表可有可无的参数
    • 计算子串在这个字符串中出现的次数,可指定计数区间
  • in && not in
    • 对于字符串这种可迭代对象可以使用Python内置的操作符判断一个元素是否在这个对象中
      chars = "hello, Python! I love Python ! We all use Python"
      print(chars.find("Python"))
      print(chars.rfind("Python"))
      print(chars.index("Python"))
      print(chars.index("Python"))
      print(chars.count("Python", 0, len(chars)))

      print("Python" in chars)
      print("Chi" not in chars)

      print(chars.index("Chi"))
      print(chars.find("Chi"))
      7
      42
      7
      7
      3
      True
      True
      Traceback (most recent call last):
      File "D:\Pycharm_code\math_and_\test.py", line 8, in <module>
      print(chars.index("Chi"))
      ValueError: substring not found

实用(熟练掌握)

  • str.replace(string1, string2)
    • 将字符串中的全部string1都替换为string2
  • str.split(base, [count])
    • 将字符串按照base为基准分为不同的字符串,分割的次数可以显式地给出,优先从左到右,返回一个字符串列表
  • str.join(itereable)
    • 将可迭代对象(可以先理解为数组、元组这些有基本元素的类型,字符串也是了),将其中的元素直接使用str连接拼接为一个更长的字符串
      chars = "Python and language C"
      print(chars.replace("language C", "Python"))
      print(chars.split(" "))
      print(chars.split(" ", 2))

      print("*".join(chars))
      print("&".join(chars.split(" ")))
      Python and Python
      ['Python', 'and', 'language', 'C']
      ['Python', 'and', 'language C']
      P*y*t*h*o*n* *a*n*d* *l*a*n*g*u*a*g*e* *C
      Python&and&language&C

      字符串不可修改,所以如果需要对字符串进行操作记得用变量接收哦

      chars = chars.split(" ")
      new_chars = chars.split(" ")

大小写转换(了解即可)

  • str.upper()
    • 将字符串内所有字符转为大写
  • str.lower()
    • 将字符串内所有字符转为小写
  • str.capitalize()
    • 将字符串首字母大写
  • str.title()
    • 将字符串每个单词首字母大写
      chars = "hello, world"
      chars_upper = chars.upper()
      chars_lower = chars.lower()
      chars_cap = chars.capitalize()
      chars_title = chars.title()
      print(chars_upper)
      print(chars_lower)
      print(chars_cap)
      print(chars_title)
      HELLO, WORLD
      hello, world
      Hello, world
      Hello, World

特判(了解即可)

  • 不咋用,因为我都有正则了还要什么自行车?
  • str.isalpha()
    • 是否全是英文字母
  • str.isspace()
    • 是否全为空白符
  • str.isupper()
    • 是否全为大写字母
  • str.islower()
    • 是否全为小写字母
  • str.istitle()
    • 是否是标题格式,单词第一个大写
  • str.isdecimal()
    • 是否是十进制阿拉伯数字,不包含其他任何形式的数字
  • str.isdigit()
    • 比上面更广,可以包含上标数字、罗马数字、全角数字
  • str.isnumeric()
    • 比上面更广,甚至可以识别中文数字和分数数字
  • str.isalnum()
    • 是否全为字母和数字
    • 字母不限于英文字母,还有各国语言字母
    • 数字不识别分数
  • str.startswith()
    • 以什么指定字符串开头
  • str.endswith()
    • 以什么指定字符串结尾

tips

  • 如果你希望想C语言一样通过码点的位置定位一个字符的话,就继续看吧
    • 例如A字符在ascii表中对于着65,所以A也可以写为'\x65'
      chars = '\x65'
      byte_string = char.encode('latin1') # 将chars理解为Byte串
      char = byte_string.decode() # 进行utf-8解码

      print(chars)
      print(byte_string)
      print(char)
      A
      b'A'
      A
  • 同理,对于unicode字符集(涵盖ascii)中的字符也可以进行转义,不过不能直接使用类似于上面的格式
    • 例如字符在utf-8编码方式中的三个字节标识是'\xe4\xb8\xad',就不可以直接打印转义字符串,Python会理解为三个在ascii码表中的字符
      chars = '\xe4\xb8\xad'
      byte_string = chars.encode('latin1') # 将chars编码理解为Byte串
      char = byte_string.decode() # 默认以utf-8来解码

      print(chars)
      print(byte_string)
      print(char)
      中-
      b'\xe4\xb8\xad'

  • 最后,Python内置了提供字符码点的函数(非ascii码字符的码点utf-8编码的标识是两个概念)
  • ord()
    • 由字符得到码点
  • chr()
    • 由码点生成字符