Python基础

 

注释 :

单行注释 #

多行注释 “”“ ”“”

输入输出:

input()输入

print()输出

print(“my name is %s my age is %s” % (“梨花”,”18″))

时间:显示当前时间:time.strftime(“%Y-%m-%d %H:%M:%S”)

休眠:time.sleep(n)

time.time()计算时间间隔

  1. 对象.__class__.__name__当前类的名字
    对象.__class__对象的类
    类.__name__类的名字

os模块:

  1. os.path.dirname(__file__)当前文件的上一个文件夹
    os.listdir(文件夹路径)------->获取文件夹中所有文件的名字,扔进一个列表
    os.remove()删除文件
    os.rename()文件改名

枚举:enumerate(good_list)

  1. 枚举 enumerate(good_list) ----> return (good_list的索引, 索引对应的值)
  1. str = “[1,2,3]”
    evalstr):把引号里的数据拿出来运行
  1. sys.path.append()添加环境变量
  1. issubclass() 这个内置函数可以帮我们判断x类是否是y类型的子类
    isinstance可以判断x是否是y类的对象,isinstance可以判断该对象是否是家族体系中的(只能往上判断类)

 

dict—》json.str—–》f.write(json.str)——>json文件中

将字典转化为json字符串,然后再写进json文件中

  1. user_path = os.path.join(setting.DB_PATH,'%s.json'%username)
    #判断当前用户是否存在 os.path.exits(需要判断的文件路径)
    if os.path.exists(user_path):
    print("用户已存在,请登录")
    continue

    with open(user_path,'w',encoding="utf-8") as h:
    json.dump(user_dic,h)#先将字典转化为json,然后写
    json.load()将json字符串转化为python字符串

 

字母、数字、下划线组成,数字不能开头

命名风格:

纯小写+下划线 age_of

驼峰体

变量内存地址

1.等号比较的是值

2.is比较的是地址

地址相同,意味着值和类型相同

值相同type肯定也相同,但地址不一定

  • Numbers(数字)

int(整数类型)

long(长整数类型)

float(浮点型)

complex(复数)

  • String(字符串)

从左到右索引默认0开始的,最大范围是字符串长度少1

从右到左索引默认-1开始的,最大范围是字符串开头

  1. print str # 输出完整字符串
    print str[0] # 输出字符串中的第一个字符
    print str[2:5] # 输出字符串中第三个至第六个之间的字符串
    print str[2:] # 输出从第三个字符开始的字符串
    print str * 2 # 输出字符串两次
    print str + "TEST" # 输出连接的字符串
  • List(列表)

列表用 [ ] 标识

 

  1. list = [ 'runoob', 786 , 2.23, 'john', 70.2 ]
    tinylist = [123, 'john']

    print list # 输出完整列表
    print list[0] # 输出列表的第一个元素
    print list[1:3] # 输出第二个至第三个元素
    print list[2:] # 输出从第三个开始至列表末尾的所有元素
    print tinylist * 2 # 输出列表两次
    print list + tinylist # 打印组合的列表
    """
    ['runoob', 786, 2.23, 'john', 70.2]
    runoob
    [786, 2.23]
    [2.23, 'john', 70.2]
    [123, 'john', 123, 'john']
    ['runoob', 786, 2.23, 'john', 70.2, 123, 'john']
    """
  • Tuple(元组)

元组用 () 标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。

  • Dictionary(字典)

字典用”{ }”标识。字典由索引(key)和它对应的值value组成。

  1. tinydict = {'name': 'runoob','code':6734, 'dept': 'sales'}


    print dict['one'] # 输出键为'one' 的值
    print dict[2] # 输出键为 2 的值
    print tinydictitems() # 输出完整的字典
    print tinydict.keys() # 输出所有键
    print tinydict.values() # 输出所有值

整型

字符型

元组

列表

集合

字典

运算符 描述 实例
+ 加 – 两个对象相加 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
运算符 逻辑表达式 描述 实例
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

除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。

运算符 描述 实例
in 如果在指定的序列中找到值返回 True,否则返回 False。 x 在 y 序列中 , 如果 x 在 y 序列中返回 True。
not in 如果在指定的序列中没有找到值返回 True,否则返回 False。 x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。
  1. if 判断条件:
    执行语句……
    else
    执行语句……
  1. if 判断条件1:
    执行语句1……
    elif 判断条件2:
    执行语句2……
    elif 判断条件3:
    执行语句3……
    else:
    执行语句4……

while循环

  1. while 判断条件(condition):
    执行语句(statements)……

循环使用 else 语句

  1. count = 0
    while count < 5:
    print count, " is less than 5"
    count = count + 1
    else:
    print count, " is not less than 5"

for循环

  1. for letter in 'Python': # 第一个实例
    print("当前字母: %s" % letter)

    fruits = ['banana', 'apple', 'mango']
    for fruit in fruits: # 第二个实例
    print ('当前水果: %s'% fruit)

    print ("Good bye!")

通过序列索引迭代

  1. fruits = ['banana', 'apple', 'mango']
    for index in range(len(fruits)):
    print ('当前水果 : %s' % fruits[index])

    print ("Good bye!")
    #内置函数 len() 和 range(),函数 len() 返回列表的长度,即元素的个数。 range返回一个序列的数

循环使用 else 语句

  1. for num in range(10,20): # 迭代 10 到 20 之间的数字
    for i in range(2,num): # 根据因子迭代
    if num%i == 0: # 确定第一个因子
    j=num/i # 计算第二个因子
    print ('%d 等于 %d * %d' % (num,i,j))
    break # 跳出当前循环
    else: # 循环的 else 部分
    print ('%d 是一个质数' % num)

二者都用在while和for循环中

break退出最近的循环

continue跳过本次循环,运行下一次

pass 不做任何事情,一般用做占位语句。

  1. for letter in 'Python':
    if letter == 'h':
    pass
    print '这是 pass 块'
    print '当前字母 :', letter

    print "Good bye!"
    """
    当前字母 : P
    当前字母 : y
    当前字母 : t
    这是 pass 块
    当前字母 : h
    当前字母 : o
    当前字母 : n
    Good bye!
    """

del删除对象

  1. del var
    del var_a, var_b
函数 返回值 ( 描述 )
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的平方根
函数 描述
choice(seq) 从序列的元素中随机挑选一个元素,比如random.choice(range(10)),从0到9中随机挑选一个整数。
randrange ([start,] stop [,step]) 从指定范围内,按指定基数递增的集合中获取一个随机数,基数默认值为 1
random() 随机生成下一个实数,它在[0,1)范围内。
[seed(x]) 改变随机数生成器的种子seed。如果你不了解其原理,你不必特别去设定seed,Python会帮你选择seed。
shuffle(lst) 将序列的所有元素随机排序
uniform(x, y) 随机生成下一个实数,它在[x,y]范围内。
函数 描述
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) 将角度转换为弧度
常量 描述
pi 数学常量 pi(圆周率,一般以π来表示)
e 数学常量 e,e即自然常数(自然常数)。
  1. var1 = 'Hello World!'

    print "输出 :- ", var1[:6] + 'Runoob!'
    #输出 :- Hello Runoob!
转义字符 描述
(在行尾时) 续行符
\ 反斜杠符号 将符号变为普通符号
单引号
双引号
\a 响铃
\b 退格(Backspace)
\e 转义
\000
\n 换行
\v 纵向制表符
\t 横向制表符 和table类似
\r 回车 回到当前行的行首
\f 换页
\oyy 八进制数,y 代表 0~7 的字符,例如:\012 代表换行。
\xyy 十六进制数,以 \x 开头,yy代表的字符,例如:\x0a代表换行
\other 其它的字符以普通格式输出
操作符 描述 实例
+ 字符串连接 >>>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

优先:1、索引取值

.find(“n”)和.index(“n”) n的索引位置

2、切片 s[1:6:3] 开始,结束,步长

3、长度len(s)

4、成员运算in、not in

5、切分. split(“ ”,1)空格切分,切分次数 返回值是一个列表

6、移除左右两边空白.strip() .strip(“*”)去除左右两边的

7、“-”.join(list)拼接 “a-b-c”

需要掌握:

1、.lstrip()只去左边

.rstrip()只去右边

2、.lower() .upper()

变小写,变大写

.swapcase()大小写反转

.title() — 各个字符的首字母大写

.capitalize() — 首字母大写

3、.startswitch() .endswitch()

以什么开头,以什么结尾

4、.format() res = “my name is {},my age is {}”.format(name,age)

res = “my name is {0},my age is {1}”.format(name,age)

res = “my name is {x},my age is {y}”.format(x = name,y = age)

res = f“my name is {x},my age is {y}” {}不能有\或者# , %%取消百分号

5、.rsplit()从右边开始切分

6、.replice(“ ”,“-”)-替换空格

7、.isdigit()判断字符串是否是纯数字组成

用[]创建,=的时候是把地址给另一个了,.copy()的时候是重新复制了一份

查:用下标索引访问值 list[0],和string类型相似

增:使用.append(“abfh”)添加数据

插:使用.insert(1,“ahf”)插入数据

删:del list[0] 指定元素删除:.remove([0,2])

根据索引删:.pop(2)(有返回值)

改:list[1] = 100

统计长度:len(list)

in、not in:多层列表时,就看外层

全部删除:.clear()

统计元素出现次数:.count(22)

将列表元素取出添加:.extend(list)

索引位置:.index(22)

反转:.reverse()

排序:.sort() (列表中元素是同类型的)

不可变列表

定义方式:()

元组只有一个元素时,需要加,t =(1,)

切片:同列表

不可hash的:可变的

可hash的:不可变的

定义方式:{“name”:“哈哈哈”,“age”:15}

key需要用不可变的

造字典:

{}.fromkeys([“name”,”age”],111)—–>{“name”:1111,”age”:1111}

  1. # res = {}.fromkeys(['k1','k2','k3'],[])
    # # print(res) # {'k1': [], 'k2': [], 'k3': []}
    # res.get('k1').append(123)
    # print(res)

    #{'k1': [], 'k2': [], 'k3': []}
    #{'k1': [123], 'k2': [], 'k3': []}

1、.get():通过key获取value

  1. res = d.get('username', '你搞什么飞机 这个键不存在 去你妹啊')
    # print(res) # 键存在还是返回对应的值
    # res = d.get('xxx', '你搞什么飞机 这个键不存在 去你妹啊')
    # print(res) # 键不存在 返回get方法里面第二个参数

2、新增:

方法1:

  1. # d['hobby'] = 'study' # 字典的key不存在新增
    # print(d)
    # d['username'] = 'egon'
    # print(d) # 字典的key存在则修改

方法2:

  1. # d.update(username='jason')
    # print(d) # 特点同上

方法3:

键如果存在的情况下 那么不做修改 而是将对应的value取出 键如果不存在的情况下 那么就是新增

  1. # d.setdefault('xxx',123)
    # print(d) # 键不存在是新增
    # res = d.setdefault('username',123)
    # print(d) # {'username': 'jason', 'password': 123,'xxx',123}
    # print(res) # jason

字典方法三剑客

print(d.keys()) # 获取字典所有的key

print(d.values()) # 获取字典所有的value

print(d.items()) # 获取字典所有的key和value组织成小元组

序号 函数及描述
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() 返回并删除字典中的最后一对键和值。

按照key值存取值:

d={”k1“:11}

d[“k2”]=222

len(d)有多少个字典元素

in和not in:判断的是key值

删除:和列表相同

函数 描述
[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 转换为一个列表
set(s) 转换为可变集合
dict(d) 创建一个字典。d 必须是一个序列 (key,value)元组。
frozenset(s) 转换为不可变集合
chr(x) 将一个整数转换为一个字符
unichr(x) 将一个整数转换为Unicode字符
ord(x) 将一个字符转换为它的整数值
hex(x) 将一个整数转换为一个十六进制字符串
oct(x) 将一个整数转换为一个八进制字符串

 

1、作用:去重,集合内不能出现相同元素,集合内元素会自动去重

2、关系运算:

共同好友,共同关注

交叉并集

集合就是用上面两个功能,如果用不上,就不要用

定义:

s = {1,2,3,4}

1、集合内的元素必须是不可变元素

2、集合内的元素是无序的

3、定义空集合一定要用set关键字

4、能够被for循环的数据类型都能够被转成集合

  1. # s1 = set('egon is o DSB')
    # print(s1)
    # s2 = set([1,2,3,4,5,6,7,7,7,7,7])
    # print(s2)
    # s3 = set({'username':'jason','password':123})
    # print(s3) # {'password', 'username'}

添加元素:.add()整个添加

.update([ ])把元素拆分添加

删除元素:.remove()

.pop()删除最后一个元素

  1. # 用户1的好友列表
    friends1 = {'jason','tank','tony','jerry'}
    # 用户2的好友列表
    friends2 = {'jason','tony','owen','oscar'}

    # 1 求两个用户的共同好友 交集
    # res = friends1 & friends2
    # print(res) # {'jason', 'tony'}
    # 2 求两个用户所有的好友
    # res = friends1 | friends2
    # print(res) # {'jerry', 'jason', 'oscar', 'tony', 'tank', 'owen'}
    # 3 求用户1独有的好友
    # res1 = friends1 - friends2
    # res2 = friends2 - friends1
    # print(res1,res2) # {'jerry', 'tank'} {'owen', 'oscar'}
    # 4 求两个用户各自独有的好友 对称差集
    # res = friends1 ^ friends2
    # print(res) # {'owen', 'jerry', 'tank', 'oscar'}
    # 5 子集 父集
    s1 = {12,3,4,5,6}
    s2 = {12,6}
    print(s1 > s2) # s1是否是s2的父集
    print(s2 < s1) # s2是否是s1的子集

万国字符———-》unicode————–》utf-8

中,英字符———-》unicode————–》gbk

屏幕 内存 磁盘

编码:unicode————–》utf-8

解码:utf-8————–》unicode(字符)

python语言中:编码 unicode——–》bytes

解码:bytes———-》unicode

rwa:r(只读),w(只写),a(追加写),+(增加功能):如r+,可读可写

tb:t(以字符串读),b(以bytes读)

.encode()编码,.decode()解码

  1. f = open(r"D:\PythonWorkspace\study\day01\text\a.txt",mode='rt',encoding='utf-8')
    res = f.read()
    print(res)
    f.close()

读:

.readable()判断是否可读

.readline()读一行

.readlines()所有内容读出来放入一个列表

写:

.writable()判断是否可写

.writlines():相当于for line in f:

lines.write(line)

其他:

.name()取得是文件的路径

.flush()

1、r(默认):只读 文件不存在时,报错;文件存在时文件指针跳到文件开头

2、w:只写 文件不存在时,创建一个空文件;文件存在时文件指针跳到文件开头,写的东西将原文件覆盖

3、a:追加写 文件不存在时,创建一个空文件;文件存在时指针跳到文件末尾,追加写

w与a的异同:

相同:w与a写文件不关的情况下,连续写入,新内容永远跟在老内容之后,

不同:重新打开文件,w会清空老的内容,a模式继续添加

1、t(默认):读写都是字符串为单位,一定要指定encoding

2、b:读写都是字节为单位,一定不能指定encoding

使用with,不用再关闭了

  1. with open() as fopen() as f1
    f.read()
    f1.write()

f.seek(移动几个字节,模式)模式:0,参照文件开头开始移动(只有0模式,可以在t模式下使用)

只能在b模式下使用:1,参照指针当前所在位置

2,参照文件末尾的位置

中文:3个字节,英文字母:1个字节

硬盘修改数据没有插入的,只能用新内容覆盖旧内容,内存可以修改

方式一:将硬盘内容全部读取到内存中,在内存中修改之后,覆盖到源文件中

  1. with open(r"D:\PythonWorkspace\study\day01\text\user.txt",mode='rt',encoding='utf-8') as f1:
    data = f1.read()
    res = data.replace("haha","Sb")

    with open(r"D:\PythonWorkspace\study\day01\text\user.txt",mode="wt",encoding="utf-8") as f2:
    f2.write(res)

方式二:

#1、循环读取源文件内容,一行行修改一行行写入一个新的临时文件 #2、删除源文件 #3、将临时文件重命名为源文件名

  1. # import os
    # with open('a.html',mode='rt',encoding='utf-8') as f1,\
    # open('.a.html.swp',mode='wt',encoding='utf-8') as f2:
    # for line in f1: (一行一行的读)
    # res=line.replace('SB','lxx')
    # f2.write(res)
    #
    # os.remove('a.html')
    # os.rename('.a.html.swp','a.html')

 

和方法类似

isinstance(x,int)判断x是不是int类型

issubclass(Foo,object)判断Foo是不是子类

1、无参:

2、有参:

def 函数名(参数一,参数二,。。。。。):

代码块

return 返回值

3、空参:

代码块用pass占位

函数名(参数)

函数内调用函数

函数内可以有多个return,但是只要执行一次return函数就立刻结束,并把return后的值当作返回值

函数有三种返回值:

1、return 值:返回该值本身

2、return 值1,值2,值3:返回一个元组

3、没有return:返回一个None

函数的使用分两个阶段: 1、定义阶段:只检测语法,不执行代码

2、调用阶段:执行函数体代码

发生语法错误,定义阶段无法通过

发生逻辑错误,只能在调用阶段检测到

1、形参:定义函数时,括号内定义的变量名

默认形参def max(z=4):默认形参可传可不传,默认形参放在位置形参后面,默认形参值应该是不可变类型

2、实参:调用函数时,括号内传入的值

位置实参必须放在关键字实参(name=haha)的前面

参数的个数不固定

1、在形参名前加会把溢出的位置实参存成元组,然后赋值其后的形参名 通常写为:*args

2、在形参名前加:会把溢出的位置实参存成字典(需要用a=1类型),然后赋值其后的形参名 通常写为:**kwargs

实参中用:

1、在实参前加*:会把值打散,相当于for循环

2、在实参前加**:会把值打散成关键字实参

  1. def max(x,y):
    print(x,y)

    res = {"x":15,"y":14}
    max(**res)

函数对象指的是函数可以被当成变量被使用,方法名存储的是方法的内存地址

  1. # 1 可以被赋值
    # f = foo
    # print(f is foo)
    # f()

    # 2 可以当作参数传给一个函数
    # def bar(func):
    # print(func)
    # func()
    #
    # bar(foo)

    # 3 可以当成一个函数的返回值
    # def bar(func):
    # return func

    # res=bar(foo)
    # print(res)


    # 4 可以当成容器类型的元素
    # l = [foo]

    # print(l)
    # l[0]()

使用范例:

  1. def login():
    print('登录功能......')


    def withdraw():
    print('提现功能......')


    def transfer():
    print('转账功能......')

    def recharge():
    print('充值功能')

    func_dic={
    "1": [login,"登录"],
    "2": [withdraw,"提现"],
    "3": [transfer,"转账"],
    "4": [recharge,"充值"]
    }

    # func_dic["1"][0]()


    while True:
    print("0 退出")
    for k in func_dic:
    print("%s %s" %(k,func_dic[k][1]))

    choice = input("请输入你的指令编号: ").strip()
    if choice == "0":
    break
    if choice in func_dic:
    func_dic[choice][0]()
    else:
    print('输入的指令不存在')

1、函数里面调用函数

2、函数里面定义函数:f2只能在f1内调

  1. def f1():
    def f2():
    return

名称空间:存放名字的地方

1、内置名称空间:存放的是内置的名字(如print/input)

生命周期:解释器启动则产生,关闭则销毁

2、全局名称空间:存放的是顶级的名字(顶头写的)

生命周期:程序运行时则产生,程序结束则销毁

3、局部名称空间:函数内的名字

生命周期:调用函数时则产生,函数调用结束则销毁

3—->2——>1 和嵌套类似

从当前位置往外查找,不会往内查

函数名称空间需要在定义阶段找

 

全局范围\全局作用域:内置名称空间+全局名称空间

特点:全局存活、全局有效

局部范围\局部作用域:局部名称空间

特点:临时存活、局部有效

global:声明为全局变量,可以在外面修改,修改之后才能输出,不能直接输出

nonlacal:找到临近外层的变量,在内层可以修改外层的变量

  1. x = 0
    def outer():
    x = 1
    def inner():
    nonlocal x
    x = 2
    print("inner:", x)

    inner()
    print("outer:", x)

    outer()
    print("global:", x)
    结果:

    inner: 2
    outer: 2
    global: 0

定义在函数内的函数,并且需要访问一个来自外层函数的变量

定义一个装饰器函数为其他函数添加新功能

1、什么是装饰器 器:工具 装饰:为被装饰者添加额外的功能

2、为何要有装饰器 软件一旦上线运行之后,就应该遵循开放封闭原则: 1、开放指的是对拓展新功能开放 2、封闭指的是对修改源代码封闭

定义装饰器的目的: ​ 定义装饰器就是为了在遵循1和2的前提下来为其他函数添加新功能的

ps: ​ 不修改被装饰对象指的是定义与调用都不能修改 ​ 所以下述行为都违反了开放封闭原则: ​ 1、修改被装饰对象定义时的源代码 ​ 2、修改被装饰对象的调用方式 3、如何用装饰器

  1. # import time
    #
    # def index(x,y):
    # time.sleep(1)
    # print('index===>',x,y)
    #
    #
    # def outter(func):
    # # func = index
    # def wrapper(*args,**kwargs):
    # start_time = time.time()
    # res = func(*args,**kwargs)
    # stop_time = time.time()
    # print('run time is: %s' %(stop_time - start_time))
    return res
    # return wrapper
    #
    # index=outter(index)

    #
    # # index(1,2)

多装饰器:

2、叠加多个装饰器 2.1 加载顺序:自下而上 2.2 执行顺序:自上而下运行内层的wrapper函数

  1. # def deco1(func1): # func1 = wrapper2的内存地址
    # def wrapper1(*args,**kwargs):
    # print('wrapper1====>')
    # res1=func1(*args,**kwargs)
    # return res1
    # return wrapper1
    #
    # def deco2(func2): # func2 = wrapper3的内存地址
    # def wrapper2(*args,**kwargs):
    # print('wrapper2====>')
    # res2=func2(*args,**kwargs)
    # return res2
    # return wrapper2
    #
    # def deco3(func3): # func3 = 最原始的那个被装饰函数的内存地址
    # def wrapper3(*args,**kwargs):
    # print('wrapper3====>')
    # res3=func3(*args,**kwargs)
    # return res3
    # return wrapper3
    #
    # # index=wrapper1的内存地址
    # @deco1 # deco1(wrapper2的内存地址)=>wrapper1的内存地址
    # @deco2 # deco2(wrapper3的内存地址)=>wrapper2的内存地址
    # @deco3 # deco3(最原始的那个被装饰函数的内存地址)=>wrapper3的内存地址
    # def index(x,y):
    # print('index=>',x,y)
    #
    # index(1,2)

    wrapper1====>
    wrapper2====>
    wrapper3====>
    index=> 1 2

有参数装饰器:

  1. # 有参装饰器的模板:
    def outter2(x,y,z,a,b):
    def outter1(func):
    def wrapper(*args,**kwargs):
    res=func(*args,**kwargs)
    return res
    return wrapper
    return outter1

  1. def outter(engine = 'file'):
    def deco2(func2):
    def wrapper2(*args,**kwargs):
    inp_name = input('username>>>: ').strip()
    inp_pwd = input('password>>>: ').strip()

    if engine == "file":
    print('基于file的认证')
    if inp_name == "egon" and inp_pwd == "123":
    print('login successful')
    res2=func2(*args,**kwargs)
    return res2
    else:
    print('username or password error')
    elif engine == 'mysql':
    print('基于mysql的认证')
    elif engine == 'ldap':
    print('基于ldap的认证')
    else:
    print('未知的engine')
    return wrapper2
    return deco2

    @outter(engine='mysql') # @deco2 # index=deco2(index)
    def index(x,y):
    print('index=>',x,y)

    index(1,2) # index=>wrapper

内置有iter方法的类型有:

1、字典

2、集合

3、文件对象

4、字符串

5、列表

6、元组

  1. dic = {"name": "egon", 'age': 18, 'gender': "male"}
    dic_iterator = dic.__iter__()

    # res1 = dic_iterator.__next__()

迭代器对象:内置有next方法、内置有iter方法

可以直接使用for循环

自定义迭代器实现惰性计算,达到节省内存的效果

函数内出现yield关键字,调用函数不会执行函数体代码,会得到一个返回值,该返回值就是我们自定义的迭代器,称之为生成器

  1. # def func():
    # print("hello1")
    # yield 111
    # print("hello2")
    # yield 222
    # print("hello3")
    # yield 333
    #


    # g = func()
    # print(g) # 生成器本质就是迭代器
    # res=next(g)
    # print(res)

yield和return的异同

同:都能返回值

异:return只能返回一次值,函数就立刻结束

yield能返回多次值,yield可以挂起函数

  1. # 案例
    # def func():
    # res=0
    # while True:
    # res+=1
    # yield res
    #
    # g=func()
    #
    # for i in g:
    # print(i)
    for循环:先将其变为迭代器对象
    不断调用next方法
    直到异常结束

核心是过程二字

优点:把复杂的问题流程化,进而简单化

缺点:扩展性差

  1. l = [i for i in range(5) 条件语句]
    print(l)
    [0,1,2,3,4]
    第一个i可以是任何值
  1. l = {‘k{i}’:i for i in range(5) 条件语句}
  1. l = {i for i in range(5) 条件语句}
  1. # res=(i for i in range(5))
    # # print(res,type(res))
    # print(next(res))
    # print(next(res))
    # print(next(res))
    # print(next(res))
    # print(next(res))
    # print(next(res))
  1. # print(abs(-1))取绝对值

    # print(all([True,11,0]))全为真才是真
    # print(all([]))真

    # print(any([True,False,0]))有一个为真就是真
    # print(any([]))假


    # print(callable(len))判断变量是否可调用

    # print(chr(90))数字转字符
    # print(ord('Z'))字符转数字

    # l=[1,2,3]

    # print(dir(l))


    # print(divmod(10,3))
    31

    res=eval('{"k1":111}\n')
    print(res['k1'])

表达式1 if 条件 else 表达式2

True:表达式1

Flase:表达式2

即没有名字的函数,使用lambda

  1. lambda xyx+y

    调用 :(lambda xyx+y)(12

匿名函数只运行一次,运行完之后就回收

多个功能的集合,不是用来直接执行的,而是用来导入使用的

多个模块的集合叫包

三大类:

1、内置的模块

2、第三方模块

3、自定义模块

导入模块时是从最高级的包下开始找的

  1. import 模块名
  1. from 模块名 import 模块中的函数

为导入模块起别名:

  1. import 模块名 as 别名

    模块内加可以控制*的范围
    __all__ = [函数1,函数2]

不建议循环导入,解决方法:将导入语句用函数包起来

  1. __name__方法
    当文件被当作主程序直接执行时,值为”__mian__
    当文件被当作模块导入时,值为”模块名“

搜索路径:

1、先从内存导入的模块中找

2、查找内置的模块

3、最后去sys.path列表中存放的多个文件夹里依次检索

  1. 如果不在一个包中,需要
    import 包.模块
    from import 模块

首次导入包这种模块,发生两件事: 1、创建模块名称空间,运行包下的init.py的文件,将运行过程中产生的名字都丢入模块的名称空间中

2、在当前位置拿到一个名字aaa,该名字指向init.py的名称空间,即aaa.名字,名字是来自于init.py中的

. :代表当前文件的文件夹

序列化:内存中某一数据类型——————转化为——————>特殊的格式

反序列化:特殊的格式——————转化为——————>内存中某一数据类型

优点:跨平台交互数据

缺点:无法识别所有的python类型

 

 

集合无法识别,元组可以识别

元组===转化为===》json格式的字符串

序列化:json.dumps()

  1. 方法一:
    items=["圣剑","蝴蝶","BKB"]
    dic_str=str(items)

    with open('db.txt',mode='wt',encoding="utf-8") as f:
    f.write(dic_str)
    方法二:
    items=["圣剑","蝴蝶","BKB"]
    with open('db.txt',mode='wt',encoding="utf-8") as f:
    json.dumpitemsf

反序列化:json.loads()

  1. 方式一:
    with open('db.txt',mode='rt',encoding='utf-8') as f:
    data=f.read() # "['圣剑', '蝴蝶', 'BKB']"

    items=eval(data)
    print(items[0])
    方式二:
    with open('db.txt',mode='rt',encoding='utf-8') as f:
    dic = json.loadf

2、为何要序列化 1、存档:把内存中的数据持久化到硬盘 2、跨平台交互数据

在python中: ​ 存档=》推荐用pickle格式 ​ 跨平台交互=》推荐用json格式

三:pickle 优点:可以识别所有python类型 缺点:只能用于python中,无法跨平台交互

序列化出来的是bytes

  1. s = {1,2,3,4,5}

    res=pickle.dumps(s)
    # print(res,type(res))
    with open('a.pkl',mode='wb') as f:
    f.write(res)


    with open('a.pkl',mode='rb') as f:
    data=f.read()
    s=pickle.loads(data)
    print(type(s))

hash是一种算法,为该算法传入文本内容,传的时候需要用bytes,该算法会计算得到一个值

使用场景:密码安全

hash值具备以下三个特点: 1、传入文本内容一致,使用算法一致,得到的hash值也一样

2、hash值的长度取决于采用的算法,与传入的文本内容大小无关

3、hash值不可逆,只能由文本变为hash值,不能由hash值变为文本

  1. import hashlib

    m=hashlib.md5() #hash工厂,可以直接传值
    m.update("你好".encode('utf-8')) #传入数据
    m.update("egon".encode('utf-8'))
    m.update("哈哈哈".encode('utf-8')) # "你好egon哈哈哈"
    res=m.hexdigest() #制造hash值
    print(res)

时间有三种格式:

1、时间戳:秒数

从1970年到现在

  1. time.time() 用于时间计算

2、格式化的字符串

  1. time.strftime("%Y-%m-%d %H:%M:%S %p") %p:上午,下午
    time.strftime("%Y-%m-%d %X)

3、结构化的时间:

  1. res = time.localtime() 获取时间的某一部分
    res.time_year

三种格式的转换:

 

 

 

  1. # 2.1 时间戳---》格式化的字符串
    # struct_time=time.localtime(3333.3)
    # res=time.strftime("%Y:%m",struct_time)
    # print(res)

    # 2.2 格式化的字符串---》时间戳
    # struct_time=time.strptime("2017-07-03 11:11:11","%Y-%m-%d %H:%M:%S")
    # res=time.mktime(struct_time)
    # print(res)

    # 三:
    # print(time.ctime(3333.3))
    # print(time.asctime(time.localtime(3333.3)))

    # 四:
    # time.sleep(3)

 

  1. datetime.datetime.now()当前时间
    datetime.date.fromtimestamp(time.time())时间戳转化为格式化字符串
    datetime.datetime.fromtimestamp(time.time())

    res=datetime.datetime.now() + datetime.timedelta(days=3)当前时间加三天

    将时间的某一部分换掉
    # res=datetime.datetime.now()
    # print(res)
    # new_res=res.replace(year=1999,month=9)
    # print(new_res)
  1. 1 import random
    2
    3 print(random.random())#(0,1)----float 大于0且小于1之间的小数
    4
    5 print(random.randint(1,3)) #[1,3] 大于等于1且小于等于3之间的整数
    6
    7 print(random.randrange(1,3)) #[1,3) 大于等于1且小于3之间的整数
    8
    9 print(random.choice([1,'23',[4,5]]))#1或者23或者[4,5]
    10
    11 print(random.sample([1,'23',[4,5]],2))#列表元素任意2个组合
    12
    13 print(random.uniform(1,3))#大于1小于3的小数,如1.927109612082716
    14
    15
    16 item=[1,3,5,7,9]
    17 random.shuffle(item) #打乱item的顺序,相当于"洗牌"
    18 print(item)

随机验证码:

  1. def make_code(n=5):
    res = ''
    for i in range(n):
    s1 = str(random.randint(0, 9))
    s2 = chr(random.randint(65, 90))
    res += random.choice([s1, s2])
    return res

    print(make_code(4))

和操作系统将交互

  1. os模块是与操作系统交互的一个接口

    View Code
    复制代码
    LinuxMac平台上,该函数会原样返回path,在windows平台上会将路径中所有字符转换为小写,并将所有斜杠转换为饭斜杠。
    >>> os.path.normcase('c:/windows\\system32\\')
    'c:\\windows\\system32\\'


    规范化路径,如..和/
    >>> os.path.normpath('c://windows\\System32\\../Temp/')
    'c:\\windows\\Temp'

    >>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'
    >>> print(os.path.normpath(a))
    /Users/jieli/test1
    复制代码


    复制代码
    os路径处理
    #方式一:推荐使用
    import os
    #具体应用
    import os,sys
    possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一级
    os.pardir,
    os.pardir
    ))
    sys.path.insert(0,possible_topdir)


    #方式二:不推荐使用
    os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

 

  1. 1 sys.argv 命令行参数List,第一个元素是程序本身路径
    2 sys.exit(n) 退出程序,正常退出时exit(0)
    3 sys.version 获取Python解释程序的版本信息
    4 sys.maxint 最大的Int
    5 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
    6 sys.platform 返回操作系统平台名称

 

  1. src_file = sys.argv[1]
    dst_file = sys.argv[2]
    将输入的所有数据变为一个列表
  1. print("\r[#### ]",end='') end不换行,\r:从头打印
  1. print("[%-15s]" % "###",) -左对齐,15:长度
  1. import time

    def progress(percent):
    if percent > 1:
    percent=1
    print("\r[%-50s] %d%%" % ("#"*int(50*percent),int(100 * percent)),end='')

    total_size = 1025
    recv_size = 0

    while recv_size < total_size:
    # 每次下载1024
    time.sleep(0.3)
    recv_size+=1024

    percent = recv_size / total_size

    progress(percent)
  1. shutil.copyfileobj(fsrc, fdst[, length])
    将文件内容拷贝到另一个文件中

    1 import shutil
    2
    3 shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))


    shutil.copyfile(src, dst)
    拷贝文件

    1 shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在


    shutil.copymode(src, dst)
    仅拷贝权限。内容、组、用户均不变

    1 shutil.copymode('f1.log', 'f2.log') #目标文件必须存在


    shutil.copystat(src, dst)
    仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

    1 shutil.copystat('f1.log', 'f2.log') #目标文件必须存在


    shutil.copy(src, dst)
    拷贝文件和权限

    1 import shutil
    2
    3 shutil.copy('f1.log', 'f2.log')


    shutil.copy2(src, dst)
    拷贝文件和状态信息

    1 import shutil
    2
    3 shutil.copy2('f1.log', 'f2.log')


    shutil.ignore_patterns(*patterns)
    shutil.copytree(src, dst, symlinks=False, ignore=None)
    递归的去拷贝文件夹

    1 import shutil
    2
    3 shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
    拷贝软连接


    shutil.rmtree(path[, ignore_errors[, onerror]])
    递归的去删除文件

    1 import shutil
    2
    3 shutil.rmtree('folder1')


    shutil.move(src, dst)
    递归的去移动文件,它类似mv命令,其实就是重命名。

    1 import shutil
    2
    3 shutil.move('folder1', 'folder3')


    shutil.make_archive(base_name, format,...)

    创建压缩包并返回文件路径,例如:ziptar

    创建压缩包并返回文件路径,例如:ziptar

    base_name 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
    data_bak =>保存至当前路径
    如:/tmp/data_bak =>保存至/tmp/
    format 压缩包种类,“zip”, tar”, bztar”,“gztar
    root_dir 要压缩的文件夹路径(默认当前目录)
    owner 用户,默认当前用户
    group 组,默认当前组
    logger 用于记录日志,通常是logging.Logger对象
    复制代码
    1 #将 /data 下的文件打包放置当前程序目录
    2 import shutil
    3 ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
    4
    5
    6 #将 /data下的文件打包放置 /tmp/目录
    7 import shutil
    8 ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
    复制代码
  1. shutil 对压缩包的处理是调用 ZipFile TarFile 两个模块来进行的,详细:


    复制代码
    import zipfile

    # 压缩
    z = zipfile.ZipFile('laxi.zip', 'w')
    z.write('a.log')
    z.write('data.data')
    z.close()

    # 解压
    z = zipfile.ZipFile('laxi.zip', 'r')
    z.extractall(path='.')
    z.close()
    复制代码

    复制代码
    import tarfile

    # 压缩
    >>> t=tarfile.open('/tmp/egon.tar','w')
    >>> t.add('/test1/a.py',arcname='a.bak')
    >>> t.add('/test1/b.py',arcname='b.bak')
    >>> t.close()


    # 解压
    >>> t=tarfile.open('/tmp/egon.tar','r')
    >>> t.extractall('/egon')
    >>> t.close()
  1. shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型

    复制代码
    import shelve

    f=shelve.open(r'sheve.txt')
    # f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']}
    # f['stu2_info']={'name':'gangdan','age':53}
    # f['school_info']={'website':'http://www.pypy.org','city':'beijing'}

    print(f['stu1_info']['hobby'])
    f.close()
  1. xml的格式如下,就是通过<>节点来区别数据结构的:


    复制代码
    <?xml version="1.0"?>
    <data>
    <country name="Liechtenstein">
    <rank updated="yes">2</rank>
    <year>2008</year>
    <gdppc>141100</gdppc>
    <neighbor name="Austria" direction="E"/>
    <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
    <rank updated="yes">5</rank>
    <year>2011</year>
    <gdppc>59900</gdppc>
    <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
    <rank updated="yes">69</rank>
    <year>2011</year>
    <gdppc>13600</gdppc>
    <neighbor name="Costa Rica" direction="W"/>
    <neighbor name="Colombia" direction="E"/>
    </country>
    </data>
    复制代码
    xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml

    # print(root.iter('year')) #全文搜索
    # print(root.find('country')) #在root的子节点找,只找一个
    # print(root.findall('country')) #在root的子节点找,找所有


    View Code
    复制代码
    #在country内添加(append)节点year2
    import xml.etree.ElementTree as ET
    tree = ET.parse("a.xml")
    root=tree.getroot()
    for country in root.findall('country'):
    for year in country.findall('year'):
    if int(year.text) > 2000:
    year2=ET.Element('year2')
    year2.text='新年'
    year2.attrib={'update':'yes'}
    country.append(year2) #往country节点下添加子节点

    tree.write('a.xml.swap')
    复制代码
    自己创建xml文档:


    复制代码
    import xml.etree.ElementTree as ET


    new_xml = ET.Element("namelist")
    name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
    age = ET.SubElement(name,"age",attrib={"checked":"no"})
    sex = ET.SubElement(name,"sex")
    sex.text = '33'
    name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
    age = ET.SubElement(name2,"age")
    age.text = '19'

    et = ET.ElementTree(new_xml) #生成文档对象
    et.write("test.xml", encoding="utf-8",xml_declaration=True)

    ET.dump(new_xml) #打印生成的格式

配置文件后缀:.ini

.cfg

.cnf

配置文件如下:

  1. # 注释1
    ; 注释2

    [section1]
    k1 = v1
    k2:v2
    user=egon
    age=18
    is_admin=true
    salary=31
    [section2]
    k1 = v1

读取

  1. import configparser

    config=configparser.ConfigParser()
    config.read('a.cfg')

    #查看所有的标题
    res=config.sections() #['section1', 'section2']
    print(res)

    #查看标题section1下所有key=value的key
    options=config.options('section1')
    print(options) #['k1', 'k2', 'user', 'age', 'is_admin', 'salary']

    #查看标题section1下所有key=value的(key,value)格式
    item_list=config.items('section1')
    print(item_list) #[('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')]

    #查看标题section1下user的值=>字符串格式
    val=config.get('section1','user')
    print(val) #egon

    #查看标题section1下age的值=>整数格式
    val1=config.getint('section1','age')
    print(val1) #18

    #查看标题section1下is_admin的值=>布尔值格式
    val2=config.getboolean('section1','is_admin')
    print(val2) #True

    #查看标题section1下salary的值=>浮点型格式
    val3=config.getfloat('section1','salary')
    print(val3) #31.0

改写

  1. import configparser

    config=configparser.ConfigParser()
    config.read('a.cfg',encoding='utf-8')


    #删除整个标题section2
    config.remove_section('section2')

    #删除标题section1下的某个k1和k2
    config.remove_option('section1','k1')
    config.remove_option('section1','k2')

    #判断是否存在某个标题
    print(config.has_section('section1'))

    #判断标题section1下是否有user
    print(config.has_option('section1',''))


    #添加一个标题
    config.add_section('egon')

    #在标题egon下添加name=egon,age=18的配置
    config.set('egon','name','egon')
    config.set('egon','age',18) #报错,必须是字符串


    #最后将修改的内容写入文件,完成最终的修改
    config.write(open('a.cfg','w'))

1、日志级别与配置

  1. 可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
    filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
    filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
    format:指定handler使用的日志显示格式。
    datefmt:指定日期时间格式。
    level:设置rootlogger(后边会讲解具体概念)的日志级别
    stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filenamestream两个参数,则stream参数会被忽略。
  1. import logging

    # 一:日志配置
    logging.basicConfig(
    # 1、日志输出位置:1、终端 2、文件
    # filename='access.log', # 不指定,默认打印到终端

    # 2、日志格式
    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',

    # 3、时间格式
    datefmt='%Y-%m-%d %H:%M:%S %p',

    # 4、日志级别
    # critical => 50
    # error => 40
    # warning => 30
    # info => 20
    # debug => 10
    level=30,
    )

    # 二:输出日志
    logging.debug('调试debug')
    logging.info('消息info')
    logging.warning('警告warn')
    logging.error('错误error')
    logging.critical('严重critical')

    '''
    # 注意下面的root是默认的日志名字
    WARNING:root:警告warn
    ERROR:root:错误error
    CRITICAL:root:严重critical
    '''

    access.log内容:
    2017-07-28 20:32:17 PM - root - DEBUG -test: 调试debug
    2017-07-28 20:32:17 PM - root - INFO -test: 消息info
    2017-07-28 20:32:17 PM - root - WARNING -test: 警告warn
    2017-07-28 20:32:17 PM - root - ERROR -test: 错误error
    2017-07-28 20:32:17 PM - root - CRITICAL -test: 严重critical

2、日志配置字典

  1. """
    logging配置
    """

    import os

    # 1、定义三种日志输出格式,日志中可能用到的格式化串如下
    # %(name)s Logger的名字
    # %(levelno)s 数字形式的日志级别
    # %(levelname)s 文本形式的日志级别
    # %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
    # %(filename)s 调用日志输出函数的模块的文件名
    # %(module)s 调用日志输出函数的模块名
    # %(funcName)s 调用日志输出函数的函数名
    # %(lineno)d 调用日志输出函数的语句所在的代码行
    # %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
    # %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
    # %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    # %(thread)d 线程ID。可能没有
    # %(threadName)s 线程名。可能没有
    # %(process)d 进程ID。可能没有
    # %(message)s用户输出的消息

    # 2、强调:其中的%(name)s为getlogger时指定的名字
    standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
    '[%(levelname)s][%(message)s]'

    simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

    test_format = '%(asctime)s] %(message)s'

    # 3、日志配置字典
    LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
    'standard': {
    'format': standard_format
    },
    'simple': {
    'format': simple_format
    },
    'test': {
    'format': test_format
    },
    },
    'filters': {},
    'handlers': {
    #打印到终端的日志
    'console': {
    'level': 'DEBUG',
    'class': 'logging.StreamHandler', # 打印到屏幕
    'formatter': 'simple'
    },
    #打印到文件的日志,收集info及以上的日志
    'default': {
    'level': 'DEBUG',
    'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,日志轮转
    'formatter': 'standard',
    # 可以定制日志文件路径
    # BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # log文件的目录
    # LOG_PATH = os.path.join(BASE_DIR,'a1.log')
    'filename': 'a1.log', # 日志文件
    'maxBytes': 1024*1024*5, # 日志大小 5M
    'backupCount': 5,
    'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
    },
    'other': {
    'level': 'DEBUG',
    'class': 'logging.FileHandler', # 保存到文件
    'formatter': 'test',
    'filename': 'a2.log',
    'encoding': 'utf-8',
    },
    },
    'loggers': {
    #logging.getLogger(__name__)拿到的logger配置
    '': {
    'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
    'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
    'propagate': False, # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
    },
    '专门的采集': {
    'handlers': ['other',],
    'level': 'DEBUG',
    'propagate': False,
    },
    },
    }


    使用:
    import settings

    # !!!强调!!!
    # 1、logging是一个包,需要使用其下的config、getLogger,可以如下导入
    # from logging import config
    # from logging import getLogger

    # 2、也可以使用如下导入
    import logging.config # 这样连同logging.getLogger都一起导入了,然后使用前缀logging.config.

    # 3、加载配置
    logging.config.dictConfig(settings.LOGGING_DIC)

    # 4、输出日志
    logger1=logging.getLogger('用户交易')
    logger1.info('egon儿子alex转账3亿冥币')

    # logger2=logging.getLogger('专门的采集') # 名字传入的必须是'专门的采集',与LOGGING_DIC中的配置唯一对应
    # logger2.debug('专门采集的日志')

 

3、使用

  1. import settings

    # !!!强调!!!
    # 1、logging是一个包,需要使用其下的config、getLogger,可以如下导入
    # from logging import config
    # from logging import getLogger

    # 2、也可以使用如下导入
    import logging.config # 这样连同logging.getLogger都一起导入了,然后使用前缀logging.config.

    # 3、加载配置
    logging.config.dictConfig(settings.LOGGING_DIC)

    # 4、输出日志
    logger1=logging.getLogger('用户交易')
    logger1.info('egon儿子alex转账3亿冥币')

    # logger2=logging.getLogger('专门的采集') # 名字传入的必须是'专门的采集',与LOGGING_DIC中的配置唯一对应
    # logger2.debug('专门采集的日志')

 

由一系列特殊字符拼接而成的表达式,该表达式用于从一个大字符串中匹配出符合规则的子字符串

 

 

*+是贪婪的

  1. print(re.findall("ab{2,5}","a ab abb abbb abbbb abbbbbbbb abbbbbbbbbbbb bbbbbbbbb"))
    ['abb', 'abbb', 'abbbb', 'abbbbb', 'abbbbb']

9.7 .*: 匹配所有

  1. # print(re.findall("a.*b","123 a1231-==-000b123123123123123b"))

    # a1231-==-000b123123123123123b 贪婪的

    print(re.findall("a.*?b","123 a1231-==-000b123123123123123b"))
    a1231-==-000b
  1. 10 ():分组

    # print(re.findall('ab+','ababab123')) #['ab', 'ab', 'ab']

    # print(re.findall('(ab)+123','ababab123')) #['ab'],匹配到末尾的ab123中的ab

    # ababab123

    # (ab)(ab)(ab)(ab)

    10.1 取消分组?:

    # print(re.findall('(?:ab)+123','ababab123'))
  1. \

  1. # print(re.findall('a\\\\c','a\c a1c aac')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常

    # print(re.findall(r'a\\c','a\c a1c aac')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常

  1. msg = '<a href="https://pan.baidu.com/s/1skWyTT7" target="_blank"><strong><span style="color: #ff0000;">原理图:https://pan.baidu.com/s/1skWyTT7</span></strong></a><a href="https://www.baidu/com">"点我啊"</a>'
    url_pattern = re.compile('href="(.*?)"')
    res=url_pattern.findall(msg)
    print(res)
  1. # ===========================re模块提供的方法介绍===========================
    import re
    #1
    print(re.findall('e','alex make love') ) #['e', 'e', 'e'],返回所有满足匹配条件的结果,放在列表里
    #2
    print(re.search('e','alex make love').group()) #e,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

    #3
    print(re.match('e','alex make love')) #None,同search,不过在字符串开始处进行匹配,完全可以用search+^代替match

    #4
    print(re.split('[ab]','abcd')) #['', '', 'cd'],先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割

    #5
    print('===>',re.sub('a','A','alex make love')) #===> Alex mAke love,不指定n,默认替换所有
    print('===>',re.sub('a','A','alex make love',1)) #===> Alex make love
    print('===>',re.sub('a','A','alex make love',2)) #===> Alex mAke love
    print('===>',re.sub('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$',r'\5\2\3\4\1','alex make love')) #===> love make alex

    print('===>',re.subn('a','A','alex make love')) #===> ('Alex mAke love', 2),结果带有总共替换的个数


    #6
    obj=re.compile('\d{2}')

    print(obj.search('abc123eeee').group()) #12
    print(obj.findall('abc123eeee')) #['12'],重用了obj

?!:没有匹配到

  1. ?!pattern,表示在没有配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始
  1. ?=pattern,表示在配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始

 

class 类名:(类名推荐用驼峰体)

创建对象:类名()

在类中加入:

  1. def __init__(obj,x,y,z):
    pass
    不能有返回值
  1. # 调用类:
    # 1、创建一个空对象与类相关
    # 2、把空对象、"冯疯子", 18, "female"一起传给__init__方法,完成对象的初始化
    # 3、赋值符号把初始化好的对象的内存地址绑定变量名stu_obj1
    stu_obj1 = Student("冯疯子", 18, "female")

封装对外不对内

  1. 属性和方法名前加__

    使用时:_类名__属性名 #强烈不建议

将功能伪造为属性

  1. # class People:
    # def __init__(self, name, height, weight):
    # self.name = name
    # self.height = height
    # self.weight = weight
    #
    # @property
    # def bmi(self):
    # return self.weight / (self.height ** 2)
    #
    #
    # p = People('egon', 1.81, 70)
    # p.height = 1.84
    # print(p.bmi)
  1. # class Student:
    # __school = "oldboy" # _Student__school = "oldboy"
    #
    # def __init__(obj, x, y, z):
    # obj.__name = x
    # obj.__age = y
    # obj.gender = z
    #
    # def get_name(self):
    # print("访问控制")
    # return self.__name
    #
    # def set_name(self,x):
    # print("赋值控制")
    # self.__name = x
    #
    # def del_name(self):
    # print("删除控制")
    # del self.__name
    #
    # def get_age(self):
    # return self.__age
    #
    # def set_age(self, x):
    # if type(x) is not int:
    # print("年龄必须是整型,傻叉")
    # return
    # self.__age = x
    #
    # def del_age(self):
    # print("不让删")
    #
    #
    # age = property(get_age, set_age, del_age)
    # name = property(get_name, set_name, del_name)
    #
    #
    # stu_obj1 = Student("冯疯子", 18, "female")
    #
    # # print(stu_obj1.age)
    # # stu_obj1.age = "19"
    # # del stu_obj1.age
    # # print(stu_obj1.age)
  1. class Student:
    __school = "oldboy" # _Student__school = "oldboy"

    def __init__(obj, x, y, z):
    obj.__name = x
    obj.__age = y
    obj.gender = z

    @property
    def name(self):
    print("访问控制")
    return self.__name

    @name.setter
    def name(self, x):
    print("赋值控制")
    self.__name = x

    @name.deleter
    def name(self):
    print("删除控制")
    del self.__name


    stu_obj1 = Student("冯疯子", 18, "female")

    stu_obj1.name

将函数绑定给了类,由类来调用,把类当作第一个参数传入

  1. @classmethod
    def 方法名(cls):
    pass

 

函数既不和类绑定也不和对象绑定,就是一个普通的函数,谁都可以调用,没有自动传参效果

class sub(父类名): python支持多继承

方式一:指名道姓地调用某一个类的函数

特点:不依赖于继承关系

  1. #
    class OldboyPeople:
    school = "oldboy"

    # 空对象,"艾利克斯",73,'male'

    def __init__(self,name,age,gender):
    self.name = name
    self.age = age
    self.gender = gender

    def f1(self):
    print('1111111')

    class Student(OldboyPeople):

    # 空对象,"艾利克斯",73,'male',1001,"python全栈开放"

    def __init__(self,name,age,gender,stu_id,course):
    OldboyPeople.__init__(self,name,age,gender) # OldboyPeople.__init__(空对象,"艾利克斯",73,'male')
    self.stu_id = stu_id
    self.course = course

    def choose(self):
    print('%s 正在选


    课' %self.name)

    def f1(self):
    OldboyPeople.f1(self)
    print("22222")

方式二、super(自己的类名,self)python3可以省略

调用super(自己的类名,self)会返回一个特殊的对象,super(自己的类名,self).属性,会参照属性查找发起的那个类的mro列表去它父类中查找属性

  1. # class OldboyPeople:
    # school = "oldboy"
    # # 空对象,"艾利克斯",73,'male'
    # def __init__(self,name,age,gender):
    # self.name = name
    # self.age = age
    # self.gender = gender
    #
    # def f1(self):
    # print('1111111')
    #
    # class Student(OldboyPeople):
    # def __init__(self,name,age,gender,stu_id,course):
    # # OldboyPeople.__init__(self,name,age,gender) # OldboyPeople.__init__(空对象,"艾利克斯",73,'male')
    # super(Student,self).__init__(name,age,gender)
    # self.stu_id = stu_id
    # self.course = course
    #
    #
    # def choose(self):
    # print('%s 正在选课' %self.name)
    #
    # def f1(self):
    # # OldboyPeople.f1(self)
    # # super().f1()

 

  1. 父类如果不想让子类覆盖自己的方法,可以在方法名前加前缀__
    class Foo:
    def __f2(self): # _Foo__f2
    print("Foo.f2")

    def f1(self):
    print('Foo.f1')
    self.__f2() # obj._Foo__f2()


    class Bar(Foo):
    def __f2(self): # _Bar__f2
    print("Bar.f2")

新式类:但凡是继承了object类的子类,以该子类子子孙孙类都称之为新式类 经典类:没有继承了object类的子类,以该子类子子孙孙类都称之为经典类

python3中全都是新式类,python2中才有经典类: 在python3中没有继承任何类的类会默认继承object类

 

菱形继承:

python2:深度优先,一条道走到黑,然后再找其他

python3:广度优先,先找所有的父类

非菱形继承:

深度优先

 

day26

  1. 类通常以Mixinableible为后缀
    通常Mixin结果的类放在左边

    首先它必须表示某一种功能,而不是某个物品,python 对于mixin类的命名方式一般以 Mixin, able, ible 为后缀

    其次它必须责任单一,如果有多个功能,那就写多个Mixin类,一个类可以继承多个Mixin,为了保证遵循继承的“is-a”原则,只能继承一个标识其归属含义的父类

    然后,它不依赖于子类的实现

    最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了)

反应的是has a的关系

组合:把另外一个类的对象赋值给当前对象的属性

组合表达的是有的关系

  1. class Teacher:
    def __init__(self, name, age, gender, level):
    self.name = name
    self.age = age
    self.gender = gender
    self.level = level

    def tell(self):
    print("%s:%s" % (self.name, self.age))


    class Student:
    def __init__(self, name, age, gender):
    self.name = name
    self.age = age
    self.gender = gender


    class Course:
    def __init__(self, name, price, period):
    self.name = name
    self.price = price
    self.period = period

    def tell(self):
    print('<%s:%s:%s>' % (self.name, self.price, self.period))


    tea1 = Teacher("egon", 18, "male", 10)
    stu1 = Student("xxx", 19, "male")

    python = Course("python开放", 30000, "3mons")
    linux = Course("linux课程", 30000, "3mons")

    tea1.courses = [python,linux]
    stu1.course = python

    # tea,stu # 超级对象

    # stu1.course.tell()
    for course_obj in tea1.courses:
    course_obj.tell()

推荐鸭子类型,不使用继承

  1. Java抽象类的概念相似

    # import abc
    #
    # class Animal(metaclass=abc.ABCMeta):
    # @abc.abstractmethod
    # def speak(self):
    # pass
    #
    # @abc.abstractmethod
    # def run(self):
    # pass
    #
    # # Animal() # Animal的作用是用来制定标准的
    #
    # class People(Animal):
    # def speak(self):
    # print("啊啊啊啊")
    #
    # def run(self):
    # print("咻咻咻...")
    #
    # class Dog(Animal):
    # def giao(self):
    # print("汪汪汪")
    #
    # class Pig(Animal):
    # def heheng(self):
    # print("哼哼哼")

    # peo1=People()
    # d1=Dog()
    # p1=Pig()

    # peo1.jiao()
    # d1.giao()
    # p1.heheng()

 

 

  1. 类():先调用__new__方法,创建一个空对象
    再调用__init__方法,将属性方法放入空对象中,完成初始化
    对象 = 类()
    对象():调用__call__方法,运行

    exec(cmd, {}, class_dic) #类名,类的基类,类的名称空间 执行这个函数生成类
  1. # 实现方式1:classmethod
    """
    import settings


    class MySQL:
    __instance = None

    def __init__(self, ip, port):
    self.ip = ip
    self.port = port

    @classmethod
    def singleton(cls):
    if cls.__instance:
    return cls.__instance
    cls.__instance = cls(settings.IP, settings.PORT)
    return cls.__instance


    # obj1=MySQL("1.1.1.1",3306)
    # obj2=MySQL("1.1.1.2",3306)
    # print(obj1)
    # print(obj2)


    obj3 = MySQL.singleton()
    print(obj3)

    obj4 = MySQL.singleton()
    print(obj4)
    """

    # 方式2:元类
    """
    import settings


    class Mymeta(type):
    __instance = None
    def __init__(self,class_name,class_bases,class_dic):
    self.__instance=object.__new__(self) # Mysql类的对象
    self.__init__(self.__instance,settings.IP,settings.PORT)

    def __call__(self, *args, **kwargs):
    if args or kwargs:
    obj = object.__new__(self)
    self.__init__(obj, *args, **kwargs)
    return obj
    else:
    return self.__instance

    # MySQL=Mymeta(...)
    class MySQL(metaclass=Mymeta):
    def __init__(self, ip, port):
    self.ip = ip
    self.port = port


    # obj1 = MySQL("1.1.1.1", 3306)
    # obj2 = MySQL("1.1.1.2", 3306)
    # print(obj1)
    # print(obj2)

    obj3 = MySQL()
    obj4 = MySQL()

    print(obj3 is obj4)
    """


    # 方式3:装饰器
    """
    import settings

    def outter(func): # func = MySQl类的内存地址
    _instance = func(settings.IP,settings.PORT)
    def wrapper(*args,**kwargs):
    if args or kwargs:
    res=func(*args,**kwargs)
    return res
    else:
    return _instance
    return wrapper

    @outter # MySQL=outter(MySQl类的内存地址) # MySQL=》wrapper
    class MySQL:
    def __init__(self, ip, port):
    self.ip = ip
    self.port = port


    # obj1 = MySQL("1.1.1.1", 3306)
    # obj2 = MySQL("1.1.1.2", 3306)
    # print(obj1)
    # print(obj2)

    obj3 = MySQL()
    obj4 = MySQL()
    print(obj3 is obj4)
    """

把程序的某一部分功能换成另外的功能

  1. class A:
    def speak(self):
    return "hello"

    def speak_patch(self):
    return "world"

    A.speak = speak_patch # <1>

    some_class = A()

    print('some_class.speak():', some_class.speak()) # <2>

    some_class.speak(): world

内置方法都是在满足某种条件下自动触发的

  1. __str__:控制对象打印行为
    重点:要用return 返回
    # class People:
    # def __init__(self, name, age):
    # self.name = name
    # self.age = age
    #
    # def __str__(self):
    # # print('===>')
    # return "<%s:%s>" %(self.name,self.age)
    #
    # obj = People("egon", 18)
    #
    # print(obj) # print(obj.__str__())
    <egon:18>

    __del__:删除对象时触发

dir(对象)以列表形式显示所有属性、方法

hasattr(对象,“属性”)判断对象是否有属性

getattr(对象,“属性”)显示属性值

getattr(对象,“属性”,None)显示属性值,没有的话不要报错,返回None

setattr(对象,属性,值)有的话改属性,没有添加

delattr(对象,属性)删除属性

  1. # class Person():
    # def __setattr__(self, key, value): # 对象.赋值会触发 a.name='lqz' name给key,lqz给value
    # print('set')
    #
    # def __getattr__(self, item):# 对象.取值会触发 a.name name给item,return 1
    # print('get')
    # return 1
    #
    # def __delattr__(self, item):# del 对象.属性 会触发
    # print('delete')
    #
    #
    # p = Person()
    # p.name
    # print(p.name)
  1. # 1 __ setattr__的使用
    # 2 递归现象的出现
    -通过反射赋值 setattr(obj,key,value)
    -self.key=value
    # 3 避免递归
    -self.__dict__[key] = value
    -object.__setattr__(self,key,value)
    # 4 object.__setattr__(f,'_Foo__size',178)的使用

    # 5 __getattr__
    -对象.属性 取值属性不存在就会触发它的执行

    # 6 应用场景(字典只支持中括号取值和赋值,让它支持 . 取值和赋值)
  1. 3 `__setitem__``__getitem__`

    ```python
    # 对象[]取值赋值会触发它的指向

    # 不继承字典,还支持[]赋值取值
    class Foo:
    def __setitem__(self, key, value):
    setattr(self, key, value)
    # object.__setattr__(self,key,value)

    def __getitem__(self, item):
    return getattr(self, item)


    f = Foo()
    f.name = 'lqz'
    print(f.name)
    print(f['name'])
    f['age'] = 19
    print(f.age)
    print(f['age'])
  1. __dict__:
    a.age = 10
    print(a.__dict__) # {'num': 10, 'age': 10}
    当一个类设置了__slots__属性后,这个类的__dict__属性就不存在了:
    class A:
    __slots__ = ['name', 'age']
    a1 = A()
    # print(a1.__dict__) # AttributeError: 'A' object has no attribute '__dict__'
    a1.name = '张三'
    a1.age = 24
    # a1.hobby = '泡妞' # AttributeError: 'A' object has no attribute 'hobby'
    print(a1.__slots__)
  1. __item__:
    class Foo:
    def __init__(self, name):
    self.name = name

    def __getitem__(self, item):
    print(self.__dict__[item])

    def __setitem__(self, key, value):
    print('obj[key]=lqz赋值时,执行我')
    self.__dict__[key] = value

    def __delitem__(self, key):
    print('del obj[key]时,执行我')
    self.__dict__.pop(key)

    def __delattr__(self, item):
    print('del obj.key时,执行我')
    self.__dict__.pop(item)


    f1 = Foo('sb')
    print(f1.__dict__)
    f1['age'] = 18
    f1.hobby = '泡妞'
    del f1.hobby
    del f1['age']
    f1['name'] = 'lqz'
    print(f1.__dict__)
  1. __call__ 方法的执行是由对象后加括号触发的
    __doc__ 注释信息
    https://www.cnblogs.com/liuqingzheng/articles/9949568.html
  1. __eq__
    拥有__eq__方法的对象支持相等的比较操作

    复制代码
    class A:
    def __init__(self,x,y):
    self.x = x
    self.y = y

    def __eq__(self,obj):
    # 打印出比较的第二个对象的x值
    print(obj.x)
    if self.x +self.y == obj.x+obj.y:
    return True
    else:
    return False

    a = A(1,2)
    b = A(2,1)
    print(a == b)

 

1、语法错误,在运行前需要改正

2、逻辑异常,

变量没有定义NameError

索引异常:IndexError

键不存在:KeyError

属性不存在:AttributeError

  1. try
    代码块
    except 异常类型:
    发生异常后要执行的代码
    except 异常类型:
    发生异常后要执行的代码
    finally
    一定会执行

    异常类型可以用Exception万能异常
  1. raise NameError(“变量名未定义”)
    自定义异常
  1. # class Interface(BaseException):
    # def __init__(self, msg, x, y, z):
    # self.msg = msg
    # self.x = x
    # self.y = y
    # self.z = z
    #
    # def __str__(self):
    # return "<%s:%s:%s:%s>" % (self.msg,self.x,self.y,self.z)
    #
    #
    # raise Interface("接口异常", 11, 22, 33)
  1. 断言:判断上一部分是否正确,正确后续执行,错误不执行
    print("====1")
    print("====2")
    print("====3")
    salaries=[1.1,2.2]

    # if len(salaries) != 3:
    # raise NameError
    assert len(salaries) == 3

    print(salaries[2])
    print(salaries[2])
    print(salaries[2])

核心是引用计数:一个变量的引用计数为0时,才会被当作垃圾回收

问题1:循环引用——–》导致内存泄漏

 

 

 

标记—清除: 标记:栈区相当于根,从根出发可以访问的(直接或者间接都可以),标记起来

清除:遍历堆中所有对象,没有标记的对象会被清除

问题2:效率问题:每次从头开始扫描,效率慢

分代回收

多次扫描都有的,提高权重,扫描频率降低,每隔一段时间扫描一次

版权声明:本文为chenxinhua原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/chenxinhua/p/16746555.html