PYTHON 学习第四章 之 使用字符串

前言

我是一个做java 编程的程序猿,程序猿中的语言不止一种,于是自学了python ,在我学习过程中记录一些笔记和心得,很荣幸你能看到我的博客,如果内容中有什么错误或意见,请下方留言。

学习过程中,我很容易带入java的语法和思想去学习python,虽然他们有共同之处,但是学习过程中我应该告诉自己,“不懂编程,从头开始”。

知识来源:

  书本知识来源 :《python 基础教程 第三版》

  视频知识来源: 《北京图灵学院》 python 讲师 ——永远只有十八岁的刘大拿

   

  以及带我入门的 微信公众号 《python小课》

如果觉得我在打广告的童靴,恭喜你们答对了,《python小课》 是我 花了 9.9元买的体验课,也是我的python 路上的第一个引路者。至于为什么不在那学习?那是因为我穷,穷,穷。

但我并不想放弃,然后就在网易课程上看到了课程齐全还免费的 python 课程《免费Python全系列教程全栈工程师 - 网易云课堂》,随后也买了一本python书。

之所以要说这些 尤其是视频学习,首先作为一个编程人员,一名学习者应该做到  "吃水不忘挖井人”,关键别人又不收费。所以我这样做,觉得过分的朋友,见谅。

 

字符串的基本操作

  之前讲过,所有标准序列操作(索引,切片,乘法,成员资格检查,长度,最小值和最大值)都适用于字符串,但是字符串是不可变的,因此所有的元素赋值和切片赋值都是非法的。

str ='hello'
print(str[0:1]='h2')

#运行结果

    File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 2
    print(str[0:1]='h2')
         ^
SyntaxError: keyword can't be an expression

 

字符串格式:基础版

  python 提供了多种字符串格式设置方法,今天先了解一个简单的——百分号(%)。%右边需要指定一个类型

序号 名称 说明
%s 字符串格 表示设置格式的必须为字符类型,否则将无法运行
%d 整数 表示设置的格式必须为整数,否则将无法执行
%.3f 浮点数 表示设置3位小数的浮点数

%s 字符串格式化 (必须为字符串,若不是则用 str() 转为 字符串

name ='王富贵'
print('%s同学真是一个好孩子,总是喜欢乐于助人'%(name))
#运行结果
王富贵同学真是一个好孩子,总是喜欢乐于助人

%d 整数格式化(不能字符类型,否则用 int()进行转换)

name ='王富贵'
mothon = 6
print('%s同学真是一个好孩子,总是喜欢乐于助人'%(name))
print('在%d月考试中,获得了第一名'%(mothon))
#运行结果
王富贵同学真是一个好孩子,总是喜欢乐于助人
在6月考试中,获得了第一名

%.nf 浮点数格式化(同样也是不能为字符类型

name ='王富贵'
mothon = 6
total =564.5
print('%s同学真是一个好孩子,总是喜欢乐于助人'%(name))
print('在%d月考试中,获得了第一名'%(mothon))
print('他的总分是%.2f'%(total))

#运行结果
王富贵同学真是一个好孩子,总是喜欢乐于助人
在6月考试中,获得了第一名
他的总分是564.50

Template 关键字参数格式化:关键字参数可视为一种向命名替换字段提供值方式,如案例:

 

from string import Template

age =18
gender = ''
name ='王富贵'
hobby =['','','rap','篮球']


temp = Template('大家好,我叫$name,今年$age,我一名快乐的$gender,我爱好很多,如$hobby')

print(temp.substitute(name=name,age=age,gender=gender,hobby=hobby))

#运行结果 
大家好,我叫王富贵,今年18,我一名快乐的男,我爱好很多,如['', '', 'rap', '篮球']

索引格式化,这样的方式比 关键字更简单,更灵活 需要使用 format 函数 

  我们需要格式为四个地方,但是实际上我们只要填写三个就可以了,虽然关键字也能做到这一点,但是比起索引的方式,显得麻烦不少。可读性也不是很好。

str='''
    静夜思
  李 白
  床 前 {0} 光,
  疑 是 {1} 霜。
  举 头 望 {0},
  {2} 思 故 乡。

'''

print(str.format('明 月','地 上','低 头'))

#运行结果

    静夜思
  李 白
  床 前 明 月 光,
  疑 是 地 上 霜。
  举 头 望 明 月,
  低 头 思 故 乡。

我们再讲讲  format 的关键字 ,与 Template 不同的时,format 不是使用 $ 而是使用 {} 的方式,执行方式 Template 类似 ( k=v)

str="my name is {name}"

print(str.format(name='王富贵'))

#运行结果
my name is 王富贵

 注:值得注意的是,关键字是无关顺序的,只要赋予相对应的字段(k=v)就行。

str='my name is {name}, 今年 {age}'
print(str.format(age=18,name='王富贵'))

#运行结果

my name is 王富贵, 今年 18

在python 3.6中,如果变量与替换字段同名,还可以使用一种简写。在字符串前 加上 f

看看不加 f 的效果

name='王富贵'
str = 'name is {name}'
print(str)

#运行结果
name is {name}

有了 f buffer 加持后... 居然连  format 函数都可以不用了。

name='王富贵'
str = f'name is {name}'
print(str)

#运行结果
name is 王富贵

不过这种简写方式,是要顺序的,必须变量定义 在 字符串的前面。而 format 则不用考虑这些。

 

字符串格式:进阶版

  字符串格式涉及的内容有很多,即便是在这里也无法全面探索所有的细节,而只是介绍主要的组成部分。这里的基本思想是对字符串调用format,并提供要设置其格式的值。字符串包含有关设置的信息,而这些信息是使用一种微型格式指定语言(mini-language)

指定的。每个值都被插入字符串中,以替换用花括号括起来的替换字段。要在最终结果中包含花括号,可在格式字符串中使用两个花括号(即{{或}})来指定

str="{{hello python}}".format()
print(str)
#运行结果
{hello python}

还真是必须要用两个 花括号,要不然大大的异常就行下面挂着。(说实话现在的我一脸蒙蔽,这是什么跟什么什么啊。。。埋头苦干就是干)

str="{hello python}".format()
print(str)

#运行结果
Traceback (most recent call last):
  File "D:/develTools/PycharmProjects/project1/venv/Include/test3.py", line 2, in <module>
    str="{hello python}".format()
KeyError: 'hello python'

   在格式字符串中,最激动人心的部分为替换字段,替换字段由如下部分组成,其中每个部分都是可选的(以下是书中原话)。

  • 字段名:索引或标识符,指出要设置哪个指的格式并使用结果来替换该字段,除指定值外,还可指定值的特定部分,如列表的元素。
  • 转换标志:跟在叹号后面的单个字符。当前支持的字符包括 r(表示repr),s(表示)和 a(表示ascii)。如果你指定了转换标志,将不能使用对象本身的格式转设置机制,而是使用指定的函数将对象转换为字符串,再做进一步的格式设置。
  • 格式说明符:跟在冒号后面的表达式(这种表达式是使用微型格式指定语言表示的)。格式说明符让我们能够详细地指定最终的方式,包括格式类型(字符串,浮点数或十六进制数),字段宽度和数的精度,如何显示符号和千位分隔符,以及各种对齐和填充方式。

替换字段名

  在最简单的情况下,只需向format 提供要设置其格式的未命名参数,并在格式字符串中使用未名参数。并按照顺序将字段和参数进行匹对。也可以指定参数名称,对指定参数进行赋值。最重要的是他们可以混合使用,但是无参数名称需要顺序(无参需要写到前面)

str='''
    我叫 {name}
    来自{}
    今年{age}
    我的梦想是{}
'''

print(str.format("肯尼亚亚麻省法西利市",'称霸韩国',name='王富贵',age=18))

#运行结果

    我叫 王富贵
    来自肯尼亚亚麻省法西利市
    今年18
    我的梦想是称霸韩国

那为什么说午餐需要顺序?因为语法就不支持

str='''
    我叫 {name}
    来自{}
    今年{age}
    我的梦想是{}
'''

print(str.format("肯尼亚亚麻省法西利市",name='王富贵','称霸韩国',age=18))

#运行结果
    print(str.format("肯尼亚亚麻省法西利市",name='王富贵','称霸韩国',age=18))
                                                                      ^
SyntaxError: positional argument follows keyword argument

切记注意,无参要按照顺序排在前面,有参排在午餐后面,但是有参与有参之间可以不考虑顺序问题

str='''
    我叫 {name}
    来自{}
    今年{age}
    我的梦想是{}
'''

print(str.format("肯尼亚亚麻省法西利市",'称霸韩国',age=18,name='王富贵'))

#运行结果

    我叫 王富贵
    来自肯尼亚亚麻省法西利市
    今年18
    我的梦想是称霸韩国

列表索引

  如果上面那种方式让我们的程序变得混乱不堪(无参看起来可读性却是不太好,两者结合可读性更差)。字符串格式化,还支持列表结构,感觉确实干净了些。

studentInfo=[[1001,'王富贵',18,'','三班',265],[1002,'李村花',16,'','一班',465],[1003,'菲甜甜',18,'','二班',654]]


for k in studentInfo:
    info = '''
        学号: {no[0]},姓名 {name[1]},年龄 {age[2]},性别 {sex[3]},班级 {clazz[4]},得分 {total[5]}
    '''
    print(info.format(no=k,total=k,name=k,age=k,clazz=k,sex=k))

#运行结果
        学号: 1001,姓名 王富贵,年龄 18,性别 男,班级 三班,得分 265
    

        学号: 1002,姓名 李村花,年龄 16,性别 女,班级 一班,得分 465
    

        学号: 1003,姓名 菲甜甜,年龄 18,性别 女,班级 二班,得分 654

  如果列表中 字段太多了,不想定义参数名称 同样也支持无参的方式,但是每个位置都需要给上 列表

studentInfo=[[1001,'王富贵',18,'','三班',265],[1002,'李村花',16,'','一班',465],[1003,'菲甜甜',18,'','二班',654]]


for k in studentInfo:
    info = '''
        学号: {[0]},姓名 {[1]},年龄 {[2]},性别 {[3]},班级 {[4]},得分 {[5]}
    '''
    print(info.format(k,k,k,k,k,k))

#运行结果

        学号: 1001,姓名 王富贵,年龄 18,性别 男,班级 三班,得分 265
    

        学号: 1002,姓名 李村花,年龄 16,性别 女,班级 一班,得分 465
    

        学号: 1003,姓名 菲甜甜,年龄 18,性别 女,班级 二班,得分 654
    

 

 基本转换:

  指定要在字段中包含的值后,就可添加有关如何设置其格式的指令了。首先可以提供转换标志,书上将这里到时候,我半天没明白什么意思

  书上的案例是这样的

>>> print("{pi!s} {pi!r} {pi!a}".format(pi="π"))
>>> π 'π' '\u03c0'

  想了半天后 原来是对转义字符的格式化啊(扎心...) 很奇怪的是,为什么 \u 在只发出中或报错。 必须 \\u,了解的朋友下方留言

str='{value!s},{value!r},{value!a}'

print(str.format(value="我\000们"))

#运行结果
我 们,'我\x00们','\u6211\x00\u4eec'

  上面的三个标志(s,r,a)分别是指str,repr,ascii进行转换。str 和 repr 之前提到过,str 只是普通字符串,会被转义符影响,而 repr 会将字符串原样输出。ascii 就是 ASCII 表示。

  除了这些还可以指定要转换的值的类型,更准确的说是将他指定为某种类型。我们拿 整数 和 浮点数举例。

  语法:{参数名 :类型} 参数名可以不给

numstr="{value}"
print(numstr.format(value=18))
#运行结果
18

numstr="{value:d}"
print(numstr.format(value=18))
#运行结果
18

numstr="{value:f}"
print(numstr.format(value=18))
#运行结果
18.000000

numstr="{d}"
print(numstr.format(18))
#运行结果
18

 

字符串格式设置中的类型说明符

序号 类型 含义
1 b 将整数表示为二进制数
2 c 将整数解读为Unicode码点
3 d 将整数视为十进制数进行处理,这是整数默认使用的说明符
4 e 使用科学表示法来表示小数(用e来表示指数)
5 E 与e相同,但使用E来表示指数
6 f 将小数表示为浮点数
7 F 与f相同,但对于特殊值(nan和inf),使用大写表示
8 g 自动在顶点表示法和科学表示法之间做出选择。这是默认用于小时的说明符,但在默认情况下至少有一位小数
9 G 与g相同,但使用大写来表示指数和特殊值
10 n 与g相同,但插入随区域而异的数字分隔符
11 o 将整数表示为八进制
12 s 保持字符串的格式不变,这是默认的用于字符串的说明符
13 x 将整数表示为十六进制数并使用小写字母
14 X 与x相同,但使用大写字母
15 % 将数表示为百分比值(乘以100,按说明符f设置格式,再在后面加上%

 

宽度、精度和千位分隔符

  设置浮点数(或其他更具体的小数类型)的格式时,默认在小数点后面显示 6 小数 ,并根据需要设置字段的宽度,而不进行任何形式的填充。当然,这是默认情况下的,但是可以根据需求指定宽度和精度。

  宽度使用整数指定,如下所示:

#--------------------数字-------------
# repr 看得更直观一点
str='{num:10}'
print(repr(str.format(num=5)))
#运行结果
'         5'

#--------------------字符-------------
# repr 看得更直观一点
str='{str:10}'
print(repr(str.format(str='hello')))
#运行结果
'hello     '

  为什么 数字和 字符指定宽度后,位置不一样呢?数字时靠右,字符是靠左。不过不用担心,他们的位置是可以指定的(居左、居中、居右)待会聊....

  精度也是使用整数指定的,但需要在前面加上一个表示小数点的句点(f)。如下所示,2f 表示将小数保留2位小数

numstr="{num:.2f}"
print(numstr.format(num=4.3624))

#运行结果
4.36

  当然,可同时指定宽度和精度 10表示 宽度为10 ,2表示 保留两位小数 ,f 表示浮点数。

numstr="{num:10.2f}"
print(repr(numstr.format(num=4.3624)))
#运行结果
'      4.36'

   我们再看看 字符串指定精度(类似截取)

str='{:.5}'
print(str.format("hello python"))
#运行结果
hello

  最后再看看看 千位分隔符 用 , 表示。

mayun='我的钱大概有:{:,.3f}亿'

print(mayun.format(1000*10000))
#运行结果
我的钱大概有:10,000,000.000亿

  如果要使用随区域而异的千位分隔符,应该使用说明符n

 

符号、对齐和零填充

  有很多用于设置数字格式的机制,比如便于打印整齐的表格。在大多数情况下,只需要指定宽度和精度,但包含负数后,原本漂亮的输出可能不再漂亮了。另外字符和数字的默认对齐方式不同,你可能想修改默认的对齐方式,在指定宽度和精度的前面,

可添加一个标志。这个表示可以是零、加号、减号或空格,其中零表示使用0来填充数字。

  如下所示:

str="{num:010.2f}"
print(str.format(num=4.23))
#运行结果
0000004.23

  注意:虽然是甚至的长度用0占位,但是并不是说可以用其他字符填充(不能用字符),除了0是填充以外,其他数字都是表示长度为 x, 然后用空格进行填充(亲测出来的)

str="{num:11.2f}"
print(repr(str.format(num=+4.23)))
#运行结果
'       4.23'

  还有注意时,给一个0 如{num:0.2f},没啥子表示的,就是和普通运行出来的一样结果

str="{num:0.2f}"
print(repr(str.format(num=+4.23)))
#运行结果
'4.23'

  然后看看 + 和 - 号 有啥不一样 (贴一下运行结果吧)

str="{num:-0.2f}"
print(repr(str.format(num=4.23)))
#运行结果
'4.23'

str="{num:+0.2f}"
print(repr(str.format(num=4.23)))
#运行结果
'+4.23'

str="{num:+0.2f}"
print(repr(str.format(num=-4.23)))
#运行结果
'-4.23'

  要指定对齐方式 可以使用 <(左对齐)、^(居中)、>(右对齐)。

  如图所示 定义一张学生表格

table ="{:<10}{:^8}{:>10}"
body1="{:<10}{:^10}{:>10}"
body2="{:<10}{:^10}{:>10}"

print(table.format('学号','姓名','班级'))
print(body1.format('101','村花','一班'))
print(body2.format('102','富贵','二班'))

#运行结果
学号           姓名           班级
101           村花            一班
102           富贵            二班

Process finished with exit code 0

  再中间加上性别和年龄 看看效果(结果我也不知道)

table ="{:<10}{:^8}{:^8}{:^8}{:>10}"
body1="{:<10}{:^10}{:^10}{:^8}{:>10}"
body2="{:<10}{:^10}{:^10}{:^8}{:>10}"

print(table.format('学号','姓名','性别','年龄','班级'))
print(body1.format('101','村花','','16','一班'))
print(body2.format('102','富贵','','18','二班'))

#运行结果
学号           姓名      性别      年龄           班级
101           村花        女        16           一班
102           富贵        男        18           二班

  可以使用填充字符来扩充对齐说明符,这样将使用指定的字符而不是默认的空格来填充。

  如下所示,其他的应该也是差不多的操作,我也难得写了。

str="{:$^20}"
print(str.format('无法无天'))

#运行结果
$$$$$$$$无法无天$$$$$$$$

  需要介绍的最后一个要素是井号(#)选项,你可以将其放在符号说明符和宽度之间(如果制定了这种两种设置)。这个选项将触发另一个转换方式,转换细节随类而异。例外,对于二进制,八进制,十六进制转换,将加上一个前缀。

  二进制

num='{:b}'
print(num.format(36))
#运行结果
100100

num='{:#b}'
print(num.format(36))
#运行结果
0b100100

  八进制

num='{:o}'
print(num.format(36))
#运行结果
44

num='{:#o}'
print(num.format(36))
#运行结果
0o44

 

字符串方法

   前面介绍了列表的方法,而字符串的方式要多得多,因为很多方法都是从模块string哪里”继承“而来。(在较早的python版本中,这些方法为模块string中的函数,如果需要,现在依然可以使用到这些函数)。

模块string 

  虽然字符串方法完全盖住了模块string的风头,但这个模块包含一些字符串没有的常量和函数。下面介绍就是string模板中几个常用的常量

  • string.digits:包含数字0~9的字符串
    import string
    
    print(string.digits)
    #运行结果
    0123456789
  • string.ascii_letters:包含所有ASCII字母(大写和小写)的字符串
    import string
    
    print(string.ascii_letters)
    #运行结果
    abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
  • string.ascii_lowercase:包含所有小写SACII字母的字符串
    import string
    
    print(string.ascii_lowercase)
    #运行结果
    abcdefghijklmnopqrstuvwxyz
  • string.printable:包含所有可打印的ASCII字符的字符的字符串
    import string
    
    print(string.printable)
    
    #运行结果
    0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~     
    
  • string.punctuation:包含所有ASCII标点字符的字符串
    import string
    
    print(string.punctuation)
    #运行结果
    !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
  • string.ascii_uppercase:包含所有大写ASCII字母的字符串
    import string
    
    print(string.ascii_uppercase)
    #运行结果
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • 更多 stirng模块 常量 参考 (help(string))

  虽然说的是ASCII 字符,但值实际上是未解码的Unicode字符串。

字符串方法

  •  center:通过在两边添加填充字符(默认为空格)让字符串居中
  • find:在子串中查找子串,如果找到,就返回子串的第一个字符的索引,否则返回-1。
  • join:用于合并序列的元素
  • lower:返回字符串的小写版本
  • replace:将指定子串都替换为另一个字符串中,并返回替换后的结果
  • split:用于将字符串拆分为序列
  • strip:将字符串开头和末尾的空白(但不包括中间的空白)删除,并返回删除后的结果
  • translate:与replace一样替换字符串的特定部分,但不同的是它只能进行单字符替换。这个方法的优势在于能够同时替换多个字符,因此效率比replace高。

 

posted @ 2019-10-30 22:53  不朽_张  阅读(227)  评论(0)    收藏  举报