05 - 字符串


一.字符串的表示方式

  • 双引号或者单引号中的数据,就是字符串
  • 如果使用一对引号来定义字符串,当出现符号冲突时可以使用转义字符
  • 使用三个单引号、双引号定义的字符串可以包裹任意文本

二.字符串的赋值和地址问题

  • s1、s2、s3的地址相同 / s4的地址不同
s1 = 'hello'
s2 = s1           #s1将地址赋给s2,这样s1和s2指向的是常量池中同一个字符串
s3 = "hello"      #hello这个字符串在常量池中已经存在,所以将地址给s3,那么s3和s1、s2地址相同
s4 = 'hello1'     #常量池中没有hello1这个字符串,会在常量池中新开辟一个地址,赋给s4

id(变量):id()函数用于将变量的内存地址得到转化为我们能看懂的地址

变量a is 变量b:is用于比较地址是否相同

  • 当没有任何指针指向字符串,字符串就会被回收

三.字符串的索引机制

  • 正向取索引(str = 'abcde')

    0 ~ len(str)-1

    从左到右索引依次为:0 1 2 3 4

  • 反向取索引

    -len(str) ~ -1

    从右往左索引依次为:-1 -2 -3 -4 -5

    有时候字符串长度很长,如果正向去取会很麻烦,但是如果倒着取,那么倒数第一个字符下标就为-1,向左依次为-2、-3、-4...

四.字符串相关操作

1.获取字符串长度

  • len(字符串)

2.截取指定字符串

  • 依据字符串索引机制,按索引取

    str = 'abcdef'
    print(str[1])   #b
    print(str[-2])  #e
    

3.截取多个字符串(切片)

  • 切片用于字符串和列表

  • 格式:字符串变量[start:end:step]

    1. 步长省略
    • [start:end] #左闭右开

      • 正向索引

        str = 'abcde'
        print(str[1:3])      #bc
        
      • 反向索引

        str = 'abcde'
        print(str[-4:-2])    #bc  也是左闭右开
        
      • 正反索引可以混用

        str = 'abcde'
        print(str[1:-2])    #bc
        
    • [:end] #默认从0开始

      str = 'abcde'
      print(str[:3])    #abc
      print(str[:-1])   #abcd
      
    • [start:] #从start开始取到最后

      str = 'abcde'
      print(str[2:])    #cde
      print(str[-2:])   #de
      
    • [:] #从头取到尾

      str = 'abcde'
      print(str[:])     #abcde
      

      注意:此时用切片的方式取出全部字符串和原字符串地址一样


    • list1[1:1] = [2,3] #比较特殊,根据底层原码大致理解为先看等号后面的列表长度n,然后再1:切片的位置之后含切片位置的所有元素后移n位,然后将等号后面的列表中的元素依次插入

      list1 = [1,4]
      list1[1:1] = [2,3,{1,2},(1,2),{'a':1},'str']
      print(list1)  #[1, 2, 3, {1, 2}, (1, 2), {'a': 1}, 'str', 4]
      

      注意只有列表的切片才能这样使用!!

    1. 加上步长
    • [start : end : step]

      str = 'abcdef'
      print(str[1:-1:2])   #bdf
      
    • [ : end : step]

      str = 'abcdef'
      print(str[:-1:3])   #ad    
      
    • [start : : step]

      str = 'abcdef'
      print(str[2::2])    #ce  
      
    • [ : : step]

      str = 'abcdef'
      print(str[::-1])    #fedcba
      print(str[::-2])    #fdb
      
    • [ : : : ]

      str = 'abcdef'
      print(str[::])    #abcdef
      

    注意:步长如果为正表示从左到右取,如果步长为负数表示从右往左反着取

    而且一定注意:当步长为负数时,说明从右往左反着取,那么start的索引值一定要在end索引值的后面!!

  • 易错举例:

    str = 'abcdef'
    print(str[1:-1:-2])    #这样会取不到任何值!!!!因为step为-2表示倒着取,起始索引为1,倒着取下一个为                         0,这样就永远到不了-1索引,所以取不到任何值
    print(str[-1:1:-2])    #这样就可以取到值--fd  (还是左闭右开)
    print(str[5::-1])      #从索引为5开始往前取--fedcba
    

4.查找(获取指定字符下标)

  • find:从左向右查找,只要遇到一个符合要求的则返回位置值。如果没有找到任何符合要求的则返回-1

    path = 'https://www.baidu.com/img/dong_e39494cd9293c9d9cc9d0gk303945.gif'
    i = path.find('_')                
    print(path[i+1:])                 #取_后面的字符串
    
    mystr = '今天天气好晴朗,处处好风光呀好风光'
    print(mystr.find('好风光'))        #10   '好风光'第一次出现时,'好'所在的位置
    print(mystr.find('风光',1,10))     #-1 从下标1开始到12查找"风光",未找到,返回 -1
    
  • rfind:类似于 find()函数,不过是从右边开始查找。如果没有找到任何符合要求的则返回-1

    mystr = '今天天气好晴朗,处处好风光呀好风光'
    print(mystr.rfind('好'))           #14
    
  • index:跟find()方法一样,只不过,find方法未找到时,返回-1,而str未找到时,会报一个异常

  • rindex:类似于 index(),不过是从右边开始。

5.判断

  • startswith:判断字符串是否以指定内容开始。

    mystr = '今天天气好晴朗,处处好风光呀好风光'
    print(mystr.startswith('今'))  # True
    
  • endswith:判断字符串是否以指定内容结束。

    mystr = '今天天气好晴朗,处处好风光呀好风光'
    print(mystr.endswith('好风光')) #True
    
  • isalpha:判断字符串是否是纯字母

    mystr = 'hello world'
    print(mystr.isalpha()) # False 因为中间有空格
    
  • isdigit:判断一个字符串是否是纯数字,只要出现非0~9的数字,结果就是False.

  • isalnum:判断是否由数字和字母组成。只要出现了非数字和字母,就返回False.

  • isspace:如果 mystr 中只包含空格,则返回 True,否则返回 False.

  • isupper:判断是否全部是大写字母

  • islower:判断是否全部是小写字母

6.统计出现次数

  • count:返回 str在start和end之间 在 mystr里面出现的次数。

    mystr = '今天天气好晴朗,处处好风光呀好风光'
    print(mystr.count('好'))      #3    '好'字出现三次
    

7.替换

  • replace:替换字符串中指定的内容。如果没有指定次数则全部替换;如果指定次数count,则替换不会超过count次。
mystr = '今天天气好晴朗,处处好风光呀好风光'
newstr = mystr.replace('好', '坏')
print(mystr)  # 今天天气好晴朗,处处好风光呀好风光  原字符串未改变!
print(newstr)  # 今天天气坏晴朗,处处坏风光呀坏风光 得到的新字符串里,'好'被修改成了'坏'

newstr = mystr.replace('好','坏',2)  # 指定了替换的次数
print(newstr) # 今天天气坏晴朗,处处坏风光呀好风光 只有两处的'好'被替换成了'坏'

注意:替换完的新字符串不会覆盖原字符串

  • 疑问:如果要替换多个怎么办-------1.正则表达式 2.列表加循环 (后面会详解)

8.切割(分割字符串)

  • split:以指定字符串为分隔符切片,如果 maxsplit有指定值,则仅分隔 maxsplit+1 个子字符串。返回的结果是一个列表。
mystr = '今天天气好晴朗,处处好风光呀好风光'
result = mystr.split() # 没有指定分隔符,默认使用空格,换行等空白字符进行分隔
print(result) #['今天天气好晴朗,处处好风光呀好风光'] 没有空白字符,所以,字符串未被分隔

result = mystr.split('好')  # 以 '好' 为分隔符
print(result) # ['今天天气', '晴朗,处处','风光呀,'风光']

result = mystr.split("好",2) # 以 '好' 为分隔符,最多切割成3份
print(result) # ['今天天气', '晴朗,处处', '风光呀好风光']
  • rsplit:用法和split基本一致,只不过是从右往左分隔。
  • splitlines(了解):按照行分隔,返回一个包含各行作为元素的列表。
mystr = 'hello \nworld'
mystr = '''第一行
第二行
第三行
'''
print(mystr.splitlines())
  • partition(了解):把mystr以指定str分割成三部分,str前,str和str后,三部分组成一个元组
mystr = '今天天气好晴朗,处处好风光呀好风光'
print(mystr.partition('好'))  # ('今天天气', '好', '晴朗,处处好风光呀好风光')
  • rpartition(了解):类似于 partition()函数,不过是从右边开始.

9.大小写转化

  • title:每个单词的首字母大写。
mystr = 'hello world'
print(mystr.title()) # Hello World
  • capitalize:第一个单词的首字母大写。
  • upper:所有都变成大写。
  • lower:所有都变成小写。

10.空格处理

  • strip:删除两端的空白字符

    str = '    he   llo      '
    print(str.strip())  #he   llo
    
  • lstrip:删除 mystr 左边的空白字符

  • rstrip:删除 mystr 右边的空白字符

  • ljust:返回指定长度的字符串,并在右侧使用空白字符补全(左对齐)。

  • rjust:返回指定长度的字符串,并在左侧使用空白字符补全(右对齐)。

  • center:返回指定长度的字符串,并在两端使用空白字符补全(居中对齐)

    str = 'hello'
    print(str.center(10))  #  hello   两端加空格,让内容居中
    

11.字符串拼接

  • join:把参数进行遍历,取出参数里的每一项,然后再在后面加上mystr

    一般用于列表--->返回一个字符串

    mystr = 'a'
    print(mystr.join('hxmdq'))  #haxamadaq  把hxmd一个个取出,并在后面添加字符a. 最后的q保留,没有加a
    print(mystr.join(['hi','hello','good']))  #hiahelloagood
    
  • +号:正常拼接字符串

12.字符串format格式化

  • 概念

    str.format() 方法通过字符串中的大括号{} 来识别替换字段 replacement field,从而完成字符串的格式化。

  • 字段名的种类

    • 1.省略字段名:{}

      注意:大括号个数可以少于位置参数的个数,反之不然

      name = '小明'
      age = 18
      print('我叫{},今年{}岁。'.format(name, age))
      
      # 大括号个数可以少于位置参数的个数
      print('我爱吃{}和{}。'.format('香蕉', '苹果', '大鸭梨'))
      
      # 大括号个数多于位置参数的个数则会报错
      # print('我还吃{}和{}。'.format('西红柿'))
      """
      IndexError: tuple index out of range
      """
      
    • 2.使用非负十进制整数{0}

      • 数字必须是大于等于 0 的整数。

      • 带数字的替换字段可以重复使用

        # 数字形式的简单字段名可以重复使用。
        name = '阿香'
        age = 17
        print('我爱{0}。\n她今年{1}。\n我也爱{0}。'.format(name, age))
        """
        我爱阿香。
        她今年17。
        我也爱阿香。
        """
        
      • 数字形式的简单字段名相当于把 format 中的所有位置参数整体当作一个元组,通过字段名中的数字进行取值。即 {0} 等价于 tuple[0],所以大括号内的数字不能越界。

        # 体会把所有位置参数整体当成元组来取值
        print('阿香爱吃{1}、{3}和{0}。'.format(
            '榴莲', '臭豆腐', '皮蛋', '鲱鱼罐头', '螺狮粉'))
        """
        阿香爱吃臭豆腐、鲱鱼罐头和榴莲。
        """
        
    • 3.变量名{name}

      • 使用变量名形式的简单字段名传递关键字参数

      • 使用变量名关键字参数的位置可以随意调换。

      • 但是注意:变量名做参数时一定要在format中赋值

      # 关键字参数的顺序可以随意调换
      print('我大哥是{name},今年{age}岁。'.format(age=20, name='阿飞'))
      """
      我大哥是阿飞,今年20岁。
      """
      
    • 4.简单字段名的混用

      • 混合使用数字形式和变量名形式的字段名,可以同时传递位置参数和关键字参数。

      • 关键字参数必须位于位置参数之后。

        # 关键字参数必须位于位置参数之后
        print('这是一个关于{0}、{1}和{girl}的故事。'.format(
            '小明', '阿飞', girl='阿香'))
        """
        这是一个关于小明、阿飞和阿香的故事。
        """
        
      • 混合使用时可以省略数字。

        # 数字也可以省略
        print('这是一个关于{}、{}和{girl}的故事。'.format(
            '小明', '阿飞', girl='阿香'))
        
      • 省略字段名 {} 不能和数字形式的字段名 {非负整数} 同时使用。

        # 但是省略字段名不能和数字形式的字段名同时出现
        # print('这是一个关于{}、{1}和{girl}的故事。'.format(
        #     '小明', '阿飞', girl='阿香'))
        """
        ValueError: cannot switch from automatic field numbering to manual field specification
        """
        

例题1:利用切片和字符串方法

  • 模拟上传文件,键盘输入上传文件的名称(不带后缀名),判断文件名是否大于6位以上,拓展名是否是:jpg、gif、png格式,如果不是则提示上传失败,如果名字不满足条件,而拓展名满足条件则随机生成一个6位数字组成的文件名,打印成功上传xxx.png等
import random
document = input('请输入上传文件名称:')
index = document.rfind('.')
if document.endswith('.jpg') or document.endswith('.gif') or document.endswith('.png'):
    if len(document[index - 1::-1]) >= 6:  #或者写[:index]
        print('打印成功上传%s' % document)
    else:
        newName = random.randint(100000,999999)   #randint()是左闭右闭的
        print('打印成功上传%d%s' % (newName,document[index:]))
else:
    print('格式不满足上传失败')   1748

改进:

  • 随机生成一个由字母和数字组成的6位文件名 (很牛的方法--验证码就是这么来的)
filename = ''   #表示filename是空的字符串类型的变量
s = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'  #所有可能的情况
for i in range(6):
    index = random.randint(0,len(s) - 1)   #随机取一个整数,去表示s中的索引
    filename += s[index]     #将从s字符串中取出的元素拼接成6位字符串
print(filename)

例题2:字符串判断

'''
admin123 19182134110 123456
用户名或者手机号登录+密码

用户名:全部小写,首字母不能是数字,长度必须6位以上
手机号码:纯数字、长度11
密码必须是6位数字

以上符合条件则进入下层验证:
判断用户名+密码 是否正确,成功或失败
'''
flag = True
error = 0
while flag:
    if error < 3:
        name = input('请输入用户名或手机号:')
        if (name.islower() and not name[0].isdigit() and len(name) > 6) or (name.isdigit() and len(name) == 11):
            while error < 3:
                password = input('请继续输入密码:')
                if password.isdigit() and len(password) == 6:
                    if (name == '19182134110' or name == 'admin123') and  password == '123456':
                        print('登录成功!')
                        flag = False
                        break
                    else:
                        print('账号或密码错误!(还有%d次尝试机会)' % (2 - error))
                        error += 1
                        break
                else:
                    print('密码必须是6位!(还有%d次尝试机会)' % (2 - error))
                    error += 1
                    break
        else:
            print('用户名或手机输入格式错误')
    else:
        print('账号锁定!')
        flag = False


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM