记录小白入门安全开发的学习笔记,供日后回顾。
本文仅展示了部分python语法,后续写代码会用到,没涉及到的大家可以自行搜索。
变量
变量名相当于门牌号,指向值所在的内存地址,是访问到值的唯一方式。
变量的值就是我们存储的教据。
定义变量的本质就是申请在内存中开辟一块空间存放变量值。不同的变量名可能绑定的内存地址不同,可用id()查看变量值的内存地址。用is比较左右两边的id是否相等。比如:
x = '100'
y = x
print(x is y) # True
变量名的命名规范
变量名只能由 字母、数字、下划线 组成,不能以数字开头。
python中的变量一般用小写字母+下划线命名。比如:full_url
常量
常量就是程序运行过程中固定的、不被改变的量。python中,一般用全部大写的英文单词代表常量。比如:SEM
基本数据类型
集合
例:set = {1, 2, 3, 4, 5}
集合是把一堆值集中在一起来做一个整体方面的操作 , 如关系运算、去重(换句话说:集合内不会出现重复的元素)等。
类型转换
set()
方法
去重
只能对不可变的变量类型去重,比如:整数(int)、浮点数(float)、字符串(str)、元组(tuple),且无法保证原来的顺序。
列表(list)、字典(dict)、集合(set)属于可变变量,不能作为集合的元素
l = [
{'name': 'alex'},
{'name': 'tom'},
{'name': 'fangfang'},
{'name': 'tom'},
]
new_l = []
for item in l:
if item not in new_l:
new_l.append(item)
print(new_l) # [{'name': 'alex'}, {'name': 'tom'}, {'name': 'fangfang'}]
字典
例:dic = {'name':'alex','age':18}
字典不能通过索引取值,是无序的。字典中的每一个值都有一个唯一的key与其对应。
类型转换
dict()
# 1.直接手写
d = {'k1': None, 'k2': None, 'k3': None}
# 2.循环增加
keys = ['k1', 'k2', 'k3']
d1 = {}
for key in keys:
d1[key] = None
print(d) # {'k1': None, 'k2': None, 'k3': None}
# 3.利用内置的fromkeys方法 (了解)
d2 = dict.fromkeys(keys, None) # 内部就是上面的for循环
print(d2) # {'k1': None, 'k2': None, 'k3': None}
内置方法
1. 按照key存取值:可存可取
d = {'k1':1}
# 针对赋值操作key存在,则修改
d['k1'] = 22
print(d) # {"k1":22}
# 针对赋值操作key不存在,则创建新值(有则修改,无则增加)
d['k2'] = 333
print(d) # {'k1':22,'k2':333}
2. 删除
#通用删除
d = {'k1':1,'k2':2,'k3':33}
del d['k1']
print(d) # {'k2':2,'k3':33}
#pop删除: 根据key删除元素,返回删除key对应的value值
d = {'k1':1,'k2':2,'k3':33}
print(d.pop('k2')) # 2
print(d) # {'k1':1,'k3':33}
#popitem删除: 随机删除,返回一个元组(删除的key,value)
d = {'k1':1,'k2':2,'k3':33}
res = d.popitem()
print(res) # ('k3',33)
print(d) # {'k1':1,'k2':2}
3. 键keys( ) 值values( ) 键值对items( )
d = {'k1':1,'k2':2,'k3':33}
print(d.keys(),type(d.keys())) # dict_keys(['k1', 'k2', 'k3']) <class 'dict_keys'>
print(d.values()) # dict_values([1, 2, 33])
print(d.items()) # dict_items([('k1', 1), ('k2', 2), ('k3', 33)])
4. for循环
d = {'k1': 1, 'k2': 2, 'k3': 33}
for key in d.keys():
print(key) # k1k2k3
for k in d:
print(k) # k1k2k3
for v in d.values():
print(v) # 1233
for k, v in d.items():
print(k, v) # k1 1k2 2k3 33
5. 清空字典: clear( )
d = {'k1':1,'k2':2,'k3':33}
d.clear()
print(d) # {}
6. get( )
通过get(key),获取字典中key对应的值 ,不存在默认返回None
d = {'k1':1,'k2':2,'k3':33}
print(d.get('k1')) # 1
print(d.get('k5')) # None
字符串
例:str = "1234"
类型转换
把任意其他类型都转成字符串:str()
内置方法
1. 按照索引取值
msg = "lxx love npy"
# 正向取
print(msg[0]) # l
print(msg[5]) # o
# 反向取
print(msg[-1]) # y
2. 切片
msg = "lxx love npy"
# 顾头不顾尾
res = msg[0:3] # lxx
print(res)
3. 步长
msg = "lxx love npy"
res = msg[0:7:2]
print(res) # lxlv
4. 反向步长
msg = "lxx love npy"
res = msg[0:7:-1]
print(res) # 空,因为切片和步长的方向不一致
res = msg[7:0:-1]
print(res) # evol xx
5. 倒转字符串
msg = "lxx love npy"
msg1 = msg[::-1]
print(msg1) # 'ypn evol xxl'
6. 计算长度:len
msg = "lxx love npy"
print(len(msg)) # 12
7. 移除字符串左右两侧的符号:strip
strip只去除两边的字符,不能去除中间的
# 默认去掉空格
name = " alex "
new_name = name.strip()
print(new_name) # 'alex'
# 指定去除符号
msg = "***好吧***"
new_msg = msg.strip("*")
print(new_msg) # 好吧
# 设置多个去除符号
msg = "*()-=alex+++*&^"
new_msg = msg.strip("*()-+=&^")
print(new_msg) # alex
lstrip rstrip
msg = "***alex***"
print(msg.strip("*")) # alex
print(msg.lstrip("*")) # alex***, 只去除左边
print(msg.rstrip("*")) # ***alex,只去除右边
8. 分割split
把字符串按照某种分割符进行切分 , 得到一个列表
info = "alex 20 男"
# 默认按照空格分割
lst = info.split()
print(lst) # ['alex','20','男']
# 指定分隔符
info = "alex:20:男"
lst = info.split(":")
print(lst) # ['alex','20','男']
# 指定分割的次数, 默认是全部分割 (了解)
info = "alex:20:男"
lst = info.split(":", 1)
print(lst) # ['alex','20:男']
split rsplit
# 默认切分是从左到右,rsplit是从右向左,只有当指定分割次数的他们两个的区分才能看出啦
msg = 'alex:男:21'
print(msg.split(':',1)) # ['alex', '男:21']
print(msg.rsplit(":",1)) # ['alex:男', '21']
9. 大小写转换 lower upper
msg = 'aaaBBccDD'
print(msg.lower()) # aaabbccdd,大写转小写
print(msg.upper()) # AAABBCCDD,小写转大写
10. startswith endswith
msg = 'lxx love npy'
print(msg.startswith('alex')) # 判断是否以什么开头
print(msg.endswith('hgn')) # 判断是否以什么结尾
11. format的三种方式
m = "lxx"
n = "npy"
print('{} love {}'.format(m, n))
print('{0} love {1}'.format(m, n))
print('{m} love {n}'.format(m=m, n=n))
12. 将列表转化为字符串:join
lst = ['alex','21','男']
print(':'.join(lst)) # alex:21:男
13. replace 替换
msg = "**alex**"
new_msg = msg.replace('*','=') # replace(待替换的字符,替换成的字符,替换次数(默认所有))
print(new_msg) # '==alex=='
14. isdigit
# 判断字符串是否全部由数字组成
print('123'.isdigit()) # True
print('12.3'.isdigit()) # False
15. count 计数
# 统计小字符串在大字符串中出现的次数
msg = 'lxx love npy'
print(msg.count('y')) # 1
print(msg.count('alex')) # 0
列表
例:lst = ['Tom', 18,'游泳' ]
列表与字符串相比:根据索引取值,取值方便, 更利于我们操作。
类型转换
把能够被for循环遍历的类型转换成列表:list( )
res = list("hello")
print(res) # ['h','e','l','l','o']
res1 = list({'k1':1,'k2':2})
print(res1) # ['k1','k2']
内置方法
1. 索引取值
l = [1, 2, 3, 'alex']
# 正向取
print(l[1]) # 2
# 反向取
print(l[-1]) # alex
# 可以取也可以改
# 索引存在则修改对应的值
l[2] = 999
print(l[2]) # 999
# 索引不存在,无论是取还是修改都会报错
l[5] = 555
print(l)
2. 切片
l = [1, 2, 3, 'alex']
print(l[0:3]) # [1,2,3]
print(l[:]) # 切片等同于拷贝行为,而且相当于浅拷贝:[1, 2, 3, 'alex']
print(l[::-1]) # 列表倒序:['alex', 3, 2, 1]
3. 长度 len
l = [0,1,2,3,4]
print(len(l)) # 5
4. 在列表的末尾追加值:append
l = [11,'alex',666]
l.append(333)
print(l) # [11,'alex',666,333]
5. insert 插入
当索引大于当前列表最大索引时,默认插入到列表末尾
l = [11, 'alex', 666]
l.insert(1, 'alex')
print(l) # [11,'alex','alex', 666]
l.insert(-1, 'wusir') # 如果索引是负的,那么追加的值的位置是向左偏移一个单位.
print(l) # [11, 'alex', 'alex', 'wusir', 666]
6. extend 迭代添加
l = [11, 'alex', 666]
l1 = [99,88,77]
l.extend(l1)
print(l) # [11, 'alex', 666,99,88,77]
7. 删除
# 方式1: del 通用的删除方法,没有返回值
l = [11, 'alex', 666]
del l[1]
print(l) # [11, 666]
# 方式二:l.pop() 根据索引删除,会返回删除的值
l = [11, 'alex', 666]
res = l.pop() # 不指定索引默认删除最后一个
print(res) # 666
print(l) # [11, 'alex']
# 方式三:l.remove() 根据元素删除,返回None
l = [11, 'alex', 666]
l.remove('alex')
print(l) # [11, 666]
8. 统计元素在列表中出现的次数:count( )
l = [11, 22, 11, 22, 'alex']
print(l.count(11)) # 2
9. 返回元素在列表中首位索引:index( )
l = ['alex',18]
print(l.index('alex')) # 0
print(l.index('mn')) # 找不到报错
10. 清空列表:clear( )
l = [1, 2, 3, 4]
l.clear()
print(l) # []
11. 列表倒序
l = [11, 22, 11, 22, 'alex']
l.reverse()
print(l) # ['alex',22,11,22,11]
12. 排序:sort( )
列表内的元素必须是同种类型才可以排序
l = ['alex', '123', 'haha'] # 字符串比大小,按照对应的位置的字符依次pk,一旦有结果就停止pk,字符串的大小按照ASCII码表的先后顺序区别字符大小
l.sort() # 默认从小到大排,升序
print(l) # ['123', 'alex', 'haha']
l.sort(reverse=True) # 从大到小,降序
print(l) # ['haha', 'alex', '123']
print('a' > "A") # True
元组
例:t = (1,2,3)
(如果元组中只有一个元素,必须加逗号)
元组就是"一个不可变的列表"
类型转换
把能够被for循环的数据类型转换成元组:tuple()
print(tuple('hello')) # ('h','e','l','l',o)
print(tuple(['hello'])) # ("hello",)
print(tuple({'hello':1})) # ("hello",)
方法
1. 索引取值
t = (1, 2, 3, 'alex')
# 正向取
print(t[1]) # 2
# 反向取
print(t[-1]) # "alex"
2. 切片
t = (1, 2, 3, 'alex')
print(t[0:3]) # (1,2,3)
print(t[:]) # 切片等同于拷贝行为,而且相当于浅拷贝
print(t[::-1]) # 元祖倒叙
3. count&index
t = (1,2,3)
print(t.count(1)) # 1
print(t.index(1)) # 0
4. 长度 len
tu = (1,2,3,4)
print(len(tu)) # 4
用户交互
python3
接收用户的输入:input
在python3中,无论用户输入什么,input都会把它放到一对引号中, 即把原数据类型转换成了字符
串类型。所以如果想要进行四则运算,输入了int类型,就要手动转换类型(int()
)。
python2
- raw_input ( )
python2中raw_input ( )
等同于python3中的input , 都会把用户输入的内容转化成字符串。
- input ( )
python2中的input ( ),不会自动更改用户输入内容的数据类型, 输入的什么类型,就返回什么类型的内容。
格式化输出
% 格式化
# %s 接收任意类型
name = 'alex'
info = '大家好我叫%s' % name
print(info) # 大家好我叫alex
# %d 接收int类型
print('我的年龄是%d' % 18)
# %f 接收float类型
print('我的体重是%fkg' % 55.7)
format ( ) 格式化
一般情况
res = '我叫{},今年{}岁'.format('tom',18) #通过位置一一对应
print(res)
通过索引
res = '我叫{1},今年{0}岁'.format(18,'tom') #通过索引一一对应
print(res)
通过key=value
res = '我叫{name},今年{age}岁'.format(name='tom',age=18) #通过key=value一一对应
print(res)
f 格式化
python3.5以后出现
name = input('请输入名字:')
age = input('请输入年龄:')
res = f'你的名字是{name},年龄是{age}岁'
print(res)
三种格式化之间的速度
f 格式化 > format( ) 格式化 > % 格式化
运算符
赋值运算符
交叉赋值
x = 10
y = 20
x, y = y, x
print(x) # 20
print(y) # 10
解压赋值个人中心
x,y = [10,20]
print(x) # 10
print(y) # 20
成员运算符
成员运算符就是判断是否存在, 返回一个布尔值。
in
# 判断一个小字符串是否在一个大字符串中
print( 'x' in 'zhenxiang' ) # True
# 判断元素是否存在于列表
print( 10 in [11,10,12]) # True
# 判断key是否存在于字典
print('k1' in {'k1':1}) # True
not in
print( 'mn' not in 'hello word') # True
身份运算符
判断对象在内存中的地址是否相同(即id()
值是否相同)
is
x = 'hello alex'
y = 'hello alex'
print(x is y) # True
# 有时候值相等id未必相等
is not
流程控制
if判断
0,None,空(空字符串,空字典,空列表. . . )代表的布尔值都是False
while循环
while + continue
while + else
当while 循环正常执行完并且中间没有被break 中止的话,就会执行else后面的语句,我们可以用else来验证循环是否正常结束。
while 条件:
代码1
代码2
...
else:
代码3
for循环
for 变量名 in 可迭代对象: # 可迭代对象可以是 字符串, 列表, 字典, 元组, 集合 等...
代码1
代码2
代码3
...
for + range
range顾头不顾尾
range(stop) -> range object
结束
range(start, stop[, step]) -> range object
开始 结束 步长
文件操作
文件的操作模式
控制文件操作的三种模式
r :只读模式(默认的操作模式)
当文件不存在时,会报错。
使用r模式,会一次性把文件内容全部从硬盘加载到内存中。当我们要读取大文件时,使用该模式会撑爆内存。
w :只写模式
当文件存在时,w模式会先清空原来的内容,再写内容。当文件不存在时,会自动在该路径创建一个新的文件。
但与覆盖模式不同的是:w模式在没有关闭的情况下,连续写入内容,不会清空之前的内容,而是会紧跟在旧的内容后面。
a 只追加写模式
当文件不存在时,会创建新文件。当文件存在时,a模式打开文件,不会清空原文件的内容,指针会自动移到文件末尾,在末尾追加要写入的内容。
控制文件内容的两种模式
t(默认的 , 一般不写 ):文本模式
- 读写文件都是以字符串( unicode )为单位的
- 只能针对文本文件
- 必须指定encoding参数
b:二进制模式
- 读写文件都是以bytes/二进制为单位的
- 可以针对所有文件
- 一定不能指定encoding参数
如果是二进制/bytes文件(一般是一些音频文件或者视频文件),则r/w/a后需加一个“b”
打开文件
open("文件路径")
取消转义
比如文件路径为:D:\Python课程\nday03
路径分隔符为反斜杠(\),但“\”有转义作用,比如文件路径中存在\n
,表示换行。
print("D:\pypractice\nday03")
#D:\pypractice
#day03
有三种方法取消转义:
- 字符串前+r,eg: r"C:\a\b\nb\d.txt"
- 用斜杠(/)代替反斜杠(\)
open()自动会把斜杠(/)替换成反斜杠(\)
- 使用双反斜杠(\\)
操作文件
# 1. 打开文件,由应用程序向操作系统发起系统调用open(...)
# 操作系统打开该文件,返回一个文件对象并将其赋值给一个变量f
f=open('a.txt',mode='r',encoding='utf-8') #默认打开模式为r模式
# 2. 调用文件对象的读/写方法,会被操作系统转换为读/写硬盘的操作
data=f.read() # 读取文件内容,将硬盘中的二进制数据读取到内存中 --> 文本模式将二进制转换成字符
关闭文件
打开一个文件包含两部分资源:应用程序的变量 f 和操作系统打开的文件。在操作完毕一个文件时,必须
把该文件的这两部分资源全部回收,回收方法为:
f.close() #回收操作系统打开的文件资源,一旦关闭就不能操作了,但 f 变量还在
del f #回收应用程序级的变量,一般我们不用写。
with上下文管理器
with语句的代码块执行完毕后会自动执行f.close()
with open('2.txt', mode='r', encoding="u8") as f1:
res = f1.read() # 读取文件内容,硬盘的搬运工
print(res)
u8为utf-8的简写
循环读取文件的两种方式
for循环
# t模式
with open('b.txt', mode='r', encoding='utf-8') as f:
for line in f:
print(line)
# b模式
with open('b.txt', mode='rb') as f:
for line in f:
print(line)
while循环
# t模式和b模式都适用
with open('b.txt', mode='rb') as f:
while 1:
content = f.read(1024) # 可以指定读取文件内容的大小,以字节为单位
if not content:
break
print(content)
f 的常用方法
# 读操作
f.read() # 读取所有内容,执行完该操作后,文件指针会移动到文件末尾
f.readline() # 读取一行内容,光标移动到第二行首部
f.readlines() # 读取每一行内容, 每一行的内容作为一个元素存放于列表中
# f.read()与f.readlines()都是一次性读入内容,如果内容过多会导致内存溢出,若还想将内容全读入内存,则必须分多次读入,有两种实现方式:
# 方式一
with open('a.txt', mode='rt', encoding='utf-8') as f:
for line in f:
print(line) # 同一时刻只读入一行内容到内存中
# 方式二
with open('1.mp4', mode='rb') as f:
while True:
data = f.read(1024) # 同一时刻只读入1024个Bytes到内存中
if len(data) == 0:
break
print(data)
# 写操作
f.write('1111\n222\n') # 针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8')) # 针对二进制模式写,需要自己写换行符
f.writelines(['333\n', '444\n']) # 迭代的将列表的元素写入文件
f.writelines([bytes('333\n', encoding='utf-8'), '444\n'.encode('utf-8')]) # b模式(二进制模式)
函数
def 函数名(参数1, 参数2, ...):
"""文档描述"""
函数体
return 值
# def是关键字,return是返回值
三种定义形式
无参函数
def func():
print('无参函数')
func()
有参函数
def func(x, y):
print(x, y)
func(1, 2)
空函数
def func():
pass
func()
形参和实参
形参
函数定义阶段定义的参数叫做形式参数,简称形参
def func(x): # x就是形参
print(x)
实参
在函数调用阶段传入的值称之为实际参数,简称实参
def func(name):
print(f'我的名字是{name}')
func('tom') # 'tom'就是实参
三种参数
位置参数
- 位置参数:按照从左到右的顺序依次定义的参数
- 位置形参 : 在函数定义阶段,按照从左到右的顺序直接定义"变量名"
特点 : 必须传值,多一个少一个都不行
- 位置实参 : 在函数调用阶段,按照从左到右的顺序依次传入值
特点 : 按照顺序与形参一 一对应
关键字参数
- 关键字实参:在函数调用阶段,按照key=value的形式传入的值
特点:指名道姓给某个形参传值,可以完全不按照顺序
- 位置参数和关键字参数混合使用:
位置实参必须放在关键字实参前面
不能为同一个形参重复传值
默认值参数
默认形参:在函数定义阶段就已经被赋值的形参
特点:在函数定义阶段就已经被赋值,意味着在调用阶段可以不用为其赋值,也可以赋值改变默认值
混合使用:
位置参数必须在默认值参数前面
可变长度参数(*与**)
可变长度的位置参数
*形参名: 用来接收溢出的位置实参 , 溢出的位置实参会被 * 保存成 元组 的格式。星号后面的形参名可以是任意名字,一般为args , 即 *args。
def func(x, y, *z):
print(x, y, z) # 1 2 (3,4,5)
func(1, 2, 3, 4, 5)
实参中带*:星号后面的值会被打散成位置参数
def func(x, y, z):
print(x, y, z)
func(*[1, 2, 3]) # func(1,2,3)
可变长度的关键字参数
**形参名:用来接收溢出的关键字实参 , 溢出的关键字实参会被 ** 保存成 字典 的格式
形参名:**号后面的形参名可以是任意名字,一般为kwargs , 即 **kwargs
def func(x, y, **kwargs):
print(x) # 1
print(y) # 2
print(kwargs) # {'z':3,'a':4}
func(1, y=2, z=3, a=4)
实参中带** , 在**号后面的值会被打散成关键字参数:
def func(x, y, z):
print(x, y, z) # 1 2 3
func(**{"x": 1, "y": 2, 'z': 3})
混用*和**
*args必须放在**kwargs之前
def func(*args, **kwargs):
print(args) # (1, 2, 3, 4, 5)
print(kwargs) # {'x': 1, 'y': 2, 'z': 3, 'c': 5}
func(1, 2, 3, 4, 5, x=1, y=2, z=3, c=5)
匿名函数
使用lambda
关键字创建匿名函数:lambda 参数1,参数2 : 返回值
匿名函数使用一次就释放,用于临时使用一次的场景,通常与其他函数配合使用。
比如:
salary_dic = {'tom': 100, 'alex': 500, 'jack': 200}
res = max(salary_dic, key=lambda k: salary_dic[k])
print(res) #alex
salary_dic = {'tom': 100, 'alex': 500, 'jack': 200}
res2 = sorted(salary_dic, key=lambda k: salary_dic[k])
print(res2) # ['tom', 'jack', 'alex']
异常处理
try:
x = 1
except Exception as e:
pass
print(1)
包裹在try里面的代码是可能出错的代码 , 比如网络请求失败 。
except 下面的代码就是当try里面的代码出错了 , 才会运行里面的代码 , 正常情况下是不会运行的 ,一般都是一些日志记录代码 , 或者是提示用户程序报错的代码。
如有错漏,欢迎指正。