python学习笔记---Python基础【廖雪峰】
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
Python基础
数据类型和变量
整数
对于很大的数例如10000000000
很难数清楚0的个数。Python允许在数字中间以_
分隔因此写成10_000_000_000
和10000000000
是完全一样的。十六进制数也可以写成0xa1b2_c3d4
。
>>> print(100000==100_000)
True
字符串
如果字符串里面有很多字符都需要转义就需要加很多\
为了简化Python还允许用r''
表示''
内部的字符串默认不转义可以自己试试
>>> print('\\\t\\')
\ \
>>> print(r'\\\t\\')
\\\t\\
如果字符串内部有很多换行用\n
写在一行里不好阅读为了简化Python允许用'''...'''
的格式表示多行内容可以自己试试
>>> print('''line1
... line2
... line3''')
line1
line2
line3
上面是在交互式命令行内输入注意在输入多行内容时提示符由>>>
变为...
提示你可以接着上一行输入注意...
是提示符不是代码的一部分
┌────────────────────────────────────────────────────────┐
│Command Prompt - python _ □ x │
├────────────────────────────────────────────────────────┤
│>>> print('''line1 │
│... line2 │
│... line3''') │
│line1 │
│line2 │
│line3 │
│ │
│>>> _ │
│ │
│ │
│ │
└────────────────────────────────────────────────────────┘
当输入完结束符`````和括号)
后执行该语句并打印结果。
变量
Python支持多种数据类型在计算机内部可以把任何数据都看成一个“对象”而变量就是在程序中用来指向这些数据对象的对变量赋值就是把数据和变量给关联起来。
对变量赋值
x = y
是把变量x
指向真正的对象该对象是变量y
所指向的。随后对变量y
的赋值不影响变量x
的指向。
a = 'ABC'
b = a
a = 'XYZ'
print(b)
这里的【b = a】只是说变量b和a指向的是内存中的同一个内存空间0x0001
而下一步【a = ‘XYZ’】变量a改变了其内存空间的指向0x0002而这个时候变量b的内存空间指向还是原来的0x001
【所以这里主要讲的就是】
Python解释器干了两件事情
- 在内存中创建了一个
'ABC'
的字符串- 在内存中创建了一个名为
a
的变量并把它指向'ABC'
。也可以把一个变量
a
赋值给另一个变量b
这个操作实际上是把变量b
指向变量a
所指向的数据而不是我们理解的简单的数字之间的赋值操作[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lSEL1oFv-1673876229143)(null)]
字符串和编码
字符串的编码问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wuO4ugDE-1673876228855)(null)]
搞清楚了ASCII、Unicode和UTF-8的关系我们就可以总结一下现在计算机系统通用的字符编码工作方式
在计算机内存中统一使用Unicode编码【防止多语言出现乱码】当需要保存到硬盘或者需要传输的时候就转换为UTF-8编码【减少工作量】。
用记事本编辑的时候从文件读取的UTF-8字符被转换为Unicode字符到内存里编辑完成后保存的时候再把Unicode转换为UTF-8保存到文件
浏览网页的时候服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器
所以你看到很多网页的源码上会有类似<meta charset="UTF-8" />
的信息表示该网页正是用的UTF-8编码。
Python的字符串
对于单个字符的编码Python提供了ord()
函数获取字符的整数表示chr()
函数把编码转换为对应的字符
>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'
如果知道字符的整数编码还可以用十六进制这么写str
>>> '\u4e2d\u6587'
'中文'
两种写法完全是等价的。
对bytes
类型的数据
由于Python的字符串类型是str
在内存中以Unicode表示一个字符对应若干个字节。如果要在网络上传输或者保存到磁盘上就需要把str
变为以字节为单位的bytes
。
Python对bytes
类型的数据用带b
前缀的单引号或双引号表示
x = b'ABC'
要注意区分'ABC'
和b'ABC'
前者是str
后者虽然内容显示得和前者一样但bytes
的每个字符都只占用一个字节。
反过来如果我们从网络或磁盘上读取了字节流那么读到的数据就是bytes
。要把bytes
变为str
就需要用decode()
方法
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'
如果bytes
中包含无法解码的字节decode()
方法会报错
>>> b'\xe4\xb8\xad\xff'.decode('utf-8')
Traceback (most recent call last):
...
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte
如果bytes
中只有一小部分无效的字节可以传入==errors='ignore'
忽略错误的字节==
>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
'中'
要计算str
包含多少个字符可以用len()
函数
格式化
用%
实现
在Python中采用的格式化方式和C语言是一致的用%
实现举例如下
>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'
你可能猜到了%
运算符就是用来格式化字符串的。在字符串内部%s
表示用字符串替换%d
表示用整数替换有几个%?
占位符后面就跟几个变量或者值顺序要对应好。如果只有一个%?
括号可以省略。
常见的占位符有
占位符 | 替换内容 |
---|---|
%d | 整数 |
%f | 浮点数 |
%s | 字符串 |
%x | 十六进制整数 |
字符串里面的
%
是一个普通字符怎么办这个时候就需要转义用%%
来表示一个%
>>> 'growth rate: %d %%' % 7 'growth rate: 7 %'
format()
另一种格式化字符串的方法是使用字符串的format()
方法它会用传入的参数==依次替换字符串内的占位符{0}
、{1}
……==不过这种方式写起来比%要麻烦得多
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'
f-string
最后一种格式化字符串的方法是使用以f
开头的字符串称之为f-string
它和普通字符串不同之处在于字符串如果包含{xxx}
就会以对应的变量替换
>>> r = 2.5
>>> s = 3.14 * r ** 2
>>> print(f'The area of a circle with radius {r} is {s:.2f}')
The area of a circle with radius 2.5 is 19.62
上述代码中{r}
被变量r
的值替换{s:.2f}
被变量s
的值替换并且:
后面的.2f
指定了格式化参数即保留两位小数因此{s:.2f}
的替换结果是19.62
。
使用list和tuple
list
列表list。list是一种有序的集合可以随时添加和删除其中的元素。
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates
['Michael', 'Bob', 'Tracy']
用len()
函数可以获得list元素的个数
>>> len(classmates)
3
用索引来访问list中每一个位置的元素记得索引是从0
开始的
>>> classmates[0]
'Michael'
如果要取最后一个元素除了计算索引位置外还可以用-1
做索引直接获取最后一个元素
>>> classmates[-1]
'Tracy'
list是可变的有序表所以可以往list中追加元素到末尾
>>> classmates.append('Adam')
>>> classmates
['Michael', 'Bob', 'Tracy', 'Adam']
也可以把元素插入到指定的位置比如索引号为
1
的位置>>> classmates.insert(1, 'Jack') >>> classmates ['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
要删除list末尾的元素用pop()
方法
>>> classmates.pop()
'Adam'
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy']
要删除指定位置的元素用
pop(i)
方法其中i
是索引位置>>> classmates.pop(1) 'Jack' >>> classmates ['Michael', 'Bob', 'Tracy']
要把某个元素替换成别的元素可以直接赋值给对应的索引位置
>>> classmates[1] = 'Sarah'
>>> classmates
['Michael', 'Sarah', 'Tracy']
list元素也可以是另一个list比如
>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
>>> len(s)
4
二维数组
tuple
另一种有序列表叫元组tuple。tuple和list非常类似但是tuple一旦初始化就不能修改比如同样是列出同学的名字
>>> classmates = ('Michael', 'Bob', 'Tracy')
现在classmates这个tuple不能变了它也没有append()insert()这样的方法。其他获取元素的方法和list是一样的你可以正常地使用classmates[0]
classmates[-1]
但不能赋值成另外的元素。
不可变的tuple有什么意义因为tuple不可变所以代码更安全。如果可能能用tuple代替list就尽量用tuple。
tuple的陷阱当你定义一个tuple时在定义的时候tuple的元素就必须被确定下来比如
如果要定义一个空的tuple可以写成()
>>> t = ()
>>> t
()
只有1个元素的tuple定义时必须加一个逗号,
来消除歧义
>>> t = (1,)
>>> t
(1,)
最后来看一个“可变的”tuple
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
表面上看tuple的元素确实变了但其实变的不是tuple的元素而是list的元素。tuple一开始指向的list并没有改成别的list所以tuple所谓的“不变”是说tuple的每个元素指向永远不变。即指向
'a'
就不能改成指向'b'
指向一个list就不能改成指向其他对象但指向的这个list本身是可变的
循环
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
for x in ...
循环就是把每个元素代入变量x
然后执行缩进块的语句。
...
中表示可以迭代的对象。元组、列表等。
Python提供一个range()
函数可以生成一个整数序列再通过list()
函数可以转换为list。
>>> list(range(5))
[0, 1, 2, 3, 4]
使用dict和set
dict
dict全称dictionary在其他语言中也称为map使用键-值key-value存储具有极快的查找速度。
要避免key不存在的错误有两种办法
一是通过
in
判断key是否存在>>> 'Thomas' in d False
二是通过dict提供的
get()
方法如果key不存在可以返回None
或者自己指定的value>>> d.get('Thomas') >>> d.get('Thomas', -1) -1
注意返回
None
的时候Python的交互环境不显示结果。
要删除一个key用pop(key)
方法对应的value也会从dict中删除
>>> d.pop('Bob')
75
>>> d
{'Michael': 95, 'Tracy': 85}
请务必注意dict内部存放的顺序和key放入的顺序是没有关系的。
dict的key必须是不可变对象。
set
set和dict类似也是一组key的集合但不存储value。由于key不能重复所以在set中没有重复的key。
要创建一个set需要提供一个list作为输入集合
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}
注意传入的参数[1, 2, 3]
是一个list而显示的{1, 2, 3}
只是告诉你这个set内部有123这3个元素显示的顺序也不表示set是有序的。
重复元素在set中自动被过滤
>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}
通过add(key)
方法可以添加元素到set中可以重复添加但不会有效果
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
通过remove(key)
方法可以删除元素
>>> s.remove(4)
>>> s
{1, 2, 3}
set可以看成数学意义上的无序和无重复元素的集合因此两个set可以做数学意义上的交集、并集等操作
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}
set和dict的唯一区别仅在于没有存储对应的value但是set的原理和dict一样所以同样不可以放入可变对象因为无法判断两个可变对象是否相等也就无法保证set内部“不会有重复元素”。试试把list放入set看看是否会报错。
不可变对象与可变对象
str是不变对象而list是可变对象。
对于可变对象比如list对list进行操作list内部的内容是会变化的比如
>>> a = ['c', 'b', 'a']
>>> a.sort()
>>> a
['a', 'b', 'c']
而对于不可变对象比如str对str进行操作呢
python >>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'
虽然字符串有个replace()
方法也确实变出了'Abc'
但变量a
最后仍是'abc'
应该怎么理解呢
>>> a = 'abc'
>>> b = a.replace('a', 'A')
>>> b
'Abc'
>>> a
'abc'
要始终牢记的是a
是变量而'abc'
才是字符串对象有些时候我们经常说对象a
的内容是'abc'
但其实是指a
本身是一个变量它指向的对象的内容才是'abc'
┌───┐ ┌───────┐
│ a │─────────────────>│ 'abc' │
└───┘ └───────┘
当我们调用a.replace('a', 'A')
时实际上调用方法replace
是作用在字符串对象'abc'
上的而这个方法虽然名字叫replace
但却没有改变字符串'abc'
的内容。相反replace
方法创建了一个新字符串'Abc'
并返回如果我们用变量b
指向该新字符串就容易理解了变量a
仍指向原有的字符串'abc'
但变量b
却指向新字符串'Abc'
了
┌───┐ ┌───────┐
│ a │─────────────────>│ 'abc' │
└───┘ └───────┘
┌───┐ ┌───────┐
│ b │─────────────────>│ 'Abc' │
└───┘ └───────┘
所以对于不变对象来说调用对象自身的任意方法也不会改变该对象自身的内容。相反这些方法会创建新的对象并返回这样就保证了不可变对象本身永远是不可变的。