(四)Python的字符串,列表和元组

前言

每一种语言都有其特定的数据类型,Python也不例外,这里我们再次看一下Python的字符串,以及列表、元组,Python的列表(list)、元组(tuple)和swift的数组、元组也十分相似。

Python的字符串

字符串的编码和解码

python中,常常会涉及到字符串的编码问题,对于单个字符编码,python提供了ord()函数来获取字符的整数表示,提供chr()函数来将编码转换成相应的字符。我们在交互式环境下来看看它们是怎样操作的。

ord()函数获取单个字符的整数形式:

>>> ord('a')
97
>>> ord('b')
98
>>> ord('x')
120
>>> ord('y')
121
>>> ord('牛')
29275

chr()函数将编码穿换成字符:

>>> chr(97)
'a'
>>> chr(98)
'b'
>>> chr(120)
'x'
>>> chr(121)
'y'
>>> chr(29275)
'牛'

从以上可以看出,对于单个字符来说,python提供的两个函数可以将对应的字符整数相互转换,来获取对于的编码值。

但是实际上,我们通常用到的还是Python的字符串str居中,而Pythonstr在计算机的内存中又是以Unicode(统一的字符编码标准)表示,一个字符对应若干个字节,如果在网络上传输或保存到磁盘,需要将str变为以字节为单位的bytes。那么转换成以字节(bytes)为单位后是怎样表示的呢?这就牵扯到Python编码解码了。

Python中,编码使用encode(), 解码使用decode()

>>> 'dog'.encode('ascii')
b'dog'
>>> '小狗'.encode('utf-8')
b'\xe5\xb0\x8f\xe7\x8b\x97'

所以,在Python中,编码之后的字节类型(bytes)是用带b字母的前缀的单引号或双引号来表示。

注意:编码的时候,如果是纯英文编码,要使用asciiutf-8编码;如果是包含中文,那么一定要使用目前统一的编码标准utf-8。因为ascii是一个字节,utf-8是1~6个字节,而一个中文的编码要大于1个字节,显然,中文编码使用ascii编码会超出ascii的编码范围,类似值溢出是一个道理。

例如,中文编码使用ascii编码就会报错

>>> '小狗'.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

通过编码后,我们得到的就是字节(bytes), 那么,又怎么变为字符串呢?那就需要通过解码decode()操作。事实上,当我们从网络或磁盘上读取到了字节流(bytes)时,要变成字符串,我们就需要解码decode()

>>> b'dog'.decode('ascii')
'dog'
>>> b'\xe5\xb0\x8f\xe7\x8b\x97'.decode('utf-8')
'小狗'

现在,编码和解码都知道了,那么,如果我们想要知道一个字符串有几个字符怎么计算呢?字节又怎么计算呢?这时候,Python为我们提供了一个len()函数用来计算字符数和字节数。当所计算的是字符串时,就是字符数;当所计算的是字符串通过编码后的字节(bytes)时,计算的就是字节数。

// 计算字符数
>>> len('dog')
3
// 计算字节数
>>> len(b'dog')
3

// 计算字符数
>>> len('小狗')
2
// 计算字节数
>>> len(b'\xe5\xb0\x8f\xe7\x8b\x97')
6

所以,当用utf-8编码后,我们可以计算出一个中文在内存中占用3个字节,2个中文占用6个字节,而一个英文字母始终只占1个字节。

字符串的格式化

Python字符串的格式化有两种方式,一种就是使用%来格式化,同时赋予相应的占位符,比如:整数用%d、浮点数用%f、字符串用%s等,和C语言的占位符差不多,我们来看例子

>>> print('this is an integer: %d' % 99)
this is an integer: 99

>>> print('Hello, %s, you got scores: %f' % ('langke', 66.66))
Hello, langke, you got scores: 66.660000

为了保留2位小数,我们可以
>>> print('Hello, %s, you got scores: %.2f' % ('langke', 66.66))
Hello, langke, you got scores: 66.66

另外一种字符串格式化是字节用Python提供的函数format(), 同样来看例子

>>> print('Hello, {0}! I have abount {1} apples'.format('langke', 38))
Hello, langke! I have abount 38 apples
>>> print('It\'s {0}'.format(123456))
It's 123456
>>> print('result is {0:.3f}'.format(998.7809))
result is 998.781

Python的list

listPython中叫列表, 其实,我们完全可以称之为数组, 和swift中的数组一样,它是一个有序元素的集合,可以增、删、改、查的功能。

>>> names = ['Jhon', 'Alice', 'Bob', 'langke', '1', '2', '3']
>>> len(names)
7
>>> print(names)
['Jhon', 'Alice', 'Bob', 'langke', '1', '2', '3']

创建一个数组names, 并计算它的元素个数,计算元素个数我们用len()函数来计算。这就和swift或很多语言不一样了,比如在swift中, 我们计算数组元素个数,直接使用count来获取它的元素个数

print(names.count)

列表访问元素是和swift一样的,直接使用下标的方式

>>> names = ['Jhon', 'Alice', 'Bob', 'langke', '1', '2', '3']
>>> names[0]
'Jhon'
>>> names[2]
'Bob'

列表修改数组的元素

>>> fruits = ['apple', 'pear', 'banana']
>>> print(fruits)
['apple', 'pear', 'banana']
>>> fruits[1] = 'orange'
>>> print(fruits)
['apple', 'orange', 'banana']

列表添加元素

>>> ages = [18, 28, 38]
>>> print(ages)
[18, 28, 38]
>>> ages.append(48)
>>> print(ages)
[18, 28, 38, 48]

列表插入元素

>>> characters = ['a', 'b', 'c']
>>> print(characters)
['a', 'b', 'c']
>>> characters.insert(1, 'x')
>>> print(characters)
['a', 'x', 'b', 'c']

列表删除最后一个元素

>>> numbers = [11, 22, 33]
>>> print(numbers)
[11, 22, 33]
>>> numbers.pop()
33
>>> print(numbers)
[11, 22]

列表删除指定位置的元素

>>> numbers = [11, 22, 33]
>>> print(numbers)
[11, 22, 33]
>>> numbers.pop(1)
22
>>> print(numbers)
[11, 33]

列表还可以通过下面这种方式访问

>>> numbers = [11, 22, 33]
>>> numbers[-1]
33
>>> numbers[-2]
22
>>> numbers[-3]
11

下标-1表示倒数第一个元素下标, 下标-2表示倒数第二个元素下标, 下标-3表示倒数第三个元素下标, 以此类推...

Python的tuple

tuple也就是元组,也是一种有序列表, 在swift中也是这样的叫法。Objective-C就没有这个API。元组在很多时候很有作用,因为元组一旦创建,既有不可变性, 也就是你不能再去修改它。

既然元组不能改变,那么就以为着添加、删除、插入等改变元组的操作都不是允许的。

其他地方,元组和列表非常类似:

>>> names = ("Bob", "Alice", "Jhon", "Frank")
>>> len(names)
4
>>> print("this is a tuple: ", names)
this is a tuple:  ('Bob', 'Alice', 'Jhon', 'Frank')

但是,尤其需要注意的一点是,元组在定义一个元素的时候,需要在第一个元素后面加一个,, 比如

>>> age = (18,)
>>> len(age)
1

最后,针对tuple,我们来看一下一个比较有意思的事情。

既然说元组一旦创建就不能改变,也不会改变

在一个.py源文件中,我们有这样的代码

list = ['a', 'b']
names = ('Alice', 'Frank', list)
list[0] = 'x'
list[1] = 'y'
print(names)

或者

list = ['a', 'b']
names = ('Alice', 'Frank', list)
names[4][0] = 'x'
names[4][1] = 'y'
print(names)

然后执行该源文件

➜  Desktop python3 tuple.py
('Alice', 'Frank', ['x', 'y'])

咦?元组names怎么改变了呢?

事实上,元组的不会变是指指针的指向不会改变, 在上面的例子中,元组的最后一个元素也就是数组list是可以改变的,当我们改变list中的元素时,指向listnames的内容也就发生了改变,但是**指向并没有改变。

然而,如果我们这样做改变时

list = ['a', 'b']
names = ('Alice', 'Frank', list)
list = ['x', 'y']
print(names)

结果还是('Alice', 'Frank', ['x', 'y'])吗?

为了验证一下,我们来做个测试

➜  Desktop python3 tuple.py
('Alice', 'Frank', ['a', 'b'])

嗯?What's up??? 刚才不是说改变元组中的数组元素时,元组内容也会改变吗?那现在为何没有改变?

是这样的,由于数组list是一个变量,当我们做list = ['x', 'y']操作的时候,这就相等于在计算机在内存中开辟了另一块内存,并且是连续的内存,而之前的list = ['a', 'b']由于还有着元组names的指向,所以没有在内存中被销毁释放,所以names指向的是原来的数组list, 而不是新开辟的另一个"list"

那之前的改变和刚才的不一样?

是的,之前通过list[0] = 'x'的方式,你改变了数组的元素, 但是并没有开辟一块新的内存,也就是说,内存中只有一个list数组,只是元素发生改变而已。而list = ['x', 'y']本质是就是重新申请了一块内存空间,我们可以看做是内存中有"两个"list数组。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354