• python学习记录笔记


    目录:

    一、变量

    二、字符串

    三、列表和元组

    四、布尔值

    五、条件语句if

    六、函数

    七、对象的方法

    八、格式化字符串

    九、循环

    十、文件的读写

    十一、字典和json

    十二、模块与包

    十三、yaml文件操作

    十四、pycharm的使用技巧

    十五、request与爬虫

    十六、面向对象(基础、进阶、高级)

    十七、异常与日志

    十八、pytest框架与allure

    十九、思考题

    一、变量

    # 变量与对象,一切皆为对象,可变的量都是变量
    print(type('123fff'))  # str
    print(2 / 3)  # 0.6666666666666666
    print(2 ** 100)  # 2的100次方
    # 字符串
    print("""hello""")  # hello
    print('''hello''')  # hello
    print('hello')  # hello
    print("hello")  # hello
    
    welcome = '欢迎来学习自动化'  # python定义变量要给初始值
    a = '小刘'
    print(a, ',', welcome)
    # 数字不能开头,用字母开头
    b = 1
    b = b + 1
    b += 1  # 等于b=b+1
    b -= 1  # 等于b=b-1
    b *= 1  # 等于b=b*1
    b /= 1  # 等于b=b/1

    二、字符串

    # 字符串,单引号和双引号都可表示字符串
    url = 'https://www.baidu.com'
    url2 = "https://www.baidu.com"
    print(url, ',', url2)
    
    # 当句子中有单引号,外面就用双引号引起来;当句子中有双引号,外面就用单引号引起来;当句子中有单、双引号,外面就用三引号引起来
    str1 = "It's OK"
    print(str1)
    # 三引号也可以表示换行
    str2 = ''' 飞流直下三千尺,
     疑是银河落九天'''
    print(str2)
    # 转义符 \n换行符;\t制表符
    filepath = 'D:\soft\note.txt'  # \n表示换行了
    print(filepath)
    ''' D:\soft
    ote.txt '''
    # 解决1:
    filepath = 'D:\\soft\\note.txt'  # 用双\\,表示后面的\是普通字符
    print(filepath)
    # 解决2:在字符串前加上r,表示后面的字符串中,所有的转义符均无效
    filepath = r'D:\soft\note.txt'
    print(filepath)
    # 解决3:表示路径时,用/代替\。(对于电脑来说,路径用\ 、 /都可以)
    filepath = 'D:/soft/note.txt'
    print(filepath)
    
    # 字符串的拼接
    print(1 + 1)  # 2
    # print(1 + '1')  # int和str会报错
    print('1' + '2')  # 11,字符串拼接
    print('1' * 6)  # 结果是111111,表示将字符串1打印6次
    
    a = 9
    b = '6'
    print(9 + int(b))  # 使用int()函数,将字符串转化为数字,得到15
    print(str(9) + b)  # 使用str()函数,将int类型转化为字符串,进行拼接,得到96
    
    # 字符串的下标
    str3 = 'adhjhhfuerhfkjfkjfer'
    print(str3[1])  # d ,下标从左边0开始
    print(str3[-3])  # f ,下标右边从-1开始
    # str3[1] = 'a'  # 会报错,'str' object does not support item assignment。因为str类型是不可变的对象,不能只修改一个值
    
    # 字符串的切片 [起始值:终止值:步长]:包含起始值,不包含终止值,所以终止值要+1。步长默认为1,代表每次走一步
    id_card = '320150199802254422'  # 18位身份证
    # 取出生日期19980225
    birthday = id_card[6:14]  # 从第6位到14位,正下标
    print(birthday)
    birthday1 = id_card[-12:-4]  # 从第6位到14位,负下标
    print(birthday1)
    # 如果要取到最后一位 id_card[-12:]
    # 步长为2,得到19980225里面的1,3,5,7位1902
    birthday2 = id_card[-12:-4:2]  # 从第6位到14位,负下标,步长为2
    print(birthday2)
    # 步长为-1,从-12位开始向左取全部的数,3201501
    birthday3 = id_card[-12::-1]  # 从第6位到14位,负下标,步长为2
    print(birthday3)

    三、列表和元组

    # 列表 元组
    # 列表类似java里面的数组,与数组不同的是可以包含各种类型的对象;列表是可变对象,可以增删改
    list_a = [1, 'a', [1, 2, 3], (4, 5, 6), {"name": "zhang"}]
    print(list_a)
    #
    list1 = [1, 2, 3]
    list1.insert(0, 999)  # 在第0位增加一个999
    print(list1)
    # 拼接
    list2 = [4, 5, 6]
    list1.extend(list2)  # 将list1和list2拼接到一起,得到[999, 1, 2, 3, 4, 5, 6],list2没有变
    print(list1)
    print(list2)
    #
    list1[0] = 88  # 把list1的第0位改成88,得到[88, 1, 2, 3, 4, 5, 6]
    print(list1)
    # 删除
    print(list1.pop())  # pop()默认删除最后一位下标,也可以指定下标进行删除,有返回值
    print(list1)  # 得到[88, 1, 2, 3, 4, 5]
    list1.pop(0)
    print(list1)  # 把88删掉,得到[1, 2, 3, 4, 5]
    
    list1.remove(4)  # 把4删掉,remove()是直接删除值,如果有多个4,那也只删除从左开始碰到的第1个
    print(list1)  # 得到[1, 2, 3, 5]
    
    del list1[0]  # 删除下标的元素1,也可以直接删除list1
    print(list1)  # 得到[2,3,5]
    # 切片---也是一个新对象
    list3 = [11, 22, 33, 44, 55, 66, 77]
    list3_new = list3[0:3]  # 从下标0开始切片,到第三位,也可以写成[:3],得到[11,22,33];负下标list3[-7:-4]
    list3_new1 = list3[-7:-4]
    print(list3_new1)
    
    # 元组,属于不可变对象,也可以使用下标和切片,但是不能增删改
    tuple_1 = (100, 200, 300, 400)
    # 元组中只有一个元素时,要加一个逗号
    tuple_2 = (100)
    print(type(tuple_2))  # 得到int类型
    tuple_3 = (100,)
    print(type(tuple_3))  # 得到tuple类型
    # 如果元组中有子列表,子列表里面的值可以修改,但是不能直接替换掉子列表
    tuple_4 = (100, 200, 300, 400, [11, 22, 33])
    tuple4_new = tuple_4[4][1]  # 取到列表的第一位22
    print(tuple4_new)
    tuple_4[4][2] = 99  # 修改列表的第二位33为99 ,得到(100, 200, 300, 400, [11, 22, 99])
    print(tuple_4)

    四、布尔值

    # 布尔类型、布尔表达式、条件组合
    # 布尔值:True  False (真 假 、 0 1)
    # python中,=表示赋值,==表示判断恒等,!=表示判断不相等
    print(1 == 2)  # 得到False
    print(1 != 2)  # 得到True
    print('a' == 'A')  # 得到False;字符串之间的比较用ASCII值,a=97,A=65
    
    # in , not in
    list1 = [1, 2, 3, 4, [999, 888]]
    print(1 in list1)  # 得到True
    print(9 not in list1)  # 得到True
    print(888 in list1)  # 得到False,888属于子列表,应该写成888 in list1[-1]
    
    # and , or  执行程序时,第一、二、三个式子只要它能判断式子是假/真,后面式子就可以不再执行,直接返回False/True
    print(3 > 2 and 2 > 1 and 5 > 3)  # True,用and都为真就是真。全真为真
    print(3 > 2 and 2 > 1 and 5 > 9)  # False,用and有一个假就是假。一假全假
    print(3 > 2 or 0 > 1)  # True,用or的时候有一个为真就是真,全部是假的就是假。一真为真,全假为假。
    
    # not and or 组合语句。不同情况按照优先级分析,not>and>or,相同情况按照从左到右
    print(2 > 1 and 1 > 2 and not True or 3 > 2)  # 得到True。
    '''
    1.先分析not: not True=false,所以假
    2.分析and:2>1 and 1>2,是假。
    3.分析or,or前面都是假,3>2是真,所以结果是真
    2 > 1 and 1 > 2 and not True or 3 > 2
    真          假         假          真
    '''
    print(2 > 1 and 1 > 2 and (not True or 3 > 2))  # 得到False
    '''
    通过括号改变运算优先级,先算括号里面的,所以是not>or>and
    (2 > 1 and 1 > 2 and (not True or 3 > 2))
    真           假             假       真
    1.括号里是真
    2.and是假
    得到结果就是假
    '''
    # 浅拷贝 深拷贝
    # 赋值--对列表赋值相当于起了一个别名,2个对象指向的是同一个对象。比如小张有1个外号张总,小张改变了,那张总也对应改变
    list2 = [11, 22, 33]
    list2_new = list2
    list2[0] = 99
    print(list2, id(list2))
    print(list2_new, id(list2_new))
    print('---------------分界线--------')
    # 浅拷贝,等价于完整切片
    import copy
    
    # 浅拷贝
    list3 = [91, 95, 66, 44, [1000, 200, 300]]
    list3_new = copy.copy(list3)  # 浅拷贝,生成了新的对象,子列表仍然是同一个对象
    list3[0] = 100
    list3[-1][0] = 000
    print('------浅拷贝', list3, id(list3), id(list3[-1]))  # list3改变了,子列表一起改变
    print('------浅拷贝', list3_new, id(list3_new), id(list3_new[-1]))  # list3_new没变,子列表一起改变
    print('---------------分界线--------')
    # 完整切片
    list5 = [91, 95, 66, 44, [1000, 200, 300]]
    list5_new = list5[:]
    list5[0] = 100
    list5[-1][0] = 123
    print('------切片', list5, id(list5), id(list5[-1]))  # list5改变了,子列表一起改变
    print('------切片', list5_new, id(list5_new), id(list5_new[-1]))  # list5_new没变,子列表一起改变
    print('---------------分界线--------')
    # 深拷贝
    list4 = [91, 95, 66, 44, [1000, 200, 300]]
    list4_new = copy.deepcopy(list4)  # 浅拷贝,生成了新的对象,子列表也是新的对象
    list4[0] = 100
    list4[-1][0] = 456
    print('-----深拷贝', list4, id(list4), id(list4[-1]))  # list4改变了,子列表一起改变
    print('-----深拷贝', list4_new, id(list4_new), id(list4_new[-1]))  # list4_new没变,子列表没变

    五、条件判断

    # 条件判断
    # 分支语句:顺序结构,分支结构,循环结构
    # python对于缩进有严格的要求,对于缩进的空格没有要求,一般默认缩进4格
    if 10 > 9:
        print('hello')  # 如果10>9为真,执行输出hello;如果是假,就不执行
    # 写一个程序,用户输入分数,如果分数大于等于60,打印合格
    score = input('请输入分数:')  # input()是从键盘获取到用户输入的值,返回的值是string类型。如果用户输入的是数字,要转成int型才能做比较
    # 如果用户输入的是字符串,那么用int也不能转,可以写判断语句
    if not score.isdigit():  # isdigit()判断对象是否是纯数字,如果输入的不是纯数字,就打印
        print('您输入的不是数字')
    else:
        score = int(score)
        if score >= 60:
            print('合格')
        else:
            print('不及格')
    
    # 写一个程序,用户输入分数,如果分数大于等于90,打印优秀;如果大于等于80,打印良好;如果大于等于60,打印合格;小于60不合格
    score1 = input('请输入分数:')  # input()是从键盘获取到用户输入的值,返回的值是string类型。如果用户输入的是数字,要转成int型才能做比较
    # 如果用户输入的是字符串,那么用int也不能转,可以写判断语句
    if not score1.isdigit():  # isdigit()判断对象是否是纯数字,如果输入的不是纯数字,就打印
        print('您输入的不是数字')
    else:
        score1 = int(score1)
        if score1 >= 90:
            print('优秀')
        elif score1 >= 80:  # 如果不用elif,都用if,那么输入62时,会打印出优秀、良好和合格。每个if都是独立的分支语句。用elif起到分支的作用
            print('良好')
        elif score1 >= 60:
            print('合格')
        else:
            print('不合格')
    
    # 复合条件语句
    # 例:如果一个人年龄大于60岁,且是男性,我们称他为老先生
    age = 62
    sex = ''
    # 写法1:
    if age >= 60 and sex == '':  # 用==判断恒等
        print('他是老先生1')
    # 写法2:
    if age >= 60:
        if sex == '':
            print('他是老先生2')

    六、函数

    # 函数的定义与调用,参数和返回值
    # 函数是一段封装的代码,需要它的时候可以调用
    def fun1():  # 1.def是define,定义函数的关键字 2.fun1是函数名,函数名尽量用小写
        print('这是一个函数')  # 函数主体语句,必须有;没有语句用pass占位符代替
    
    
    def fun2():
        return 'hello'
    
    
    # 调用函数
    # 方法一,直接调用
    fun1()
    print(fun1())  # 先打印’这是一个函数‘,再返回None,因为函数没有返回值
    fun2()  # 返回显示是空的,因为没有print打印,实际的返回值hello已经写入
    print(fun2())  # 打印返回值hello
    
    
    # sin(30*) = 0.5, sin(90*) = 1,sin(45*) = 2**0.5/2,括号里面的30 90 45 就是函数的参数,后面的结果就是函数的返回值
    # 写一个函数,可以计算两数之和
    def add_func(x, y):  # x,y是形式参数,简称形参
        return x + y
    
    
    # 方法二,赋值调用
    a = add_func(5, 6)  # 调用,把返回值赋给a ; 5和6是实际参数,简称实参
    print(a)  # 11
    
    
    # 如果调用add_func(5),少参数会报错,因为实参数量小于形参数量;多参数也会报错
    
    def add_func1(c=100, b=90):  # a和b有默认值
        return c + b
    
    
    print(add_func1(60))  # 只传一个参数,默认替代第一个参数a,b还是90,打印150
    print(add_func1())  # 不传参数,使用默认值,打印190
    print(add_func1(b=10))  # 只传一个参数,指定替代b,a还是100,打印110
    print(add_func1(10, 20))  # 传2个参数,都替代函数里的默认值,打印30
    print(add_func1(b=110, c=120))  # 传2个参数,位置可以指定,都替代函数里的默认值,打印230
    
    
    # 函数中可以出现多个return,但是没必要
    # 写一个函数,返回数的绝对值
    def abs_value(n):
        if n >= 0:
            return n
            return '34344'  # 在第一个return执行完毕之后,程序跳出,后面的renturn不执行,称为不可达语句
        else:
            return -n
    
    
    print(abs_value(-5))
    
    
    # 函数能否return多个值?-------可以,以元组的形式返回
    def add_func2(e=100, f=90):
        return e, f, e + f, e - f
    
    
    print(add_func2())  # 得到元组(100, 90, 190, 10)
    
    
    def add_func3(e=100, f=90):
        return [e, f, e + f, e - f]  # [e, f, e + f, e - f]是一个对象,是一个值,不会组合成元组
    
    
    print(add_func3())  # 得到list[100, 90, 190, 10]
    
    
    # 可变长度参数
    # 自己写的函数叫做自定义函数,python里自带的叫做内置函数
    # print(1, 2, 3, 4, 5, 6, 7)  # 不管传几个参数,都能打印处理
    # *args:允许用户输入任意个参数
    def fun_change(*args):
        # print(args)
        return args
    
    
    print(fun_change(1, 2, 3, 4, 5, 6, 7))  # 打印出(1, 2, 3, 4, 5, 6, 7)
    
    
    # 关键字参数:**kwargs:允许用户输入任意个参数,用户传的参数必须是a=b的格式,相当于键值对,返回值是字典类型
    def fun_arbitrary(**kwargs):
        return kwargs
    
    
    print(fun_arbitrary(name='九九', age=18))  # 得到{'name': '九九', 'age': 18}
    
    # def print(self, *args, sep=' ', end='\n', file=None):  # known special case of print
    # print()函数中的sep=' '表示每个参数的间隔符,默认用空格分割,end='\n'表示打印完就换行
    print(1, 2, 3, 4, 5, 6, 7, sep='=')  # 得到1=2=3=4=5=6=7
    print(1, end='')
    print(2, end='')  # 把换行符去掉,打印完不换行,得到12

    七、对象的方法

    # 对象的方法,其实就是函数,只不过是写在类里面的
    str1 = 'abchdjdj'  # str1是一个字符串,可以直接使用类str中的函数
    str1.isdigit()
    str1.format()
    # def index(self, sub, start=None, end=None):返回值是数字
    a = str1.index('d')  # 返回某个或某些字符串中的位置,默认从头查找,也可以指定起始位置进行查找
    print(a)
    print(str1.index('d', 5))  # 从第五位开始查找
    # index()方法,找不到键值会报异常:
    # print(str1.index('c', 4))  # 报错,substring not found
    # find()方法找不到键值会返回-1
    
    # strip()  :默认是去掉字符串前后的空格,也可以指定去掉字符,但是只能去掉字符串外面的字符
    print(str1.find('c', 4))
    str2 = '            whdwehfkwef'
    str2_new = '*********fjdk***fhkjd********'
    print(str2.strip())  # whdwehfkwef
    print(str2_new.strip('*'))  # fjdk***fhkjd,字符串里面的*不会被去掉
    
    # relace(oldstr,newstr)  :oldstr是需要替换的字符,newstr是替换后的字符,返回值是str型,可以一直替换
    print(str1.replace('d', 'k').replace('abc', 'KKK'))  # 把所有的d替换成k后,再把abc替换成KKK
    # 如果没有找到要替换的字符,就保持原样不进行替换
    
    # startswith() :判断字符串是否以某个或某些字符开头,返回值是true或false
    # 根据身份证号判断是否是南京的身份证
    id_card = '320104199905024422'
    if id_card.startswith('3201'):
        print('南京的身份证')
    
    # endswith() :判断字符串是否以某个或某些字符结尾,返回值是true或false
    # 根据身份证号最后一位是否是X
    if id_card.endswith('X'):
        print('最后一位是X')
    
    # split() 切割字符串,它有一个参数,以参数作为切割符,将字符分隔成多个值,返回值是列表
    str4 = '你好,中国'
    print(str4.split(''))  # ['你好,', '国'],中字消失
    # 如果切割符位于首位或结尾,会产生空值
    print(str4.split(''))  # ['你好,中', '']
    # 如果没有找到切割符,会把原来的字符串转成列表
    print(str4.split('1'))  # ['你好,中国']

    八、格式化字符串

    # 格式化字符串
    # 输出10+5=15
    a = 10
    b = 5
    print(str(a) + '+' + str(b) + '=' + str(a + b))  # 字符串拼接方式实现
    print('%d+%d=%d' % (a, b, a + b))  # 格式化字符串实现
    
    # 方案一
    # %s:字符串  %d:整数  %f:浮点数
    info1 = '我是%s,你是%s,他是%s,今年是%d年' % ('刘德华', '古天乐', '刘青云', 2022)
    print(info1)
    
    # 前面的空位比后面的值多,会报错not enough arguments for format string
    # info2 = '我是%s,你是%s,他是%s,今年是%d年' % ('刘德华', '古天乐', 2022)
    
    # 前面的空位比后面的值少,报错:not all arguments converted during string formatting
    # info3 = '你是%s,他是%s,今年是%s年' % ('刘德华', '古天乐', '刘青云', 2022)
    
    # 前面用%d,后面用字符串,会报错 :%d format: a number is required, not str
    # info4 = '我%d岁' % ('刘德华')
    
    # 前面用%s,后面用数字,不会报错
    info4 = '我叫%s' % 100
    
    # 自动补齐%n,n是任意正整数,不足n位,用空格补齐到n位;默认右对齐;超过n位则全部显示
    # %5n代表这个字符串有5位,格式化提供的只有3位,所以会补齐2个字符的空格
    # 得到:我是刘德华上天下地霹雳无敌雷劈电视动画,你是  古天乐,他是刘青云,今年是2022年
    info5 = '我是%6s,你是%5s,他是%s,今年是%s年' % ('刘德华上天下地霹雳无敌雷劈电视动画', '古天乐', '刘青云', 2022)
    print(info5)
    # 如果想补0,就写成%0位数d
    info6 = '我的编号是%05d' % 7  # 我的编号是00007
    print(info6)
    
    # 补齐时左对齐显示,空格在后面。但是前面补的0会消失,只会在后面补空格
    # 得到:我是刘德华上天下地霹雳无敌雷劈电视动画,你是古天乐  ,他是刘青云,今年是2022    年
    info7 = '我是%s,你是%-5s,他是%s,今年是%-08s年' % ('刘德华上天下地霹雳无敌雷劈电视动画', '古天乐', '刘青云', 2022)
    print(info7)
    
    # %f浮点型,默认保留6位小鼠
    number1 = '你输入的数字是%f' % 3.6
    print(number1)  # 得到你输入的数字是3.600000
    
    # 保留2位小数,%.小数位f
    number2 = '你输入的数字是%.2f' % 3.6
    print(number2)  # 得到你输入的数字是3.60,如果是最少要显示10位,可以%10.2f,得到      3.60,格式化时小数点占一位
    
    # 方案二,参数用{}代替,不用关注类型
    str1 = 'My name is {},your name is {},age is {}.'.format('clark', 'ralf', 20)
    print(str1)  # My name is clark,your name is ralf,age is 20.
    
    # 前面的空位比后面的值少,不报错,多的不显示
    # 前面的空位比后面的值多,报错
    # {}没有写数字时,称为顺序取值法,写了数字,称之为下标取值法,下标从0开始,{}都要写下标,2种方法不能混用,不然会报错
    str2 = 'My name is {1},your name is {0},age is {2}.'.format('clark', 'ralf', 20)
    print(str2)  # My name is ralf,your name is clark,age is 20.
    
    # 补齐{:n} n是任意整数,不足n位时补齐到n位,字符是左对齐,数字是右对齐
    str3 = 'My name is {:8},your name is {:9},age is {:5}.'.format('clark', 'ralf', 20)
    print(str3)  # 得到My name is clark   ,your name is ralf     ,age is    20.
    
    # 改变对齐方式:左对齐:<,居住对齐^,右对齐>。{0:>8}:第0个参数右对齐显示8位
    str4 = 'My name is {:>8},your name is {:^9},age is {:<5}.'.format('clark', 'ralf', 20)
    print(str4)  # 得到My name is    clark,your name is   ralf   ,age is 20   .
    
    # 补0,字符串补0没意义
    str5 = 'My name is {:>08},your name is {:^09},age is {:>05}.'.format('clark', 'ralf', 20)
    print(str5)  # 得到My name is 000clark,your name is 00ralf000,age is 00020.  居中对齐就是2边都补0
    
    # 在python3.6以后的版本,f’{}’ 用法等同于 format用法的简单使用,更加方便。:后面跟位数
    name1 = 'clark'
    name2 = 'Ralf'
    print(f'my name is {name1:10},your name is {name2:8}.')  # my name is clark     ,your name is Ralf    .

    九、循环

    # 循环语句
    # while循环,打印0到10的数字
    i = 0
    while i <= 10:  # while后面的布尔表达式为真,则一直执行循环内的语句,直到表达式的值为假,循环才结束
        print(i)
        i += 1
    
    # for循环实现从1到10的打印,左闭右开
    for a in range(1, 11):  # range(起始值,终止值,步长)  包含起始值,不包含终止值,步长默认为1
        print(a)
    # 利用步长打印1-100的奇数:
    for b in range(1, 100, 2):
        print(b)
    # for循环的起始值,不写时默认为0;终止值必须写
    for c in range(10):
        print(c)  # 打印了0-9的数
    # 遍历列表
    '''
    list1 = ['张飞', '刘备', '关羽', '马超']
    for d in range(len(list1)):
        print(list1[i])
    '''
    list1 = ['张飞', '刘备', '关羽', '马超']
    for d in list1:
        print(d)
    
    # break:终止循环(强制性终止)   continue:跳出当此循环
    for e in range(1, 11):
        if e == 5:
            # break
            continue
        print(e)  # break打印出1-4,continue打印出1,2,3,4,6,7,8,9,10,去掉了5,因为5跳出循环
    else:  # 循环语句也可以带一个else语句,当循环中没有出现break,则循环结束时,运行else部分
        print('循环执行完毕')
    
    # 写一个倒计时程序,循环实现
    import time  # 加载time模块
    
    for i in range(10, 0, -1):  # 起始值是10,终止值是0,从大到小,步长是负的
        print(f'\r倒计时{i}秒', end='')  # \r:光标回到行首;end=‘’:不换行
        time.sleep(1)  # 让程序等待1秒
    else:
        print('\r倒计时结束')

    十、文件的读写

    # 文件的读写,正反斜杠都能识别,防止有转义符,就用反斜杠。open()读取的是文本类的文档
    filepath = 'D:/note/note1.txt'  # 文件路径
    file1 = open(filepath)  # 打开一个文件,默认mode='r',读取模式,不可写入
    # print(file1.read())  # 读取并打印文件的内容:1111
    file1.close()  # 关闭文件,使用open()时,必须要用close(0,否则会一直占用内存
    
    file2 = open(filepath, 'w')  # 以写入的模式打开,不可读取
    file2.write('ABC')  # 文本内容被替换成ABC
    file2.close()  # 关闭文件
    
    # w+ 可以同时读写,如果文件不存在,则新建文档,写入时是清空写入
    # r+ 可以同时读写,如果文件不存在,则报错,写入时是覆盖写入
    # a+ 可以同时读写,如果文件不存在,则新建文档,写入时是追加写入
    file3 = open('D:/note/note2.txt', 'w+')  # 以w+的模式打开,新建了一个文本
    file3.write('ABC')  # 文本内容写入ABC
    file3.close()  # 关闭文件
    
    file4 = open('D:/note/note2.txt', 'r+')  # 以w+的模式打开,新建了一个文本
    file4.write('9')  # 文本内容变成9BC,9覆盖了A
    file4.close()  # 关闭文件
    
    file5 = open('D:/note/note2.txt', 'a+')  # 以w+的模式打开,新建了一个文本
    file5.write('888')  # 文本内容变成9BC888,888追加在后面
    file5.close()  # 关闭文件
    
    '''
    模式   原始   写入  结果
    r+     ABC   Q    QBC
    w+     ABC   Q    Q
    a+     ABC   Q    ABCQ
    '''
    
    file6 = open(filepath, 'w+')
    file6.write('春风得意马蹄疾,\n一日看尽长安花。')  # 第二句换行显示
    file6.seek(0)  # 要让光标回到首位,不然就默认在末尾,读取不了内容。
    '''
    注意:中文一般占2个字节,如果seek(2),春字不读取,如果是1,报错
    seek()其实有2个参数,第二个参数默认为0,表示回到文件首位
    如果第二个参数为1,表示保持光标在当前位置
    如果第二个参数为2,表示光标会移到文件末尾
    
    第二个参数为1,2时,只有wb模式可以使用
    '''
    print(file6.read())  # 输出
    file6.close()
    
    # 读取文件
    '''
    1.print(file1.read())    一次性把文本内容全读取,返回值是字符串
    2.print(file1.readline())     每次读取一行的内容,返回值是字符串
    3.print(file1.readlines())  读取文件所有内容,但是是用每行内容做为列表形式展示,会出现\n
       返回值是列表:['春风得意马蹄疾,\n', '一日看尽长安花。']
    4.print(file1.read().splitlines())   读取文件所有内容,但是是用每行内容做为列表形式展示,没有\n
       返回值是列表:['春风得意马蹄疾,', '一日看尽长安花。']
    '''
    
    # 打开文件,用with...open打开不用关闭,可以处理多个文件
    with open(filepath) as a:
        a.read()
    # 新建一个文件,写入
    with open('D:/note3.txt', 'w+') as file7, open(filepath) as file8:
        print(file8.read().splitlines())
        file7.write('9999')
    
    # 性能测试,要求快速生成1000个账号,密码可以一样,账号格式:sq001,123456
    with open('D:/zhanghao.txt', 'w+') as f:
        for i in range(0, 1001):
            f.write(f'sq{i:03},123456\n')  # 最少3位数字,不足3位补0

     十一、字典和json

    # 字典和json
    dict1 = {'姓名': 'nuncio', 'age': 18}
    '''
    一、字典可以存放哪些对象?(不可变对象)
    1.str
    2.num
    3.tuple
    二、字典的值可以存放哪些对象?
       任意的类型
    三、字典是无序的
    四、字典的键是唯一的
    五、字典的新增与修改语句是一样的,根据键修改值,如果已有键则更新,否则就新增键
    六、更新多个键,用update()方法
    七、删除字典中的键值对,用del方法
    八、清空字典
    1.dict.clear() :清空字典,id不变
    2.dict={}  :重新赋值了一个空字典,id改变
    九、遍历字典
    十、判断某个对象是否在字典中,判断的是键
    '''
    dict2 = {'a': 'apple', 123: 'niu', (1, 2, 3): 'fei'}
    print(dict2)
    dictb = {'a': 'A', 'b': 'B'}
    dicta = {'b': 'B', 'a': 'A'}
    print(dicta == dictb)  # 两个列表是否相等,得到==》TRUE。因为字典是无序的
    dictc = {'A': 'apple', 'A': 'ace'}
    print(dictc)  # 得到==》'A':'ace'  代码是从左往右跑,因为后定义的键A把前面的A覆盖,只会输出后面键的值。字典的键是唯一的
    dicta['A'] = '场所'
    print(dicta)  # 没有键A,会新增,得到{'b': 'B', 'a': 'A', 'A': '场所'}
    dicta['A'] = '场所111'
    print(dicta)  # 有键A,会修改,得到{'b': 'B', 'a': 'A', 'A': '场所111'}
    dicta.update({'D': 'duck', 'E': 'eyes'})
    print(dicta)  # 得到{'b': 'B', 'a': 'A', 'A': '场所111', 'D': 'duck', 'E': 'eyes'}
    del dicta['A']
    print(dicta)  # 把A的值删掉,得到{'b': 'B', 'a': 'A', 'D': 'duck', 'E': 'eyes'}
    # 清空字典
    # 第一种
    print(id(dicta))  # 1691485815656
    dicta.clear()
    print(id(dicta))  # 1691485815656
    print(dicta)  # 得到空字典{}
    # 第二种
    print(id(dict2))  # 1746518884088
    dict2 = {}
    print(id(dict2))  # 1746519659208
    
    # 遍历字典:dict1 = {'姓名': 'nuncio', 'age': 18}
    # 1.遍历键
    for k in dict1.keys():
        print(k)  # 得到姓名,age
    # 2.遍历值
    for v in dict1.values():
        print(v)  # 得到nuncio,18
    # 3.遍历键值对
    for k, v in dict1.items():
        print(k, v)  # 得到姓名 nuncio,age 18
    for k in dict1.items():
        print(k)  # 得到元组('姓名', 'nuncio'),('age', 18)
    for k, v in dict1.items():
        print(k)  # 只输出键
    for k, v in dict1.items():
        print(v)  # 只输出值
    
    # 判断某个对象是否在字典中是根据键来判断。 dict1 = {'姓名': 'nuncio', 'age': 18}
    print('age' in dict1)  # True,键存在
    print('18' in dict1)  # False,18这个键不存在,是值
    
    '''
    1.json长得像字符串,本质上是字典
    2.json的键值对都要用双引号,不能用单引号(字典是可以单双的)
    '''
    # 模拟读出来的文件格式,都是str
    str1 = '''{
    "name":"jiu",
    "age":"18",
    "sex":"female",
    "phone":"18988888888"
    }'''
    print(str1)  # 得到{"name":"jiu","age":18,"sex":"female"},如果把引号去掉,实际上str1就是一个字典
    print(type(str1))  # str
    
    # 场景:修改str1的手机号。思考:因为str1是字符串,修改手机号只能通过下标str1[3]去修改,不能通过键,维护比较麻烦
    # 思路:1.把str1转成json,然后修改键phone
    print('-------------分界线-----------')
    import json
    from random import randint
    
    str1_new = json.loads(str1)  # 将json转为字典
    print(str1_new)  # 得到{'name': 'jiu', 'age': '18', 'sex': 'female', 'phone': '18988888888'}
    print(type(str1_new))  # <class 'dict'>,变成字典格式
    print(str1_new['phone'])  # 18988888888
    str1_new['phone'] = '18899999999'
    print(str1_new['phone'])  # 18899999999
    str1_new['phone'] = f'138{randint(10000000, 99999999)}'  # 随机的手机号
    print(str1_new['phone'])
    
    str1 = json.dumps(str1_new)  # 将字典转为json
    print(type(str1))  # <class 'str'>
    # load和dump是将文件中的XX转换,loads和dumps是将代码中的XX转换

     十二、模块与包

    # 模块与包
    '''
    包>模块>函数
    模块:
    1.一个.py文件就是一个模块
    2.模块命名时,以英文开头,尽量不用中文作为模块名,方便调用
    包:
    1.包是一种特殊的文件夹,如果目录里有__int__.py文件,则这个文件夹就是包
    2.当导入包时,__init__.py文件里的代码会立刻执行一次
    导入模块的几种方式:
    1.import 模块名  :适用于与当前模块在同一目录内,或者位于标准库/第三方库中的文件;使用模块中的函数时,方式是 模块名.函数()
    2.from 包 import 模块 :调用时,方式是 模块名.函数()
    3.from 包.模块 import 函数
    4.from 模块 import 函数
    '''
    import time
    
    print(time.time())
    # 主函数,输入main后按tab键,自动补全
    if __name__ == '__main__':  # 以下代码只在本模块运行
        pass
    print(__name__)  # 得到__main__
    
    # 第三方库需要安装才能使用:pip install selenium;标准库不需要安装,直接使用:如print()
    # 安装指定版本pip install selenium==2.7.1
    '''
    安装使用的源:
    1.豆瓣源
    pip install selenium -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
    2.清华源
    pip install selenium -i http://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
    '''
    import this
    
    # 卸载 pip uninstall 第三方库
    '''
    在pycharm中安装第三方库:
    1.settings+项目名+python interpreter,点击加号进行安装
    2.新建项目时,选择真实环境(现有解释器)
    '''
    # 标准路径
    import sys
    
    for one in sys.path:  # 显示python的标准路径,表示位于这些路径下才能被导入
        print(one)
    # 标准路径的第一个目录是当前路径,第二个是工程路径,后面都是标准路径。第三方库都在D:\soft\python\lib\site-packages
    # 进入该目录,新建一个pth文件,文件名任意,后缀名必须是.pth,将路径写入文件中

    十三、yaml

    # yaml文件操作
    '''
    安装:pip install pyyaml
    1.全名: Yet another markup language(仍是一种置标语言
    2.专门用来写配置文件,非常简介和强大,远比json格式方便
    3.可以用之作为自动化测试框架的配置文件或用例文件
    4.新建文件,后缀名可以用.yaml,也可以用.yml
    5.yaml的书写规范,列表必须要有空格,可以是一个可以是多个
    6.值前面没有空格,打印出来是字符串;有空格,打印出来是字典
    7.字典和列表不能混用,可以多建几个yaml文件
    8.列表中还有子列表:得到[10, [20, 30], 40]
    - 10
    -
     - 20
     - 30
    - 40
    9.字典中还有列表,{'name': [10, 20, 30], 'age': 20}
    name:
      - 10
      - 20
      - 30
    age: 20
    20.列表中有子字典,[{'name': 'dehua', 'age': 20}, 20]
    -
      name: dehua
      age: 20
    -20
    10.用---分割数据,得到[10, 20]  [100, 200]
    ---
    - 10
    - 20
    ---
    - 100
    - 200
    '''
    import yaml
    
    # with open('config.yaml',encoding='utf-8') as file1:
    # print(file1.read())
    # content = yaml.safe_load(file1)  # 安全读取
    # print(content)  # 直接读出来{'name': 'JIU'}
    
    with open('config.yaml',encoding='utf-8') as file2:
        # print(file1.read())
        content1 = yaml.safe_load_all(file2)  # 安全读取
        for one in content1:
            print(one)  # 直接读出来{'name': 'JIU'}

    十四、pycharm的使用

    #pycharm的使用技巧
    """
    1.每次新建文件自动生成内容:
    setting--editor--file and code temples:选择python script:
    #${NAME}   文件名
    #${DATE}   当前日期
    #作者:XXX
    2.自动补齐
    (1)输入部分,按tab键
    (2)自动补齐自定义的段落:
    setting--editor--live temples:点击+号,新建一个,命名为李商隐
    文本输入:身无彩凤双飞翼,心有灵犀一点通。 选择下面的生效范围,勾选python。
    输入李商隐,回车,自动出现诗句。
    3.修改注释的颜色:
    setting--editor--color scheme--python
    4.取消语法检查:
    setting--editor--inspections,选择python,取消PEP 8两个选项
    5.分屏
    settings,搜索split,找到split down和split right,右键新增键盘快捷键
    6.切换编码:当遇到乱码问题时,可以考虑切换编码
    setting--editor--file encoding
    """
    list1 = [100,98,27,36,-5,89]
    list1.sort()  #没有返回值对list1进行永久性排序
    print(list1)
    list1_new = sorted(list1)#有返回值,返回排序后的列表
    print(list1_new)
    
    #冒泡算法
    '''
    原始数据4321 4个数,第一轮比较多少次?--3次 ,n个数,第一轮比较n-1次
    1.3421 第一次比较,将4和3的位置互换
    2.3241 第二次比较,将4和2的位置互换
    3.3214 第三次比较,将4和1的位置互换
    第二轮比较多少次?--2次,n-2次
    1.2314 第一次比较,将3和2的位置互换
    2.2134 第二次比较,将3和1的位置互换
    第三轮比较多少次?--1次,n-3次
    1.1234,第一次比较,将2和1的位置互换
    '''
    list2 = [100,98,27,36,-5,89]
    for i in range(len(list2)-1):  #控制比较多少轮
        for j in range(len(list2)-1-i): #控制每轮比较多少次
            if list2[j] > list2[j+1]: #如果前面的数比后面的大
                print(f'这是第{i}轮,第{j}位和第{j+1}位的顺序不对')
                print(f'---变化之前{list2}')
                list2[j],list2[j+1] = list2[j+1],list2[j] #两数互换
                print(f'现在的list是{list2}')
    print(f'---比较后的list是{list2}')

    十五、request爬虫

    """
    lesson15_request   爬虫
    2022/5/9   
    作者:大九九
    步骤:
    1.建一个空字典
    2.先拿到小说主页,获取到章节名
    3.通过章节名拿到地址,章节名和地址都赋给字典
    4.通过地址拿到每个章节的内容,章节名和内容赋给字典
    5.把标题和章节写进txt中
    """
    import re #正则表达式模块,标准库文件补需要安装,re.S表示跨行匹配
    import requests  #网络爬虫模块,第三方库,需安装才能使用
    
    #str1 = '但使龙城飞将在,不教胡马度阴山'
    #print(re.findall('使(.*?)飞',str1)[0])   #得到空城([0]得到字符串,原始返回是列表)
    
    url = 'http://www.quannovel.com/read/620/' #进行爬虫的网址
    req = requests.get(url)  #获取html网页
    #print(req)   #得到<Response [200]>
    #print(req.text) #得到html网页
    mulu = re.findall('class="name ">(.*?)</a>',req.text)
    title = re.findall('<title>(.*?)的章节目录_全书小说网</title>',req.text)[0]  #获取到标题
    #print(title)
    #for one in mulu:
        #print(one)  #打印目录
    #第一章真正的网址是http://www.quannovel.com/read/620/246756.html
    real_url_num = re.findall('<a href="(.*?).html" title=',req.text) #把每一章的数字提取出来
    #print(real_url_num)
    #for i in real_url_num:
        #real_url = f'{url}{i}.html'  #拼接得到真正的网址
        #print(real_url)
    #把目录和网址存在对象中
    dict1 = {}
    for i in range(len(mulu)):  #因为抓网址的时候,vip章节也抓取,所以只匹配免费章节的长度
        dict1[mulu[i]] = f'{url}{real_url_num[i]}.html'  #把键的值更新成章节
    #for k,v in dict1.items():
        #print(k,v)
    #抓取每章的内容
    for k,v in dict1.items():
        res = requests.get(v)
        #print(res.text)
        content = re.findall('<div id="htmlContent" class="page-content ">(.*?)<div class="reward"',res.text,re.S)
        #print(content)
        content_c = '</p>'.join(content).replace('<p>','').replace('</p>','')#用join把列表转成字符串,用</p>分割,然后再替换<p></p>为空
        #print(content_c)
        dict1[k] = content_c #把键的值更新成内容
    #print(dict1)
    with open('D:/novelurl.txt', 'w+') as f2:
        f2.write(f'标题:{title}\r\n')
        f2.write(f'正文\r\n')
        for k, v in dict1.items():
            f2.write(str(k)+'\r'+' ')
            #f2.write('\r')
            #f2.write(' ')
            f2.write(str(v)+'\r\n')
            #f2.write('\r\n')

    十六、面向对象(基础、进阶、高级)

    """
    lesson16_面向对象
    2022/5/10   
    作者:大九九
    """
    '''
    面向过程与面向对象的区别,以下五子棋为例
    面向过程:
    先判断谁落子,再判断是否获胜;如果没有获胜,继续判断是谁落子,判断是否获胜
    面向对象:
    事先写好各种方法,主程序只负责调用,调用落子的方法,调用判断胜负的方法
    '''
    '''
    类和实例的概念:
    类是抽象的模板,实例是根据模板创建出来的具体的对象
    例如:人类,指的是一个统称,说人类的时候并不知道说的是谁;想让人知道具体说的是谁,就要进行实例化,例如吴彦祖=人类
    例如汽车、演员、医生、老师等统称的类,模板定义汽车会跑,演员会演戏,医生会看病,老师会教书。实例化时,
    就默认带有模板定义的属性,例如实例化公交车会跑、卡车会跑、张国立会演戏等
    例如:界门纲目科属种,涉及到子类的概念
    '''
    #定义一个长方形的类:属性:两边长相等,两边宽相等,直角90度,周长=2(a+b),面积s=a*b
    class Rectangle:   #类名的首字母大写
        list1 = [1,2,85,99]  #类属性,属于类,具有唯一性
        def __init__(self,length,width):  #初始化方法,实例化要传的参数在这定义。self指的是实例本身的意思
            self.length = length  #self.length,类中的所有方法都能用
            self.width = width  #将用户传的宽转为实例自身的宽
            self.list2 = [89,5,666]  #实例属性,不唯一
        def perimeter(self):   #周长的方法
            return  (self.length+self.width)*2
        def area(self):   #面积的方法
            return self.width * self.length
    #实例化一个长是5,宽是4的长方形
    rec = Rectangle(5,4)
    print(rec.perimeter())  #直接调用周长的方法,得到18
    print(rec.area())  #直接调用面积的方法,得到20
    print(rec.__dict__)  #查看实例的属性:得到{'length': 5, 'width': 4, 'list2': [89, 5, 666]}
    print(Rectangle.list1) #不用实例化,就可以得到类属性[1, 2, 85, 99]
    print(rec.list2) #实例的属性,要实例化才能用,因为类本身不能用实例的东西。得到[89, 5, 666]
    
    rec1 = Rectangle(10,8)
    rec2 = Rectangle(12,5)
    print(id(rec1.list1)==id(rec2.list1)) #list1是类属性,是唯一的,所有的实例都共用一个list1,所以是true
    print(id(rec1.list2)==id(rec2.list2)) #list2是实例属性,每个实例都生成1个list2,所以id不同
    '''
    单例模式:
    一般情况下,类可以生成任意个实例,单例模式只生成1个(生成新的会覆盖之前的)
    例如:班主任,一个班级只有一个班主任
    '''
    class Single:
        def __init__(self):  #初始化方法
            pass
        def __new__(cls,*args,**kwargs): #构造方法,用于生成实例
            if not hasattr(cls,'obj'): #判断类当中有没有实例方法,如果没有则新建
                cls.obj = object.__new__(cls) #生成实例对象
            return cls.obj  #返回实例
    '''
    反射:用户点菜,有这个菜就给用户反馈
    1.hasattr()
    2.getattr()
    3.setattr()
    '''
    class Fanguan:
        def __init__(self):  #初始化方法
            self.price = 18
        def yuxiangrousi(self):
            return '鱼香肉丝'
        def gongbaojiding(self):
            return '宫爆鸡丁'
        def qingjiaotudousi(self):
            return '青椒土豆丝'
        def shousibaocai(self):
            return '手撕包菜'
        def kaishuibaicai(self):
            return '开水白菜'
        def fanqie(self):
            return '番茄'
    #客人点菜
    fg = Fanguan()   #实例化
    while True:
        caidan = input('请点菜: ')
        if hasattr(fg,caidan):  #hasattr(对象,属性或方法名)判断是否有这个菜的方法或属性。
            print('好的,请厨师开始做菜')
            break
        else:
            print('没有这道菜')
    
    def fun1():
        return '没有这道菜'
    input1 = input('请输入要翻译的菜名: ')
    c = getattr(fg,input1,fun1) #gesattr(对象,属性或方法名,缺省值)判断是否有这个菜的方法或属性,如果有返回对象本身。
    #如果找不到对象,就返回缺省值。返回的是对象本身,所有用fun1,不需要括号
    print(c()) #调用返回值,加括号
    
    setattr(fg,'price',22) #setattr(对象,属性或方法名,新值)把实例化以后的price属性改成22
    print(fg.price)  #得到22
    
    '''
    面向对象进阶
    '''
    class Rectangle1:
        def __init__(self,length,width):
            self.length = length
            self.width = width
        def perimeter(self):   #实例方法,只能被实例调用,不能被类调用
            return  (self.length+self.width)*2
        def area(self):   #实例方法
            return self.width * self.length
        @classmethod  #装饰器,声明下面的方法是类方法
        def features(cls):  #类方法写cls,实例方法写self。类方法既可以被实例调用,也可以被类调用
            print('两边的长相等,两边的宽也相等,长和宽的角度为90度')
        @staticmethod  #装饰器,声明下面的方法是静态方法。如果不声明,直接调用下面的方法,会报错。类和实例都能调用,本质上是函数
        def fun2(a,b):
            return a+b
    
    rec1 = Rectangle1(5,4)#实例化
    print(rec1.perimeter())  #直接调用周长的方法,得到18
    print(rec1.area())  #直接调用面积的方法,得到20
    rec1.features()
    Rectangle1.features()  #不用实例化,直接调用类方法,不会报错
    rec1.fun2(3,5)  #得到8
    
    #通过type查看对象是方法还是函数
    print(type(rec1.perimeter()))   #得到返回值是<class 'int'>
    print(type(rec1.perimeter))   #得到<class 'method'>,是方法
    print(type(rec1.features)) #得到<class 'method'>,是方法
    print(type(rec1.fun2))  #得到<class 'function'>,是函数,是静态方法
    
    #inspect模块,判断某个对象是否是某种类型,返回值是布尔型
    import inspect
    print(inspect.ismethod(rec1.perimeter))   #true,是方法
    print(inspect.isfunction(rec1.fun2))  #true,是函数
    
    '''
    继承
    1.完全继承
    定义一个正方形的类,完全继承上面长方形的面积和周长的计算方法,Rectangle就是Square的父类
    完全继承,主体可以写pass
    调用的时候正常对长方形实例化,就可以调用父类方法
    '''
    class Square(Rectangle):
        pass
    squ = Square(6,6)  #长和宽都是6
    print(squ.area())  #36
    print(squ.perimeter())  #24
    
    '''
    2.部分继承--重写一些父类的方法
    3.部分继承--继承父类方法的同时,扩展一些方法的代码:
    squ1.features()  #得到两边的长相等,两边的宽也相等,长和宽的角度为90度。想要加上长和宽也相等这句话,用super()
    '''
    class Square1(Rectangle1):
        def __init__(self,side):   #同名的方法会覆盖,初始化方法也会
            self.length = side
            self.width = side
        def features(cls):
            super().features()  #声明继承父类的features方法的代码
            print('长和宽也相等') #扩展代码,加上一句
    squ1 = Square1(7)  #边是7
    print(squ1.area())  #49
    print(squ1.perimeter())  #28
    squ1.features()  #两边的长相等,两边的宽也相等,长和宽的角度为90度。长和宽也相等
    
    #@property 声明下面的方法是一个属性,不是方法
    class Test:
        def __init__(self):
            pass
        @property
        def fun3(self):
            return 'hello'
    tt1 = Test()
    print(tt1.fun3) #得到hello,不能加括号,因为fun3是一个属性
    
    '''
    面向对象高级
    1.私有属性与私有方法不能从外部被调用,也不能被子类继承
    2.在属性或方法的前面加上__,就变成私有属性或方法;如果前后都有__,不是私有属性或方法
    method1  原属性
    __method1  私有属性
    __method1__  _method1 非私有属性
    3.在普通方法里进行调用私有属性
    '''
    class Class_test1:
        __str1 = '这是一个私有的属性'
        str2 = '这是一个普通的属性ABC'
        def __init__(self):
            pass
        def __method1(self):
            print('这是一个私有方法')
        def method2(self):
            print('这是一个普通方法')
        def method3(self):
            print(self.__str1)  #调用私有属性
            self.__method1()  #调用私有方法
    tt2 = Class_test1() #实例化
    print(tt2.method2())  #这是一个普通方法,None
    print(tt2.str2)#这是一个普通的属性ABC
    #print(tt2.__str1) 会报错
    print(tt2.method3())  #这是一个私有的属性。这是一个私有方法。None
    
    '''
    所有的类都是object的子类,一个类无论是否声明继承object,实际都继承
    '''
    class Class_test2:
        """
        这是一个注释
        """
        pass
    print(Class_test2.__dict__) #{'__module__': '__main__'等等,__dict__就是类的属性
    print(Class_test2.__doc__) #显示类Class_test2的注释:这是一个注释
    print(Class_test2.__name__) #显示类名:Class_test2
    print(Class_test2.__base__)#显示父类名:<class 'object'>
    print(Square1.__bases__)#显示所有父类名:(<class '__main__.Rectangle1'>,)
    
    '''
    多继承:一个类可以有多个父类
    例如:学生可以学英语课、语文课、数学课
    '''
    class Math:
        def class1(self):
            print('数学课')
    class  English:
        def class2(self):
            print('英语课')
    class Chinese:
        def class3(self):
            print('语文课')
    class Student(Math,English,Chinese): #继承多个父类时,用逗号隔开;多个父类中有同名方法时,按照继承顺序进行调用
        pass
    man = Student() #实例化
    print(man.class1())  #学生类可以调用其他3个类的方法
    print(man.class2())
    print(man.class3())
    print(Student.__bases__) #父类名:(<class '__main__.Math'>, <class '__main__.English'>, <class '__main__.Chinese'>)
    
    '''
    多态:
    即不同内容的函数拥有同一个函数名,这样在类外即可通过同一个函数名调用不同内容的函数
    '''
    #案例1
    class Dog:
        def say(self):
            print('汪汪汪')
    class Cat:
        def say(self):
            print('喵喵喵')
    dog = Dog()  #实例化
    cat = Cat()
    #本来要调用应该是这样写:
    dog.say()
    cat.say()
    #利用多态
    def animal_say(obj):  #用一个函数作为接口,传入实例
        obj.say()
    animal_say(dog) #汪汪汪
    animal_say(cat) #喵喵喵
    #案例2
    class Fanguan1():
        pass
    class Yuxiangrousi(Fanguan1):
        def caidan(self):
            print('鱼香肉丝')
    class Gonbaojiding(Fanguan1):
        def caidan(self):
            print('宫保鸡丁')
    class Qingjiaotudousi(Fanguan1):
        def caidan(self):
            print('青椒土豆丝')
    guke1 = Yuxiangrousi()
    guke2 = Gonbaojiding()
    guke3 = Qingjiaotudousi()
    def fuwuyuan(obj):
        obj.caidan()
    fuwuyuan(guke1) #鱼香肉丝

    十七、异常与日志

    """
    异常与日志
    2022/5/17   
    作者:大九九
    """
    '''
    异常:程序运行时报错
    例如:print(1/0),报错:ZeroDivisionError: division by zero
    try except语句,至少有一个except,也可以有多个,也可以有一个else语句,一个finally语句
    所有的异常,都是Exception的子类,或者子类的子类
    
    常见的异常:
    BaseException 所有异常的基类:
      SystemExit 解释器请求退出
      KeyboardInterrupt 用户中断执行(通常是输入^C)
    Exception 常规错误的基类
        FileNotFoundError  --------找不到文件异常
      StopIteration 迭代器没有更多的值
      GeneratorExit 生成器(generator)发生异常来通知退出
      StandardError 所有的内建标准异常的基类
      ArithmeticError 所有数值计算错误的基类
      FloatingPointError 浮点计算错误
      OverflowError 数值运算超出最大限制
      ZeroDivisionError 除(或取模)零 (所有数据类型)
      AssertionError 断言语句失败
      AttributeError 对象没有这个属性
      EOFError 没有内建输入,到达EOF 标记
      EnvironmentError 操作系统错误的基类
      IOError 输入/输出操作失败
      OSError 操作系统错误
      WindowsError 系统调用失败
      ImportError 导入模块/对象失败
    LookupError 无效数据查询的基类
      IndexError 序列中没有此索引(index)----下标越界
      KeyError 映射中没有这个键
      MemoryError 内存溢出错误(对于Python 解释器不是致命的)
      NameError 未声明/初始化对象 (没有属性)-----未定义
      UnboundLocalError 访问未初始化的本地变量
      ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象
    RuntimeError 一般的运行时错误
      NotImplementedError 尚未实现的方法
      SyntaxError Python 语法错误
      IndentationError 缩进错误
      TabError Tab 和空格混用
      SystemError 一般的解释器系统错误
      TypeError 对类型无效的操作
      ValueError 传入无效的参数
    UnicodeError Unicode 相关的错误
      UnicodeDecodeError Unicode 解码时的错误
      UnicodeEncodeError Unicode 编码时错误
      UnicodeTranslateError Unicode 转换时错误
    Warning 警告的基类:
      DeprecationWarning 关于被弃用的特征的警告
      FutureWarning 关于构造将来语义会有改变的警告
      OverflowWarning 旧的关于自动提升为长整型(long)的警告
      PendingDeprecationWarning 关于特性将会被废弃的警告
      RuntimeWarning 可疑的运行时行为(runtime behavior)的警告
      SyntaxWarning 可疑的语法的警告
      UserWarning 用户代码生成的警告
    '''
    try:
        input1 = 5
        print(1 / input1)  #执行的程序,如果报错,执行下面的print('0不能作为分母')。如果不报错,继续执行try下面的代码
    except ZeroDivisionError:  #输入0
        print('0不能作为分母')
    except ValueError:   #输入abc
        print('您输入的不是数字')
    except Exception as e:  #兜底,不知道什么类型的异常时,捕获
        print('程序出现错误')
    else:#当程序没有出现任何异常,则执行else中的语句
        print('没有出现错误')
    finally:#无论程序是否出现异常,都会执行
        print('程序运行结束')
    
    try:
        raise IOError  #假装这里有异常,原来调试是否能捕获到异常,复现问题
    except IOError:
        print('程序出现了IO异常')
    
    '''
    日志
    logging模块,可以用来try...except记录日志
    '''
    import logging
    import traceback
    import time
    logging.basicConfig(level='ERROR',filename='D:/20220517_log1.log',filemode='a')
    #只会打印error以上的:ERROR:root:songqin CRITICAL:root:songqin
    #filemode='a',指定打开文件的默认模式是a
    '''
    不同等级的错误:
    logging.debug('songqin')
    logging.info('songqin')
    logging.warning('songqin')
    logging.error('songqin')
    logging.critical('songqin')
    默认打印的等级:
    WARNING:root:songqin
    ERROR:root:songqin
    CRITICAL:root:songqin
    '''
    logging.debug('songqin')
    logging.info('songqin')
    logging.warning('songqin')
    logging.error('songqin')
    logging.critical('songqin')
    
    try:
        input1 = int(input('请输入数字: '))
        print(1 / input1)  #执行的程序,如果报错,执行下面的print('0不能作为分母')。如果不报错,继续执行try下面的代码
    except :  #输入非数字
        logging.error(time.strftime('%y-%m-%d %H:%M:%S ')+traceback.format_exc())#把完整的报错信息写到文本中
    '''
    执行完,得到完整的报错信息:
    ERROR:root:Traceback (most recent call last):
      File "C:/Users/zhangxiaoqing/PycharmProjects/pythonProject1/test/Python_code/lesson17_log_exception.py", line 109, in <module>
        print(1 / input1)  #执行的程序,如果报错,执行下面的print('0不能作为分母')。如果不报错,继续执行try下面的代码
    ZeroDivisionError: division by zero
    
    加上时间后:
    ERROR:root:22-05-17 19:02:17Traceback (most recent call last):
      File "C:/Users/zhangxiaoqing/PycharmProjects/pythonProject1/test/Python_code/lesson17_log_exception.py", line 109, in <module>
        input1 = int(input('请输入数字: '))
    ValueError: invalid literal for int() with base 10: 'djfkg'
    '''
    import os
    from loguru import logger
    logger.debug(111)
    logger.info(111)
    logger.warning(111)
    logger.error(111)
    logger.critical(111)
    '''
    得到5个级别:美观度较好
    2022-05-17 19:07:51.465 | DEBUG    | __main__:<module>:127 - 111
    2022-05-17 19:07:51.465 | INFO     | __main__:<module>:128 - 111
    2022-05-17 19:07:51.465 | WARNING  | __main__:<module>:129 - 111
    2022-05-17 19:07:51.465 | ERROR    | __main__:<module>:130 - 111
    2022-05-17 19:07:51.465 | CRITICAL | __main__:<module>:131 - 111
    '''
    if not os.path.exists('./log'):  #如果没有存在这个目录,就新建一个
        os.mkdir('./log')
    logfile = './log/log1.log'
    logger.add(logfile,rotation='4KB',compression='3KB')   #写入文件,把日志文件拆分,每个4kb。不超过4kb,不会被拆分
    for i in range(100):
        logger.info(111)

    十八、pytest框架与allure

    """
    lesson18_pytest   
    2022/5/18   
    作者:大九九
    """
    '''
    1.py测试文件必须以test_开头(或者以test_结尾)
    2.测试类必须以Test开头,并且不能有__init__方法
    3.测试方法必须以test开头
    4.断言必须使用assert, assert 预期结果==实际结果
    5.pytest框架向下兼容unittest框架
    6.测试结果"."表示测试通过,测试结果F表示测试不通过
    '''
    import os
    import pytest
    import allure
    
    # def test_c01():
    #      print('开始执行用例1')
    #      assert 1==1
    # def test_c02():
    #      print('开始执行用例2')
    #      assert 2==3
    
    #
    # class Test1:
    #     def setup_method(self):  #①
    #         print('正在进行初始化工作')
    #     def test_c01(self):  #②
    #         assert 1==1
    #     def test_c02(self):  #③
    #         assert 2==3
    #     def teardown_method(self):  #④
    #         print('正在进行收尾工作')
    #method级别运行顺序①②④①③④
    '''
    得到:
    .正在进行收尾工作
    正在进行初始化工作
    F正在进行收尾工作
    '''
    
    # class Test2:
    #     def setup_class(self):  #①
    #         print('正在进行初始化工作')
    #     def test_c01(self):  #②
    #         assert 1==1
    #     def test_c02(self):  #③
    #         assert 2==3
    #     def teardown_class(self):  #④
    #         print('正在进行收尾工作')
    '''
    class级别运行顺序①②③④
    得到:
    正在进行初始化工作
    .F正在进行收尾工作
    module级别,整个模块只运行一次
    '''
    # test_example1
    # @pytest.fixture(scope='class')  #装饰器,声明下面的函数是setup函数
    # #scope缺省值为function,还有class,module,session级别
    # #session级别,fixture的内容写到conftest.py文件中,目录内的所有文件共用这个配置
    # def fun1():
    #     print('测试开始')
    #     yield  #声明下面的代码是teardown的用法
    #     print('测试结束')
    # class Test1:
    #     def test_some_data(self,fun1):
    #         assert 1==2
    #     def test_some_data2(self,fun1):
    #         assert 2==3
    # if __name__ == '__main__':
    #     pytest.main(['lesson18_pytest.py','-s'])
    
    #allure
    #数据驱动 :其实就是把我们测试用例的数据放到excel,yaml,csv,mysql,然后通过去改变数据达到改变测试用例的执行结果 。
    list1=[[10,22],[2**25,33554432],[72,72]]
    '''
    1.story 是 feature 的子集,当测试用例有 @allure.feature、@allure.story 时,在报告上会先显示 feature,
    点开之后再显示 story【可以想象成,安徒生童话(feature)有很多个童话故事(story)】
    2.如果不加 @allure.feature、@allure.story 时,在Behaviors栏目下,测试用例都不会分类显示,当用例多的时候可能看的花里胡哨
    '''
    @allure.feature('层级1') #功能点的描述
    @allure.story('层级2') #故事
    @allure.title('层级3') #标题
    class Test10:
        @pytest.mark.parametrize('result,real_result',list1)
        #传两个参数@pytest.mark.parametrize('参数名1,参数名2',[(参数1_data[0], 参数2_data[0]),(参数1_data[1], 参数2_data[1])]) 进行参数化
        def test_10(self,result,real_result):  #实际结果和预期结果的比较(就是参数1和参数2的比较断言)
            assert result==real_result
    
    #1、下载allure.zip
    #2、解压allure.zip到一个文件目录中
    # 3、将allure报告安装目录\bin所在的路径添加环境变量path中
    # 4、pip install  allure-pytest
    #
    # 测试结果"."表示测试通过,测试结果F表示测试不通过
    if __name__ == '__main__':
        pytest.main(['lesson18_pytest.py','-s','--alluredir','./report'])  #-s表示运行执行print语句
        os.system('allure generate ./report -o ./report/report --clean')

    十九、思考题

    """
    面向对象思考题
    2022/5/11   
    作者:大九九
    """
    '''
    题目1:
    写一个猜数字游戏,需求如下:
    随机生成0-100之间的数字,让用户猜,如果用户猜对了,提示回答正确,游戏结束
    如果用户猜错了,给出对应的提示,最多允许猜7次
    '''
    #用类的思想
    import random
    class Think_num:
        def __init__(self):
            self.i = 1  #初始化,次数首先是1
            self.num = random.randint(0,100)  #得到随机数字
        def think(self,num):
            while True:
                    if self.i < 7:  #次数小于7
                        if num == self.num:
                            print(f'回答正确,系统随机数是{self.num}')
                            break
                        elif num < self.num:
                            print(f'猜错了,输小了,您已用了{self.i}次机会')
                            self.i +=1
                            num =  int(input('请继续输入0-100的数字: '))
                        elif int(num) > self.num:
                            print(f'猜错了,输大了,您已用了{self.i}次机会')
                            self.i += 1
                            num = int(input('请继续输入0-100的数字: '))
                    else:
                        print(f'7次机会已用完,游戏结束,实际的随机数是{self.num}')
                        break
    game = Think_num()
    num = int(input('请输入0-100的数字: '))
    game.think(num)
    
    #只用循环
    num1 = random.randint(0,100)
    for i in range(7):
        input_num = int(input('请输入0-100的数字: '))
        if input_num > num1:
            print('您输入的值过大')
        elif input_num < num1:
            print('您输入的值过小')
        else:
            print('回答正确')
            break
    else:  #for循环的else
        print('7次机会已用完,还是没猜中')
    """
    think3   
    2022/5/17   
    作者:大九九
    """
    '''
    题目3:
    写一个三角形的类,包含面积和周长的计算方法
    '''
    class Sanjiaoxing:
        def __init__(self,a,b,c):
            self.a = a
            self.b = b
            self.c = c
        def zhouchang(self):
            if self.a+self.b<=self.c or self.a+self.c<=self.b or self.b+self.c<=self.a:
                return '无法构成三角形,忽略周长'
            else:
                zhouchang = self.a+self.b+self.c
                return zhouchang
        def mianji(self):
            if self.a + self.b <= self.c or self.a + self.c <= self.b or self.b + self.c <= self.a:
                return '无法构成三角形,忽略周长'
            else:
                p = (self.a + self.b + self.c)/2  #半周长
                mianji = (p*(p-self.a)*(p-self.b)*(p-self.c))**0.5  #海伦公式
                return mianji
    sjx = Sanjiaoxing(3,4,5)
    print(sjx.mianji())
    print(sjx.zhouchang())
    """
    think4   
    2022/5/17   
    作者:大九九
    """
    '''
    题目:将九九乘法表写入文件中
    第一行:
    1*1=1
    第二行:
    1*2=2 2*2=4
    第三行:
    1*3=3 2*3=6  3*3=9
    '''
    
    # 九九乘法表
    #九九乘法表
    with open('D:/99乘法表_211103.txt','w+') as file1:
        for i in range(1,10):    #i控制外层循环
            for j in range(1,i+1):   #i+1控制内层循环
                file1.write(f'{j}*{i}={i*j}\t')
            file1.write('\n')
    """
    think2   
    2022/5/17   
    作者:大九九
    """
    
    '''
    题目2:
    要求大家用面向对象的设计编写一个python程序,实现一个文字游戏系统。
    1.动物园里面有10个房间,房间号从1 到 10。
    2.每个房间里面可能是体重200斤的老虎或者体重100斤的羊。
    游戏开始后,系统随机在10个房间中放入老虎或者羊。
    3.然后随机给出房间号,要求游戏者选择敲门还是喂食。
    
    如果选择喂食:
    喂老虎应该输入单词 meat,喂羊应该输入单词 grass
    喂对了,体重加10斤。 喂错了,体重减少10斤
    
    如果选择敲门:
    敲房间的门,里面的动物会叫,老虎叫会显示 ‘Wow !!’,羊叫会显示 ‘mie~~’。 动物每叫一次体重减5斤。
    
    
    游戏者强记每个房间的动物是什么,以便不需要敲门就可以喂正确的食物。 
    游戏3分钟结束后,显示每个房间的动物和它们的体重。
    '''
    '''
    自己的思路:(未成功)
    import random
    room = [1,2,3,4,5,6,7,8,9,10]
    dict1 = {}  #'1':'羊'
    animal = ["sheep","tiger"]
    tiger_weight = 200
    sheep_weight = 100
    class Game:
        def __init__(self):  #初始化,在每个房间里放入老虎或羊
            for i in room:
                dict1[i] = random.choice(animal)
            print(dict1)
        def room_number(self): #获取随机房间号
            room_num = random.randint(1,10)
            return room_num
        def feet(self,room_num,word): #喂食
            animal_room = dict1[room_num]
            if animal_room == 'tiger' and word == 'meat':
                tiger_weight =tiger_weight+10
            elif animal_room == 'sheep' and word == 'grass':
            else:
                tiger_weight -=10  
        def knock(self,room_num):  #敲门
            animal_room = dict1[room_num]
            if animal_room == 'tiger':
                tiger_weight -=5
                print('Wow !!)
            else:
                sheep_weight -=5
                print('mie~~')
    game = Game()
    room_num = game.room_num()
    word = input('请选择是喂食还是敲门: ')
    if word =='喂食':
        a = input('请选择喂meat还是grass: ')
        f = game.feet(room_num,a)
    else:
        k = game.knock(room_num)
    print(game.room_num())
    '''
    #老师的答案
    # 211101_面向对象思考题讲解
    #解题思路
    #新建一个老虎的类,老虎的体重是200,类里面有叫的方法,有吃的方法
    #新建一个羊的类,羊的体重是100,类里面有叫的方法,有吃的方法
    #新建一个房间的类
    #将老虎或羊的实例放入房间的实例
    #写游戏相关的代码①调用叫的方法②调用吃的方法③游戏时间的控制④游戏结束时显示每个房间的动物的种类与体重
    
    class Tiger:
        def __init__(self):
            self.name='老虎'
            self.weight=200
        def eat(self,food):
            if food=='meat':
                print('喂食正确')
                self.weight+=10
            elif food=='grass':
                print('喂食错误')
                self.weight-=10
        def roar(self):
            print('Wow!!')
            self.weight-=5
    
    class Sheep:
        def __init__(self):
            self.name=''
            self.weight=100
        def eat(self,food):
            if food=='grass':
                print('喂食正确')
                self.weight+=10
            elif food=='meat':
                print('喂食错误')
                self.weight-=10
        def roar(self):
            print('mie~~')
            self.weight-=5
    
    class Room:
        def __init__(self,animal):
            self.animal=animal
    
    roomlist=[]  #定义一个列表,用来存放房间的实例
    
    from random import randint
    for i in range(10):
        if randint(1,2)==1:  #在1和2之间随机取一个值
            animal=Tiger()  #实例化一个老虎
        else:
            animal=Sheep()  #实例化一个羊
        room=Room(animal)  #实例化一个房间,把动物的实例放进去
        roomlist.append(room)  #把房间的实例放到列表中
    
    import time
    start_time=time.time()  #记录游戏开始的时间
    while time.time()-start_time<=10:
        room_number=randint(0,9)  #随机选取一个房间
        random_room=roomlist[room_number]  #选取该房间
        load1=input(f'当前访问的是{room_number+1}号房间,请问是敲门还是喂食?1表示敲门,2表示喂食')
        if load1=='1':
            random_room.animal.roar()  #调用房间实例的动物实例的叫的方法
        elif load1=='2':
            food=input('请选择喂的食物  meat/grass')
            if food in ('meat','grass'):
                random_room.animal.eat(food)  #调用房间实例的动物实例的吃的方法
            else:
                print('您输入的食物不正确')
        else:
            print('请输入1或2')
    else:
        print('游戏结束')
        for i in range(len(roomlist)):
            print(f'{i+1}号房间的动物是{roomlist[i].animal.name},体重是{roomlist[i].animal.weight}')
  • 相关阅读:
    NET Core-TagHelper实现分页标签
    NET Core-学习笔记(三)
    NET Core-学习笔记(二)
    NET Core-学习笔记(一)
    MVC默认路由实现分页-PagerExtend.dll
    Tomcat优化
    JVM参数配置大全
    tomcat8+memcached session共享
    Tomcat+Nginx+Redis+MySQL实现反向代理、负载均衡、session共享
    搭建Tomcat应用服务器、tomcat虚拟主机及Tomcat多实例部署
  • 原文地址:https://www.cnblogs.com/dydxw/p/16241560.html
Copyright © 2020-2023  润新知