Python基础知识
1 - 变量/常量
1.1 - 变量使用方式
1.需先定义再使用(使用规范)
name = 'cbg' (定义字符串)
age = 20 (定义整数)
sorce = 19.76 (定义浮点数)
2.变量名定义规范
(1)变量名只能是数字 字母 下划线的任意组合
(2)数字不能开头
(3)关键字不能作为变量名
3.书写规范
(1)驼峰体 ———— js推荐使用的方式
AgeOfJason = 18
2.下划线 ———— python推荐使用的方式
age_of_jason = 18
1.2 - 变量三要素
1.id
类似于内存地址
2.type
变量名指向的数据的数据类型
3.value
变量名指向的数据的值
1.3 - 小整数池
Python在实现int类型变量的存储在小范围内使用了一个小整数池,为了避免与创建相同的值而重复的申请内存空间所带来的效率问题
1.范围:-5 ~ 256之间
2.验证方式:
a = 4
print(id(a))
x = 3
print(id(x))
x += 1
print(id(x))
1.4 - 常量
Python中并没有严格意义上的常量,且通常我们使用全大写来定义常量
PI = 3.141592654
HOST = '127.0.0.1'
2 - IO/注释
2.1 - input输入
python3的输入
res = input() # 无参输入
res = input('Please input:') # 先输出字符串再进行输入
print(res,type(res)) # 其用户输入默认为字符串型
python2的输入
input # 用户输入什么类型就存成什么类型
>>> res = input()
>>> res = 'cbg'
>>> type(res) # <type 'str'>
>>> res = input()
>>> res = 123
>>> type(res) # <type 'int'>
raw_input # 等价于python3的input
2.2 - print输出
1.占位符:
%s 可以接受任意类型的值
%d 只能接受数字
2.使用方式:
print('my name is %s' % ('cbg')) # 补位%s的位置
print('%08d' % 123) # 8位整数,不够输出前导0补齐8位,够则是多少就多少位
2.3 - 注释
1.单行注释:
# python是世界上最好的语言
2.多行注释:
'''
python是世界上最好的语言
python是世界上最好的语言
'''
"""
python是世界上最好的语言
python是世界上最好的语言
"""
3 - 基础数据类型
3.1 - 整数型int
用于存储只用整数表示的变量
age = 18
birth = 2002
student_count = 76
3.2 - 浮点型float
用于存储需要实数表示的变量
height = 183.5
weigth = 150.1
salary = -3000
3.3 - 字符串str
1.用于存储需要字符混合表示的变量:
name = 'cbg'
addresss = '温州'
gender = '男'
2.三种定义方式:
name = 'cbg'
name = "cbg"
name = """cbg"""
name = '''cbg'''
3.输出引号:
print('"python"')
4.字符串的加乘运算:
print('cbg' + 'python')
print('cbg' * 10)
3.4 - 列表list
1.性质:
内部可以存储多个元素,且每个元素可以是任意数据类型
2.存储方式:
以中括号'[]'包裹,且以','分隔
name_list = ['jason', 'egon', 'tank', 'sean', 'oscar']
name_list = [111,11.11,'jason',[12,3,4,5,6]]
3.5 - 字典dict
1.性质:
内部可以存储多个元素,且每个元素以key:value的形式存储数据,其中key是对value的描述性信息
key一般情况下都是字符串 但是只要key是不可变数据类型都可以
value可以是任意数据类型
2.存储方式:
以中括号'{}'包裹,以','分隔元素,以':'表示每个元素(key:value)
person_info = {'name':'jason','age':18,'hobby':['read','DBJ']} # 字典中的数据是无序的
3.6 - 布尔值bool
用来记录事物的真假两种状态的
python内部所有的逻辑判断,都是转成布尔值再判断的
is_ok = True
is_ok = False
"""
在python中我们习惯性将存储布尔值的变量名/函数名用is_开头
只要一个变量名或者函数名是用is开头的那么极大概率指向的/返回的应该是一个布尔值
"""
主要应用在逻辑判断中if
"""
布尔值为False的有哪些数据
0、None、''、[]、{}
"""
3.7 - 元组tuple
1.性质:
元组与列表相似 也是可以存储多个任意类型的元素
不同之处在于元组的元素不能被修改,即元祖相当于不可变的列表
用于记录多个固定不允许修改的值 单纯的用于查看
2.存储方式:
以中括号'()'包裹,且以','分隔,且至少要有一个','
countries = ('中国','日本','美国')
countries = ('中国','日本','美国')
print(type(countries)) # <class 'tuple'>
无',':
names = ('jason')
print(type(names)) # <class 'str'>
ages = (18)
print(type(ages)) # <class 'int'>
# 元组里面如果只有一个元素 不加逗号的情况下元素是什么类型就是什么类型
有',':
names = ('jason',)
print(type(names)) # <class 'tuple'>
ages = (18,)
print(type(ages)) # <class 'tuple'>
3.8 - 集合set
1.性质;
(1)使用集合只在下面两种情况下使用
去重、关系运算:交叉并集
(2)集合每一个元素必须是不可变类型
(3)集合内不可能存在重复的元素
(4)集合内元素是无序的
PS:
(1)可变类型 列表
值改变内存地址不变
(2)不可变类型 字符串
值改变内存地址肯定改变
2.存储方式
se = {1,2,3,4,5,6,7}
3.如何区别set与dict / 定义一个空集合
s = {}
print(type(s)) # <class 'dict'>
d = {}
print(type(d)) # <class 'dict'>
# 定义空集合
se = set()
print(type(se)) # <class 'set'>
4 - 运算符
4.1 - 增量赋值
简单的四则运算、幂/模/整除、直接赋值
x = 10
x = x + 1 # x += 1
x = x - 1 # x -= 1
x = x * 2 # x *= 2
x = x / 2 # x /= 2
x = x ** 2 # x **= 2
x = x // 2 # x //= 2
x = x % 2 # x %= 2
4.2 - 链式赋值
x,y,z = 10
4.3 - 交叉赋值
m = 10
n = 20
m,n = n,m
4.4 - 解压赋值
1.正确赋值:
l = [111,222,333,444]
x,y,z,o = l # 左右两边个数一致
2.因元素不匹配的错误赋值:
a,b = l # too many values to unpack (expected 2)
a,b,c,d,e = l # not enough values to unpack (expected 5, got 4)
3.使用_作为变量名解决部分取值问题:
a,*_ = l
print(a,_) # 111 [222,333,444]
a,*_,b = l
print(a,_,b) # 111 [222, 333] 444
"""
我们需要解压赋值元素但是解压出来的数据我们有不需要用
那么这个时候我们会习惯用下划线作为变量名
这样我们一看到就知道这是一个无用的数据 仅仅是为了满足语法需求
"""
4.5 - 逻辑运算
与 and
或 or
非 not
1.and链接多个条件,会按照从左往右的顺序依次判断,一旦某个条件为False则无需继续往后判断了,可以立即判定结果就是False
1 > 2 and ... and ... and ...
2.or链接多个条件,会按照从左往右的顺序依次判断,一旦某个条件为True则无需继续往后判断了,可以立即判定结果就是True
2 > 1 or ... or ... or ...
3.混用是有优先级之分的,但日常使用中我们通常使用()来实现优先级的判断,
(3 > 4 and 4 > 3) or (1 == 3 or 3 > 3)
4.6 - 成员运算
判断是否存在于某个数据内
names = ['jason','oscar','sean','tank']
print('jason' in names) # True
print('jason' not in names) # False
4.7 - 身份运算
1.使用' == '判断值是否相等
print(m == n) # 判断两个变量的值是否相等
2.使用 'is' 判断内存地址是否相等(身份运算)
m = [111,222,333,444]
n = [111,222,333,444]
print(m is n) # 判断两个变量名指向的内存地址是否相同 False
5 - 流程控制(语法)
5.1 - 顺序结构
Python中通过简单的缩进[Tab]实现从属关系的确认
同级的内容通过缩进相同即可
简单的顺序关系直接同缩进写下去即可:
a = 1
b = 2
c = 3
5.2 - 分支结构
Python中分支结构一般通过if else elif语句实现
1.单分支判断
if 条件1:
操作1
2.双分支判断
if 条件1:
操作1
else:
操作2
3.多分支判断
if 条件1:
操作1
elif 条件2:
操作2
elif 条件3:
操作3
else:
操作4
5.3 - 循环结构
1.while循环:
(1)while + 条件 (基础条件循环)
cnt = 0
while cnt < 10:
cnt += 1
(2)while + break (使用break终止循环)
while True:
if 条件1:
break
(3)while + continue (使用continue跳过本次循环的部分内容)
cnt = 0
while cnt < 10:
if 条件1:
continue
cnt += 1;
(4)while + while (while嵌套)
i,j = 0
while i < 10:
while j < 10:
j += 1
i += 1
2.for循环
(1)for + range
for i in range(1,6) 循环[1,6)
(2)for + list/tuple...
l = [1,2,3,4,5,6]
for i in l
(3)for + break / continue / for / while
同while
6 - 数据类型的内置方法
6.1 整数型int/浮点型float
res = int('123') # 字符串强制转化为int类型
res = float('12.12') # 字符串强制转化为float类型
6.2 - 字符串str
1.任何类型的数据都能强转为str
res = str([12,3,4]) # 列表转字符串
res = str(123) # 整数转字符串
res = str({'username':'jason'}) # 字典转字符串
2.输出方式:
name = 'cbgpython'
print(name) # cbgpython
print(name[0]) # c
print(name[0:3]) # cbg
print(name[0:5:2]) # cgy
print(name[-1]) # n (相当于最后一个元素的下标,往前依次减小)
3.基本方法:
(1)长度方法
res = "cbg|python|like|c++|ac"
len(res) # 返回字符串的长度
print(len(res)) # 22
(2)移除方法
res = "|||AC|||"
res.strip() # 移除首尾指定字符,无参时为空格
print(res.strip('|')) # AC
res.lstrip() # 移除首指定字符,无参时为空格
print(res.lstrip('|')) # AC|||
res.rstrip() # 移除尾指定字符,无参时为空格
print(res.rstrip('|')) # |||AC
(3)分割方法
res = "cbg|python|like|c++|ac"
res.split() # 以指定字符分割字符串,得到一个字符串列表,无参时为空格
print(res.split('|')) # ['cbg','python','like','c++','ac']
res.split(' ',maxsplit = 1) # 从左往右切割字符串,第二个参数为分割次数
print(res.split('|',maxsplit = 1)) # ['cbg','python|like|c++|ac']
res.rsplit(' ',maxsplit = 1) # 从右往左切割字符串,第二个参数为分割次数
print(res.rsplit('|',maxsplit = 1)) # ['cbg|python|like|c++','ac']
(4)转化方法
res = "aC aC aC"
res.lower() # 字符串全部转为小写 'ac ac ac'
res.upper() # 字符串全部转为大写 'AC AC AC'
res.title() # 字符串全部转为首位大写 'Ac Ac Ac'
res.capitalize() # 字符串首字母大写 'Ac ac ac'
res.swapcase() # 字符串大小写反转 'Ac Ac Ac'
(5)插入方法
res = 'hello'
print('%'.join(res)) # h%e%l%l%o 默认每个字符中间插入
res1 = ['jason','18','read']
print('$'.join(res1)) # jason$18$read 默认每个元素中间插入,需要纯字符串列表,有数字会报错
(6)替换方法
res.replace('tank','jason')) # 替换全部的tank
res.replace('tank','jason',1)) # 替换从左往右第一个tank
(7)计数方法
res.count('m')) # 统计字符出现的次数
res.count('m',1,6)) # 统计字符在规定的索引范围内出现的次数
(8)填充方法
res.center(35,'$')) # 头尾填充指定字符至字符串总长度为35
res.ljust(35,'&')) # 尾部填充指定字符至字符串总长度为35
res.rjust(35,'#')) # 头部填充指定字符至字符串总长度为35
res.zfill(35)) # 头部填充字符'0'至字符串总长度为35 zerofill
4.判断方法:
(1)判断首尾
res.startswith() # 判断该字符串开头是否为指定字符,返回值为布尔值
res.endswith() # 判断该字符串末尾是否为指定字符,返回值为布尔值
(2)判断数字
res.isdigit() # 判断字符串是否为纯数字
res.isdecimal() # 判断字符串是否只包含十进制数字
res.isnumeric() # 判断字符串是否只含有数字 罗马数字,汉字数字皆可
(3)判断字符
res.islower()) # 是否全为小写
res.isupper()) # 是否全为大写
res.isspace()) # 是否全为空格
5.格式化方法:
(1)类似于%s
res = 'my name is {} and my age is {}'
print(res.format('jason',18)) # my name is jason and my age is 18
(2)方式2 按照指定的索引放值
res = 'my {1} name is {0} and my {0} age is {1} {0}'
print(res.format('jason',123)) # my 123 name is jason and my jason age is 123 jason
(3)方式3 指名道姓
res = 'my {name} name {age} is {name} and my {name} age is {age}'
print(res.format(name='jason',age=18))
6.3 - 列表list
1.基本方法:
(1)索引取值、索引改值、切片操作、步长、长度同字符串str
(2)插入方法
res.append(777) # 尾部插入整数
res.append([777,888,999]) # 尾部插入列表(可以插入任意元素)
res.insert(index,element) # 指定索引插入指定元素
res.extend(list) # 尾部扩展指定列表
(3)删除方法
del res[index] # 删除指定索引的元素
res.remove() # 删除所有指定元素
res.pop(index) # 删除指定索引的元素,无参则默认删除末尾元素
res.clear() # 直接清空所有元素
(4)顺序方法
res.reverse() # 翻转列表内所有元素
res.sort() # 排序列表内所有元素
(5)比较方法
直接使用 '<' '<=' '==' '>' '>=' 进行比较,返回布尔值
按照索引从小到大依次比较,比出大小之后直接输出结果
(6)计数方法
res.count() # 记录指定元素出现的次数
6.4 - 元组tuple
1.基本方法:
(1)索引取值、索引改值、切片操作、步长、长度、计数、同列表list
(2)res.index() 获取指定元素的下标
6.5 - 字典dict
2.基本方法:
(1)长度同列表list
(2)赋值/插入方法
直接使用res['element']的方式赋值或修改权值 # 有则修改,无则添加
res.update() # 插入指定键值对,有则修改value,无则添加
res.fromkeys(list,value) # 快捷赋值,给list内每个元素作为key与指定的value建立键值对
(3)删除方法
res.pop() # 删除指定元素对应的键值对
res.popitem() # 随机删除某个简直对
(4)取值方法
res['element'] # 按key取值 (dict是无序的,所以不能根据索引取值)存在则返回value,不存在则报错
res.get('element') # 用get取值,存在则返回value,不存在则返回None
res.keys() # 返回整个字典所有的key
res.values() # 返回整个字典所有的value
res.items() # 返回整个字典所有的键值对
res.setdefault(key,value) # 找到键值则返回value,没有找到则添加该键值,并设置value为指定的value
6.6 - 集合set
1.基本方法:
(1)插入方法
res.append() # 插入某个指定元素,set是无序的,所以可能在尾部
(2)交叉运算
res = s1 | s2 # 求合集
res = s1 & s2 # 求交集
res = s1 ^ s2 # 求对称差集
res = s1 - s2 # 求s1对s2的差集,即s1独有的元素
res = s2 - s1 # 求s2对s1的差集,即s2独有的元素
s1 > s2 # 求父集,看是否存在包含关系
(3)去重方法
s = set(list)
(1)只针对不可变类型
(2)去重后失去原有的顺序
7 - 底层知识基础
7.1 - python垃圾回收机制
"""
解释器在执行到定义变量的语法时,会申请内存空间来存放变量的值,而内存空间有限的
这就涉及到变量值所占用的内存空间回收的问题
当一个变量值没有用了,就应该被回收释放内存资源
由于变量名是访问到变量值的唯一方式所以当一个变量值不再关联任何的变量名的时候,我们就无法访问到该值了,该值就没有用了就应该被当成垃圾回收掉
毫无疑问内存空间的申请和回收是非常消耗精力而且有一定的风险
处理不当可能会导致内存溢出等问题
好在Cpython解释器提供了自动的垃圾回收机制(GC)
"""
垃圾回收机制主要有三种方式
1.引用计数
2.标记清除
3.分代回收
1.引用计数
变量值被变量名关联的次数
age = 18
18身上的引用计数为1 当前计数为1
m = age
18身上的引用计数加1 当前计数为2
del m
del的意思是解除变量名m与变量值18的关联关系
18身上的引用计数减1 当前计数为1
一旦变量值18身上的引用计数为0 那么垃圾回收机制就会自动回收18
ps:扩展知识点 循环引用的问题
2.标记清除
就是为了解决循环引用带来的问题
堆区和栈区
当内存占用率过高的时候 解释器会立刻停止程序的运行
从头到位将程序中所有的值扫描一遍 计算出值身上的引用计数 打上不同的标记
之后一次性清除掉所有标记为引用计数0的数据
3.分代回收
垃圾回收其实也是需要消耗资源的 因为每次工作都需要将所有对象的引用计数遍历一遍
这是非常消耗时间的,所以引入了分代回收的机制来提高回收效率
分代回收采用的是用
"空间换时间"的策略
核心思想:在历经多次扫描之后 都没有被回收的变量 垃圾回收机制会认为该变量是常用变量,所以垃圾回收之后对改变了的扫描频率会降低
参考图解
青春代
年轻代
老年代
7.2 - 字符编码
1.字符编码定义:
人类能够读懂的字符 转换 二进制数据
翻译的过程必须参照一个特定的标准 该标准称之为字符编码表,该表存放的就是字符与数字的对应关系
2.字符编码发展史:
(1)一家独大
计算机是起源于美国,所以最先考虑仅仅是计算机识别英文字符,于是就诞生了ASCII表
1.只有英文字符与数字的对应关系
2.一个英文字符对应1bytes
1bytes = 8bit(2的八次方)
8bit最多包含256个数字即对应256个字符
足够表示所有的英文字符,其实2的7次方就已经完全能够表示所有的英文字符,当初为了留有余地特定空了一位
(2)群雄割据
为了让计算机能够识别中文和英文 中国人定制了GBK
1.只有中文字符、英文字符与数字的对应关系
2.一个英文字符照样对应1bytes
一个中文字符则需要用2bytes
65535个字符
同理日本人 shift_JIS
1.只有日文字符、英文字符与数字的对应关系
同理韩国人 Euc-kr
1.只有韩文字符、英文字符与数字的对应关系
"""
如果有一个文件里面即有中文又有日文又有韩文...
那么该文件无论使用哪国的编码都会出现“乱码”的现象
"""
(3)天下一统
我们需要做到让计算机能够允许我们输入万国字符均可识别不乱码
万国码 unicode 1994才诞生
1.存在所有语言中的所有字符与数字的对应关系 即兼容万国字符
2.与其他编码的二进制数据也有对应关系
英文字符 unicode ASCII数字
中文字符 unicode GBK数字
...
1.unicode在存取数据的时候统一都是采用2bytes来存储,这样的话会导致一个纯英文的文件占用比原来多一倍的硬盘空间
2.数据IO耗时增加
utf-8是unicode的一个优化版本,是不定长的
1.英文字符 1bytes
2.中文字符 3bytes 生僻字更多的bytes
内存里面使用的是
unicode
硬盘里面的使用是
utf-8
假设:当所有其他编码的软件都消失之后,可以考虑内存硬盘统一使用utf-8(XXX)编码
3.编码与解码:
encode 与 decode
res = s.encode('utf-8') # 字符串转bytes
res1 = res.decode('utf-8') # bytes转对应数据
(1)定义bytes类型
data = b'cbg'
(2)转字符串
data = str(data,decoding = 'utf-8')
(3)转bytes类型
data = bytes(data,encoding = 'utf-8')
4.文件头的概念
coding:utf8
接下来读取这个文件内容的时候采用coding后面指定的编码格式读取
5.在python2和python3中的区别
python2默认使用ascii
(1)加文件头 强制修改编码
coding:utf-8 # 一般情况下为了兼容不同版本 py文件都可能会加文件头
(2)在字符串的前面加一个u
a = u'阿斯顿哈说' # 将字符串按照unicode存储
python3默认使用unicode
python3中则无需加u