第一章-基础
1 数据类型和变量
1.1整数
16进制数前面加0x
1.2 浮点数
1.23x109就是1.23e9
1.3 字符串
单引号或者双引号
要输入引号可以用\(右斜线)转义或者使用不同类型的引号, 但是转义符\可以转义更多的诸如本身
>>> str1 = 'I\'m fine'
>>> str1
"I'm fine"
>>> str2 = "I'm fine"
>>> str2
"I'm fine"
在输出前面加r表示后面不转义, 也就是原生字符串
>>> print('\\\t\\')
\ \
>>> print(r'\\\t\\')
\\\t\\
表示多行内容 '''内容里面直接回车就好了''' 内容会保留成回车
>>> print('''line1
... line2
... line3''')
line1
line2
line3
在程序中直接输入就好了
print('''line1
line2
line3''')
同时也可以在'''前面加入r来实现换行和不转义
1.4 布尔值
只有True和False两种值
布尔值运算为False的情况:
空list, 空set, 空tuple, 空dict
空字符('')
0
None
布尔值可以进行and or not 运算
在Python中, 先执行非, 再执行与, 最后执行或, 遵循短路原则
1.5 空值
None表示
1.6 变量
变量名必须是大小写英文、数字和下划线的组合,且不能用数字开头
python是动态语言, 赋值的时候不用管类型, 新建的时候也不用声明类型
静态语言诸如java, 要声明类型, 赋值也要看类型
1.7 常量
通常用全部大写的变量名表示常量
1.8 Python的运算
1.8.1 算数运算
/计算的结果始终为浮点型
//叫做地板除, 结果是小于除法结果的最大整数
1.8.2 比较运算符
其中<>是python 2.x的用法, 3.x已经不再使用了
1.8.3 赋值运算符
1.8.4 位运算符
与: 有假为假, 全真为真
或: 有真为真, 全假为假
异或: 同为假, 异为真
同或: 同为真, 异为假
左移: 左移多少位, 就乘以多少2
右移: 右移多少位, 就除以多少2
取反运算处理如下:
在计算机存储的是补码形式
正数的原码, 反码, 补码是一致的
取反就是补码的所有位取反, 然后获得取反之后的补码, 通过这个补码获得反码, 来看是哪个数
-9的取反过程如下:
9的补码是 0000 1001
取反 1111 0110
由于这是负数, 要知道这是多少需要将这个补码改为原码
减一 1111 0101
取反 1000 1010 也就是-10
负数的原码, 反码. 补码是不一致的
原码是其绝对值的编码, 将最高位标志位设为1
-10的绝对值 0000 1010
原码就是 1000 1010
反码就是, 原码取反
1111 0101
补码就是, 反码加1
1111 0110
-10的取反过程如下:
-10的补码1111 0110
取反 0000 1001 得到的就是正数, 也就是+9
总结:
补码-->绝对值: 减一取反
绝对值-->补码: 取反加一
1.9 三元运算符
三元运算符的格式:
为真的时候的结果 if 判断条件 else 为假的时候的结果
主要是用于判断后赋值给别人, 不能把为真为假的添加用于赋值, 这是Python与别的语言不一样的地方
>>> a = 4 if True else a = 4
SyntaxError: can't assign to conditional expression
#错误使用方法, 不能在结果里赋值运算
>>> a = (45 if True else 46)
>>> a
45
#正确的使用方式
1.10 常用函数
获得数字的二进制 bin(数字)
获得数字的八进制 oct(数字)
获得数字的十六进制 hex(数字)
2 字符串和编码
2.1 字符编码
最开始的时候电脑将1个比特作为一个字节, 因而最大表示的整数就是255
最开始的编码只有127个字符编入, 使用的也是一个字节, 也就是ASCII
中文由于数量众多, 因而采用两个字节, 形成了GB2312
随后GB2312发展成为GBK
Unicode是将所有语言都编入进去的语言, 采用两个字节, 少数的字会有四个字节
Unicode可以分为UTF-32 是四个字节, UTF-16是两个字节, UTF-8是一个字节
由于这样比较费空间, 因而形成变长的UTF-8, 常用的英文字母被编码成1个字节, 汉字通常是3个字节, 只有很生僻的字符才会被编码成4-6个字节
Python3最大的编码处理结果就是: 把字符和字节类型完全分开了
从内存到CPU的处理主要是encode()和decode()两个处理
2.1.1 Python3的编码问题
在计算机的内存中, 统一使用Unicode编码, 当需要保存到硬盘或者传输的时候, 就转化为UTF-8
在Python3中, 字符串是以Unicode编码的, 一个字符对应若干个字节
同样的, 在网络上传输, 保存到磁盘上的时候, 会把字符串(str)转化以字符为单位的bytes
其中Bytes是以 b 为前缀的单引号或者双引号的字符串.
x = b'ABC'
str可以通过 encode() 方法来指定某个编码的 bytes
>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.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为str需要 decode() 方法
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'
计算多少个字符
>>> len('ABC')
3
>>> len('中文')
2
如果内容是bytes, 就是返回存储占用的字节数
>>> len(b'ABC')
3
>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>> len('中文'.encode('utf-8'))
6
因此,UTF-8的编码中, 中文占用3个字节, 英文字符占用1个字节
2.1.2 Python2的编码
早期的Python由于形成的时间比Unicode的发布时间早, 因而早期的Python只支持ASCII编码
普通的字符串str是以ASCII编码
在Python2中Unicode的字符串是用u表示的
>>> print u'中文'
中文
>>> u'中'
u'\u4e2d'
将Unicode字符串转化为UTF-8要使用 encode() 方法
>>> u'ABC'.encode('utf-8')
'ABC'
>>> u'中文'.encode('utf-8')
'\xe4\xb8\xad\xe6\x96\x87'
将UTF-8的编码表示的str转化为Unicode字符串要使用 decode() 方法
>>> 'abc'.decode('utf-8')
u'abc'
>>> '\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
u'\u4e2d\u6587'
>>> print '\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
中文
2.2 Python的字符串
Python 3是Unicode字符集
使用ord和chr可以将实际编码与字符对应上
ord('字符') 获取字符的整数表示
chr(整数) 根据整数获得字符
>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'
一般还可以用十六进制表示字符
>>> '\u4e2d\u6587'
'中文'
正常字符串 一个字符对应若干个字节
b'字符串' 一个字符只用一个字节表示,用于网络传输或者保存到磁盘上
转换成别的编码类型
字符串.encode('目标编码')
通常有 ascii 和 utf-8
>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
计算一个字符串有多少个字符, 如果换成bytes,len()函数就计算字节数
len(字符串)
>>> len('中文')
2
>>> len('中文'.encode('utf-8'))
6
>>>
为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换
所以, 在有中文的源码中, 最好保存为UTF-8的格式
通常文件头写上如下的代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
第一句表示Linux系统这是一个Python程序
第二句告诉Python解释器以UTF-8的编码读源代码
字符串的处理
replace方法
字符串A.replace("要替换的","替换成的")
注意: 返回的结果是替换的内容, 但是字符串A本身不会发生变化
>>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'
3 格式化
'字符串内容 占位符'%(占位符的内容)
>>> 'Hello, %s' % 'world' 'Hello, world' >>> 'Hi, %s, you have $%d.' % ('Michael', 1000000) 'Hi, Michael, you have $1000000.'
常见的占位符:
补0或者限定输出的长度
>>> '%2d-%02d' % (3, 1)
' 3-01' #注意此处3前面有空格
限制小数点位数:
>>> '%.2f' % 3.1415926
'3.14'
想要输出% 用%%表示
>>> 'growth rate: %d %%' % 7
'growth rate: 7 %'
3 list和tuple
3.1 list
定义
classmates = ['Michael', 'Bob', 'Tracy']
特点:
List是可变的, 可以添加重复的元素的
获取list的长度
len(list名字)
获取数据
名字[索引]
从左往右0开始
从右往左-1开始
list是一个可变的 有序表
添加数据
名字.append(添加的内容)
添加的数据放到最后
插入数据
名字.insert(位置,数据)
数据就放在位置上, 以后的数据依次后延
删除数据
名字.pop()
删除最后一个元素
名字.pop(位置)
删除某位置的元素
替换元素
名字[位置]=新换的数据
list里面的元素的数据类型也可以不同
list元素也可以是另一个list
此时回去数据可以形成多级[][]的形式
list的排序
list名字.sort()
一般按照字母的字典排序, 数字的大小排序
3.2 tuple
tuple又叫元组
特点:
一旦初始化就不能被修改
定义
classmates = ('Michael', 'Bob', 'Tracy')
空tuple的定义
t = ()
单个元素tuple的定义
t = (1,)
注意: 当tuple的元素当中有类似于list这样可以改变的元素的时候, 该tuple就变的"可变"了
因此, 在初始化tuple的时候最好保证元素是不可变的
3.3 list和tuple的相互转换
list对象 = list(tuple对象)
但是这不改变原来的 元组对象, 只是根据原来的元组的内容新建了一个列表
tuple对象 = tuple(list对象)
但是这不改变原来的 列表对象, 只是根据原来的列表的内容新建了一个元组
4 条件判断和循环
4.1 条件判断
if语句的结构
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>
特点: 只会执行其中的一个函数体
4.2 input
获取用户输入
变量 = input("输入提示")
birth = input('birth: ')
input()返回的数据类型是字符串类型
字符串类型转为int类型
int(字符串)
同理, 转化为float就是
float(字符串)
4.3 循环
4.3.1 for..in循环
可以将list或者tuple的元素迭代出来
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
sum = 0
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
sum = sum + x
print(sum)
生成整数序列方法
range(整数A)
生成了从 0 开始到小于 整数A 的整数序列
sum = 0
for x in range(101):
sum = sum + x
print(sum)
4.3.2 while循环
满足条件就循环, 不满足就退出
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)
5 dict和set
5.1 dict
dict也就是字典类型, 全称dictionary, 在其他语言中称为map, 是基于键值对的
特点: 查找速度块 实际存储的顺序和key放入的顺序不一致
查询块的原因
因为存储键值对的时候做了处理, 针对key值可以计算出相应的存储位置, 就跟字典的拼音查询一个道理
正是因为这个原因, 实际存储的顺序与key的顺序是不一致的
定义
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
获取值
方法一: 字典名字[key值]
d['Michael']
方法二: 字典名字.get(key)
d.get('Thomas')
当所输入的key值不在字典当中, 就会输出None值
此时还可以设置遇到这种情况输出自己的值的时候,可以 字典名字.get(key, 为None时的默认值)
d.get('Thomas', -1)
因此可以判断key是不是在字典中
key in 字典名字
'Thomas' in d
设置值
字典名字[key值]=值
d['Adam'] = 67
重复对同一个key赋值, 最后存储的值是最后一次赋值的值
删除值
字典名字.pop(key)
d.pop('Bob')
注意: 字典类型的key最好是设置为不可变的对象
因为如果key值变化, 存储的内容地址就会跟着发生变化
5.2 set
特点:
只存储key, 类似于List
可以修改set
set的存储顺序和定义顺序不同(与list区别, list怎么定义的就是怎么存储的)
存储的key不重复, 重复添加没有什么效果(这是与List的区别, 可以说set就是List去重之后用于集合运算的数据结构)
表示由花括号表示
常用于做集合的运算
定义
set名 = set([key, key, key])
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}
添加元素
set名.add(key)
>>> s.add(4)
>>> s
{1, 2, 3, 4}
删除元素
set名.remove(key)
>>> s.remove(3)
>>> s
{1, 2}
应用, 两个set可以做并集和交集
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}
6 深浅拷贝
Python的赋值实际上是赋值引用
浅拷贝的实现:
方法一: 通过copy()方法
方法二: 通过切片的方法
方法三: 通过工厂的方法
方法四: 直接赋值
>>> jack = ['jack', ['age', 20]]
>>> jack1 = jack.copy()
>>> jack2 = jack[:]
>>> jack3 = list(jack)
>>> jack4 = jack
浅拷贝的特点:
只拷贝引用, 也就是拷贝的是原内容的地址
当修改jack的第一个字段'jack'的时候, 由于字符串是不可以变化的, 所以实际上是新开辟新空间并将地址返回, 这样的修改相互不影响
但是如果修改第二个字段['age', 20]的话, 由于这个list本身是存储的地址, 所以一修改都修改了
深拷贝的实现:
使用copy的deepcopy方法
>>> jack = ['jack', ['age', '20']]
>>> import copy
>>> tom = copy.deepcopy(jack)
>>> anny = copy.deepcopy(jack)
深拷贝的特点:
单独形成内容, 相互不影响
不会发生浅拷贝的问题