python接口自动化之python

2021-03-25  本文已影响0人  三观正_1e5f

一、python入门

1. python介绍

1.1 python可运用范围

1.1.1 脚本、小工具

import random
import win32api
import time
import win32con

names = ['张三', '李四', '王五', '小六']
name = random.choice(names)
print("抽到谁谁是大帅比!")
print("倒计时开始~")
for num in range(3):
     time.sleep(1)
     print(3-num)
time.sleep(1)
win32api.MessageBox(0, name, "提示", win32con.MB_ICONASTERISK)

1.1.2 单个接口测试

import requests
import json


def config():
    # 拉取配置,获取配置列表
    # url
    url = "http://17620533205.wicp.vip:46685/logout"
    # 请求头
    # headers = {
    #     'Content-Type': 'application/x-www-form-urlencoded'
    # }
    # 请求参数
    data = {
        'account': '111000',
        'password': '123456'
    }
    r1 = requests.post(url, json=data)
    # 以json数据类型接收,传给r2,r2即整个接口测试返回的数据
    r2 = r1.json()
    print(json.dumps(r2, sort_keys=True, indent=4, separators=(',', ':'), ensure_ascii=False))


config()

1.1.3 selenium

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
url = 'https://dev.umaicloud.com/login'
# 访问网页登录页
driver.get(url)
# 点击账号输入框和输入账号
driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/div[1]/div[2]/div[1]/form/div[1]/div/div/input').send_keys(
    'xxxxx')
# 点击密码输入框输入密码
driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/div[1]/div[2]/div[1]/form/div[2]/div/div/input').send_keys(
    'xxxxx')
# 点击登录按钮
driver.find_element_by_xpath('//*[@id="app"]/div/div[3]/div[1]/div[2]/div[1]/form/div[4]/div/button').click()
time.sleep(10)
print("登录成功")
# 关闭浏览器
driver.quit()

# 八大定位元素方法
# find_element_by_name
# find_element_by_id
# find_element_by_xpath
# find_element_by_link_text
# find_element_by_partial_link_text
# find_element_by_tag_name
# find_element_by_class_name
# find_element_by_css_selector

1.1.4 appium

# -*- encoding=utf8 -*-
__author__ = "Administrator"
from airtest.core.api import *
auto_setup(__file__)
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

def open_app(start_time):
 stop_app('com.tencent.mm')
 start_app('com.tencent.mm')
 sleep(2)
 items_elements = poco(name='com.tencent.mm:id/b2p').offspring('com.tencent.mm:id/e0n')
 names = list(map(lambda x: x.get_text(), items_elements))
 target = "调试"
 index = names.index(target)
 print([index])
 print(items_elements[index])
 items_elements[index].click()
 while True:
     times = time.strftime("%H:%M:%S")
     sleep(1)
     if times >= start_time:
         while True:
             try:
                 msg_list = poco("com.tencent.mm:id/alz").child("android.widget.RelativeLayout").offspring("com.tencent.mm:id/ak4")
             except Exception:
                 print("暂无红包,继续等待!")
             else:
                 while True:
                     for msg in msg_list:
                         red_package = msg.offspring("com.tencent.mm:id/r6")
                         invalid = msg.offspring("com.tencent.mm:id/aa5").offspring("com.tencent.mm:id/qv")
                         if red_package:
                             print("发现红包")
                             if invalid.exists() and (invalid.get_text() == '已领取' or invalid.get_text() == '已被领完'):
                                 print("无效红包")
                                 continue
                             else:
                                 print("有效红包,正在抢~")
                                 red_package.click()
                                 open_btn = poco("com.tencent.mm:id/dbr")
                                 if open_btn.exists():
                                     open_btn.click()
                                 else:
                                     print("来晚一步,已被抢完~")
                                 keyevent('BACK')

     else:
         print(times)


open_app("10:29:00")

1.1.5 爬虫

import requests
import re
from urllib import parse
from win32com.client import Dispatch
import time
import win32api
import pyperclip
from DownloadMovie import download


class dytt(object):
 def __init__(self):
     pass

 @staticmethod
 def get_id():
     name = parse.quote(input("请输入你要下载的电影名称:"), encoding='gbk')
     url = "http://s.ygdy8.com/plus/so1.php?typeid=1&keyword=" + name
     headers = {
         "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
         "Accept-Encoding": "gzip, deflate",
         "Accept-Language": "zh-CN,zh;q=0.9",
         "Connection": "keep-alive",
         "Cookie": "UM_distinctid=16f9ecd77256b4-07ee71ccac26da-376b4502-1fa400-16f9ecd77262a1",
         "Host": "s.ygdy8.com",
         "Upgrade-Insecure-Requests": "1",
         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
     }
     r = requests.get(url, headers=headers, verify=False)
     r.encoding = 'gbk'
     # print(r.text)
     result1 = re.findall("<a href='/html/gndy/.+?</a>", r.text, re.S)
     # print(result1)
     if len(result1) == 0:
         print("未获取到资源~正在切换路线寻找资源···")
         names = parse.unquote(name, encoding='gbk')
         # print(names)
         download(names)
         time.sleep(3)
         quit()
     elif len(result1) == 1:
         result2 = str(re.findall("html/gndy/.+?.html", str(result1), re.S)).strip('[""]').strip("'")
         # print(result2)
         return result2
     else:
         for i in range(len(result1)):
             print(f"{i + 1}、", result1[i].strip("<a href=</a>"))
             i += 1
         num = int(input("请输入你要下载的电影序号:"))
         result2 = str(re.findall("html/gndy/.+?.html", result1[num - 1], re.S)).strip('[""]').strip("'")
         # print(result2)
         return result2

 @staticmethod
 def get_download_url():
     movie_id = dytt.get_id()
     requests.packages.urllib3.disable_warnings()
     url = "https://www.ygdy8.com/" + movie_id
     # print(url)
     r = requests.get(url, verify=False)
     r.encoding = 'gbk'
     # print(r.text)
     result = re.findall('>magnet:.+?<', r.text, re.S)
     # print(len(result))
     if len(result) == 0:
         result1 = re.findall('<a href="ftp:.+?">', r.text, re.S)
         if len(result1) == 0:
             result3 = re.findall('thunder.+?<', r.text, re.S)
             if len(result3) == 0:
                 print("暂未找到下载链接或下载链接失效!")
             elif len(result3) == 1:
                 print("正在打开迅雷,可能需要几秒钟~")
                 win32api.ShellExecute(0, 'open', 'C:\\Program Files\\Thunder\\Program\\ThunderStart.exe', '', '', 3)
                 time.sleep(5)
                 pyperclip.copy(result3)
             else:
                 for j in range(len(result3)):
                     print(f"{j + 1}、", result3[j])
                     j += 1
                 num = int(input("请选择:"))
                 pyperclip.copy(result3[num - 1])
         else:
             if len(result1) == 1:
                 result2 = str(result1).strip("['<a href=>']").strip('"')
                 # print(result2)
                 dytt.open_thunder(result2)
             else:
                 for m in range(len(result1)):
                     print(f"{m + 1}、", result1[m])
                     m += 1
                 num = int(input("请选择:"))
                 result2 = str(result1[num - 1]).strip("['<a href=>']").strip('"')
                 # print(result2)
                 dytt.open_thunder(result2)
     else:
         for n in range(len(result)):
             print(f"{n + 1}、", result[n].strip('><'))
             n += 1
         num = int(input("请输入你要下载的电影序号:"))
         result3 = result[num - 1].strip('><')
         dytt.open_thunder(result3)

 def open_thunder(downloadurl):
     print("正在打开迅雷,可能需要几秒钟~")
     win32api.ShellExecute(0, 'open', 'C:\\Program Files\\Thunder\\Program\\ThunderStart.exe', '', '', 3)
     time.sleep(5)
     thunder = Dispatch('ThunderAgent.Agent64.1')
     thunder.AddTask(downloadurl)
     thunder.CommitTasks()


dytt.get_download_url()

1.1.6 面向对象与面向过程

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
举个栗子:用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭。盖浇饭,就是菜饭分离,在一碗白米饭上面浇上一份盖菜,喜欢什么菜,你就浇上什么菜。

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展。

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护。
缺点:性能比面向过程低。

1.2 环境搭建(python+pycharm)

1.2.1 python下载

Python官网:https://www.python.org/

Python文档下载地址:https://www.python.org/doc/

\172.18.1.125\download添加到映射,长期共享学习软件。

1.2.2 python安装

https://www.runoob.com/python3/python3-install.html

1.2.3 python安装路径添加至path

如:D:\python;复制到系统变量中的path中。

1.2.4 检验安装

cmd中输入python,能进入python则安装成功,不能则环境有误或者安装不成功。

1.2.5 修改pip下载路径为国内源

在C:\Users\Administrator路径下新建pip文件夹,再进入pip文件夹中新建pip.ini文件,将下面三行复制保存即可。

[global]
trusted-host =  mirrors.aliyun.com
index-url = https://mirrors.aliyun.com/pypi/simple

1.2.6 升级pip版本到20版本+

python -m pip install --upgrade pip

1.2.7 查看安装的所有模块

pip list

1.2.8 设置pycharm运行Python的路径

打开pycharm——点击左上角文件-设置——搜索框中输入project——点击project interpreter右侧的下拉箭头——确认是否是你的Python的安装路径——如果找不到或路径不对,点击show all——再点击+添加——进入到new environment中——设置location(py文件的路径)——设置base interpreter(Python安装路径)——勾选下面inherit global···和make available

1.2.9 修改字体大小及主题

设置——搜索框搜索font——修改font、color scheme font、console font中的字体(推荐source code pro)、大小(16)、行距(1.0)

1.3 解释器及编码

1.3.1 解释器

未指定解释器时,在linux中运行代码可能会报错,需将下面一行复制在代码第一行

#!/usr/bin/python

1.3.2 编码

Python 文件中如果未指定编码,在执行过程可能会出现报错,Python3正常

#!/usr/bin/python

print ("你好,世界")

解决方法为只要在文件开头加入 # -*- coding: UTF-8 -*- 或者 # coding=utf-8 就行了,# coding=utf-8的=号两边不要空格

2.python基础(针对性讲解)

2.1 语法要求

2.2 常用运算符

2.3 条件语句

常规语句表达:

if 判断条件:
    执行语句……
else:
    执行语句……

多个条件判断表达:

if 判断条件1:
    执行语句1……
elif 判断条件2:
    执行语句2……
elif 判断条件3:
    执行语句3……
else:
    执行语句4……

2.4 循环语句

2.4.1 for

for num in range(10):
    print(num) # num会从0开始遍历,至10结束(不包含10),打印出来
0
1
2
3
4
5
6
7
8
9
for num in range(1, 10):
    print(num) # num从1开始遍历,至10结束(不包含10),打印出来
1
2
3
4
5
6
7
8
9
names = ['张三', '李四', '王五', '小六']
for name in names:
    print(name) # 遍历列表names,打印names所有元素
张三
李四
王五
小六
names = ['张三', '李四', '王五', '小六']
print(len(names))  # 获取列表长度 结果为4
for num in range(len(names)):  # 将长度作为一个范围,num会从0遍历,再把num作为序号加入到列表索引中
    print(names[num])
4
张三
李四
王五
小六

2.4.2 while

执行语句可以是单个语句或语句块。判断条件可以是任何表达式,任何非零、或非空(null)的值均为true。

当判断条件假 false 时,循环结束。

while 判断条件:
    执行语句……
age = 0
while age > 0:  # 条件不成立,所以不会执行该while语句
    print("条件不成立")
while age == 0:  # 因为age永远是0,所以陷入无限循环
    print("条件为真")

2.4.3 循环控制语句

age = 0
while True:  # 判断该条件是否为真,真就会一直循环往下执行代码,也可以表示为while age >= 0:
    age += 1  # 每过一年,我大一岁
    if age > 18:  # 如果我长大到了18岁,则跳出循环
        print("我超过18岁了")
        break  # 开始跳出
    elif age == 18:  # 当age=18岁时,会走到这,因为加了pass语句,执行了空语句,所以不会报错
        # print("我刚好18岁了")
        pass
    else:
        print("我还没到18岁呢")  # 判断我还没到18岁,会一直循环下去,知道18岁才跳出循环
        continue
        print("加了continue就不会走到这条语句,没加的话会执行完else里的语句再进行下一次循环")

2.5 变量类型

2.6 字符串

2.7 列表

2.8 字典

2.9 类型转换

2.9.1 各数据类型转换

有时候,我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可。

函数 描述
[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) 将一个整数转换为一个八进制字符串

2.9.2 字符串与字典

json.dumps()和json.loads()是json格式处理函数(可以这么理解,json是字符串)
(1)json.dumps()函数是将一个Python数据类型列表进行json格式的编码(可以这么理解,json.dumps()函数是将json丢掉,不要json,那就是将字典转化为字符串)
(2)json.loads()函数是将json格式数据转换为字典(可以这么理解,json.loads()函数是加载json,意味着要json,那就是将字符串转化为字典)

3. 脚本实例编写

二、接口测试

1. 内置模块

1.1 time

序号 函数及描述
1 time.altzone 返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用。
2 [time.asctime(tupletime]) 接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。
3 time.clock( ) 用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用。
4 [time.ctime(secs]) 作用相当于asctime(localtime(secs)),未给参数相当于asctime()
5 [time.gmtime(secs]) 接收时间戳(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst始终为0
6 [time.localtime(secs]) 接收时间戳(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)。
7 time.mktime(tupletime) 接受时间元组并返回时间戳(1970纪元后经过的浮点秒数)。
8 time.sleep(secs) 推迟调用线程的运行,secs指秒数。
9 [time.strftime(fmt,tupletime]) 接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。
10 time.strptime(str,fmt='%a %b %d %H:%M:%S %Y') 根据fmt的格式把一个时间字符串解析为时间元组。
11 time.time( ) 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。
12 time.tzset() 根据环境变量TZ重新初始化时间相关设置。

print(round(3.1415926, 2))


```python
3.14
import time

print(time.time())  # 打印当前时间戳
print(round(time.time()))  # 打印无小数点的时间戳
print(round(time.time()*100))  # 等于1588932416.278496四舍五入后的值*100,即12位时间戳
1588932416.278496
1588932416
158893241628

1.2 calendar

序号 函数及描述
1 calendar.calendar(year,w=2,l=1,c=6) 返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21* W+18+2* C。l是每星期行数。
2 calendar.firstweekday( ) 返回当前每周起始日期的设置。默认情况下,首次载入 calendar 模块时返回 0,即星期一。
3 calendar.isleap(year) 是闰年返回 True,否则为 False。>>> import calendar >>> print(calendar.isleap(2000)) True >>> print(calendar.isleap(1900)) False
4 calendar.leapdays(y1,y2) 返回在Y1,Y2两年之间的闰年总数。
5 calendar.month(year,month,w=2,l=1) 返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。
6 calendar.monthcalendar(year,month) 返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。
7 calendar.monthrange(year,month) 返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。日从0(星期一)到6(星期日);月从1到12。
8 calendar.prcal(year,w=2,l=1,c=6) 相当于 print calendar.calendar(year,w=2,l=1,c=6)
9 calendar.prmonth(year,month,w=2,l=1) 相当于 print calendar.month(year,month,w=2,l=1)
10 calendar.setfirstweekday(weekday) 设置每周的起始日期码。0(星期一)到6(星期日)。
11 calendar.timegm(tupletime) 和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间戳(1970纪元后经过的浮点秒数)。
12 calendar.weekday(year,month,day) 返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。

1.3 json

类型转换已经提到过,可以翻阅类型转换查看,下面也截取了一部分关键内容,可以多了解一点

函数 描述
json.dumps 将 Python 对象编码成 JSON 字符串
json.loads 将已编码的 JSON 字符串解码为 Python 对象
Python JSON
dict object
list, tuple array
str, unicode string
int, long, float number
True true
False false
None null
JSON Python
object dict
array list
string unicode
number (int) int, long
number (real) float
true True
false False
null None

1.4 random

1.5 os常用方法

1.6 hashlib

hashlib是一个提供字符加密功能的模块,包含MD5和SHA的加密算法,具体支持md5,sha1, sha224, sha256, sha384, sha512等算法。 该模块在用户登录认证方面应用广泛,对文本加密也很常见。

简单来说。就是三步:

1,建立加密对象。2,对字符串进行算法加密。3,获得16进制显示。

import hashlib

md5 = hashlib.md5()  # 创建hashlib的md5对象
md5.update('字符串'.encode('utf-8'))  # 将字符串载入到md5对象中,获得md5算法加密
new_md5 = md5.hexdigest()  # 通过hexdigest()方法,获得new_md5对象的16进制md5显示
print(new_md5)
cc4dd1da7e1a754534215f02fb9ba85d

注意:向对象中传入字符串时,在python3中需要对字符串进行 encode 操作必须为编码类型。使用.encode('UTF-8')的方法,使字符串变为bytes类型。

可以创建的加密算法有:md5,sha1, sha224, sha256, sha384, sha512。

import hashlib
new_md5 = hashlib.md5()
new_sha1 = hashlib.sha1()
new_sha256 = hashlib.sha256()

2. 第三方模块

2.1 requests

3. 组成

3.1 url

3.2 params的用法

3.3 data

3.4 headers

3.5 cookies和session

4. get请求

5. post请求

6. 代理

7. response属性

属性 描述
response.text 获取str类型(Unicode编码)的响应,即:url对应的页面内容
response.content 获取bytes类型的响应
response.status_code 获取响应状态码
response.headers 获取响应头
response.request 获取响应对应的请求
response.url 获取请求url
response.encoding 从HTTP header中猜测的响应内容编码方式

³äº�ç�¾åº¦</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使ç�¨ç�¾åº¦å��å¿
读</a>  <a href=http://jianyi.baidu.com/ class=cp-feedback>æ��è§�å��é¦�</a> äº¬ICPè¯�030173å�·  <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>


> 指定encoding后可以解决乱码,utf-8是通用编码,如遇到中文乱码问题,也可以使用gbk2312

```python
import requests
r = requests.get("http://www.baidu.com")
r.encoding = 'utf-8'
# r.encoding = 'gbk2312'
print(r.text)
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>

三、python进阶

1. 函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

1.1 规则

函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()

任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。

函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。

函数内容以冒号起始,并且缩进。

return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

1.2 调用

# 定义函数
def printme1():
    print("无参数,随便打印")


def printme2(strings):
    "打印任何传入的字符串"
    print(strings)
    return  # 未带表达式,不返回内容则不用写return,两者相同,所以返回的是None


def printme3(a):
    "打印任何传入的字符串"
    print(f"传进来的a的值为:{a}")
    b = 2
    c = a + b
    return c  # 带表达式,会返回a给调用方,经常这样表达:返回值=函数名(参数)


# 调用函数
printme1()  # 无参数,不用填写参数,直接函数名()调用即可
printme2("调用函数!")  # 有参数,需要提交参数,不然会报错
num = printme3(1)
print("返回的c的值为:{num}")

1.3 参数

1.3.1 必备参数

必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

调用printme()函数,你必须传入一个参数,不然会出现语法错误:

def printme(strings):
    "打印任何传入的字符串"
    print(strings)
printme()
TypeError: printme() missing 1 required positional argument: 'strings'

1.3.2 关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

def printme(string1, string2):
    "打印任何传入的字符串"
    print(string1)
    print(string2)
printme(string2="打赢我Java你就是第一", string1="php是世界上最好的语言!")  # 会按照关键字传值,所以顺序不重要
php是世界上最好的语言!
打赢我Java你就是第一

1.3.3 默认参数

调用函数时,默认参数的值如果没有传入,则被认为是默认值。下例会打印默认的age。

# 可写函数说明
def printinfo(name, age=35):
    "打印任何传入的字符串"
    print("Name: ", name)
    print("Age ", age)
    return
# 调用printinfo函数
printinfo(age=50, name="miki")  # 传递了age,所以age取最后一次传递的值
printinfo(name="miki")  # 没有传递age,但是age有默认值,所以不会报错
Name:  miki
Age  50
Name:  miki
Age  35

1.3.4 不定长参数

你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下:

def printinfo(arg1, *arg2):
    "打印任何传入的参数"
    print(arg1)
    for var in arg2:
        print(var)
    return
# 调用printinfo 函数
printinfo(10)
printinfo(70, 60, 50, 40)  # 70传递给了arg1,剩下的60 50 40···全部传给了arg2

1.4 return

函数中return后,需要在调用方接收值表达如下:

def test():
    a = 1
    return a
b = test()  # 右侧调用test函数,因为函数返回了a的值,所以在左侧设置一个变量b接收函数返回的a,为了避免看起来混乱,所以尽量改个名来接收返回的值
print(b)  # 此时b的值就是a,也就是1

1.5 全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:

total = 0  # 这是一个全局变量


# 可写函数说明
def sum(arg1, arg2):
    # 返回2个参数的和."
    total = arg1 + arg2  # total在这里是局部变量.
    print("函数内是局部变量 : ", total)

    return total


# 调用sum函数
sum(10, 20)
print("函数外是全局变量 : ", total)
函数内是局部变量 :  30
函数外是全局变量 :  0

2. file读写

open()方法,用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。

注意:使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法。

open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)。

open(file, mode='r')
完整的语法格式为:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

3. 异常处理

异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。

当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

3.1 try except else finally

try:
<语句>        #运行别的代码
except BaseException:  # BaseException为所有异常的基类,还有很多异常,RuntimeError、ValueError··
<语句>        #如果引发了异常,执行这,不执行else
else:
<语句>        #如果没有异常发生,就执行else,不会执行except
finally:
<语句>        #不管有无报错,都会执行这条语句
a = 1
try:
    print(b)  # 尝试打印b,但是b不存在,所以会报错
except Exception as e:  # 在这捕获了异常,且打印出异常,代码还会往下执行,不捕获的话走到print(b)就会终止运行
    print(e)
else:  #
    print(a)
finally:
    print("不管有无报错,都会执行这条语句")
<class 'Exception'>
不管有无报错,都会执行这条语句

3.2 try except else

try:
    正常的操作
except:
    发生异常,执行这块代码
else:
    如果没有异常执行这块代码

3.3 try finally

try:
<语句>
finally:
<语句>    #退出try时总会执行

3.4 触发异常

我们可以使用raise语句自己触发异常。

# 定义函数
def mye(level):
    if level < 1:
        raise(Exception, "Invalid level!")
        # 触发异常后,后面的代码就不会再执行


try:
    mye(0)  # 触发异常
except Exception:
    print(Exception, "Invalid level!")  # 这里捕获异常且打印异常
else:
    print(2)
<class 'Exception'> Invalid level!

3.5 用户自定义异常

通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。

class Networkerror(RuntimeError):
    def __init__(self, arg):
        self.args = arg
try:
    raise Networkerror("Bad hostname")
except Networkerror as e:
    print(e)

4. 面向对象

4.1 类

用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

4.2 实例化对象与访问属性

4.3 类方法和Python函数的区别

4.4 深入理解实例化对象

class 人(object):
    def __init__(self,性别,年龄,姓名等等):
        self.性别=性别
        self.年龄=年龄
        self.姓名=姓名
    def 吃饭(self,要吃的菜品):
        print(要吃的菜品)
    def 喝水(self,要喝的水)
        print(要喝的水)
    def 睡觉(self)
        pass
小明=人(男,20岁,小明)
小明.吃饭('青椒土豆丝')
小明.喝水('快乐肥宅水')
小明.睡觉()

在上面例子中,人要吃饭,人要喝水,所以吃饭和喝水都是人这一类中,因为类是具有相同属性(吃饭、喝水、睡觉)的集合,但是人类是个集合,是个名称,是个名词,是个抽象的东西,不是具体对象,“人类”不能实现吃饭,但人类中的小明可以实现吃饭和喝水,所以类需要一个具体对象去实现类中的方法,这就是实例化对象,然后用实例化的对象去执行类中的方法。

4.5 深入理解类方法、静态方法、类变量和实例变量

5. mysql

5.1 数据库连接与查询

Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。

  • fetchone(): 该方法获取下一个查询结果集。结果集是一个对象

  • fetchall():接收全部的返回结果行.

  • rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。

import MySQLdb

# 打开数据库连接
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8')

# 使用cursor()方法获取操作游标
cursor = db.cursor()

# 使用execute方法执行SQL语句
cursor.execute("SELECT VERSION()")

# 使用 fetchone() 方法获取一条数据
data = cursor.fetchone()

# 关闭数据库连接
db.close()

5.2 数据库更新操作

import MySQLdb

# 打开数据库连接
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8')

# 使用cursor()方法获取操作游标 
cursor = db.cursor()

# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')
try:
    # 执行SQL语句
    cursor.execute(sql)
    # 提交到数据库执行
    db.commit()
except:
    # 发生错误时回滚
    db.rollback()

# 关闭数据库连接
db.close()

5.3 删除操作

import MySQLdb

# 打开数据库连接
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8')

# 使用cursor()方法获取操作游标 
cursor = db.cursor()

# SQL 删除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > %s" % (20)
try:
    # 执行SQL语句
    cursor.execute(sql)
    # 提交修改
    db.commit()
except:
    # 发生错误时回滚
    db.rollback()

# 关闭连接
db.close()

6. 多线程

6.1 线程模块

Python3 通过两个标准库 thread 和 threading 提供对线程的支持。

thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。

threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

  • threading.currentThread(): 返回当前的线程变量。
  • threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

  • run(): 用以表示线程活动的方法。
  • start():启动线程活动。
  • join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
  • isAlive(): 返回线程是否活动的。
  • getName(): 返回线程名。
  • setName(): 设置线程名。

6.2 创建多线程

6.3 线程锁

当线程需要共享数据时,可能存在数据不同步的问题。

考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。

锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。

经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。

import threading
import time

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开启线程: " + self.name)
        # 获取锁,用于线程同步
        threadLock.acquire()
        print_time(self.name, self.counter, 3)
        # 释放锁,开启下一个线程
        threadLock.release()

def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

threadLock = threading.Lock()
threads = []

# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 开启新线程
thread1.start()
thread2.start()

# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)

# 等待所有线程完成
for t in threads:
    t.join()
print ("退出主线程")
开启线程: Thread-1
开启线程: Thread-2
Thread-1: Sun May 10 18:47:12 2020
Thread-1: Sun May 10 18:47:13 2020
Thread-1: Sun May 10 18:47:14 2020
Thread-2: Sun May 10 18:47:16 2020
Thread-2: Sun May 10 18:47:18 2020
Thread-2: Sun May 10 18:47:20 2020
退出主线程

7. 正则

7.1 re.match()和re.search()

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

re.match(pattern, string, flags=0)
# pattern 匹配的正则表达式
# string 要匹配的字符串
# flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等

我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
import re

line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)

if matchObj:
    print("matchObj.group() : ", matchObj.group())
    print("matchObj.group(1) : ", matchObj.group(1))
    print("matchObj.group(2) : ", matchObj.group(2))
else:
    print("No match!!")
matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter

re.match()和re.search()的区别:

re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None。

re.search 匹配整个字符串,直到找到一个匹配。

import re
 
line = "Cats are smarter than dogs"
 
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
   print ("match --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")
 
matchObj = re.search( r'dogs', line, re.M|re.I)
if matchObj:
   print ("search --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")
No match!!
search --> matchObj.group() :  dogs

7.2 re.sub()

Python 的re模块提供了re.sub用于替换字符串中的匹配项。

re.sub(pattern, repl, string, count=0, flags=0)
# pattern : 正则中的模式字符串
# repl : 替换的字符串,也可为一个函数
# string : 要被查找替换的原始字符串
# count : 可选参数,模式匹配后替换的最大次数,默认 0 表示替换所有的匹配
# flags : 可选参数,编译时用的匹配模式,数字形式
phone = "2004-959-559 # 这是一个电话号码"

# 删除注释
num = re.sub(r'#.*$', "", phone)
print("电话号码 : ", num)

# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print("电话号码 : ", num)
电话号码 :  2004-959-559 
电话号码 :  2004959559

7.3 re.compile()

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

re.compile(pattern[, flags])
# pattern : 一个字符串形式的正则表达式
# flags 可选,表示匹配模式,比如忽略大小写,多行模式等
# re.I 忽略大小写:
# re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
# re.M 多行模式
# re.S 即为' . '并且包括换行符在内的任意字符(' . '不包括换行符)
# re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
# re.X 为了增加可读性,忽略空格和' # '后面的注释

7.4 re.findall()

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

注意: match 和 search 是匹配一次 findall 匹配所有。

re.findall(string[, pos[, endpos]])
# string 待匹配的字符串
# pos 可选参数,指定字符串的起始位置,默认为0
# endpos 可选参数,指定字符串的结束位置,默认为字符串的长度
import re
 
pattern = re.compile(r'\d+')   # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
 
print(result1)
print(result2)
['123', '456']
['88', '12']

7.5 正则表达式模式

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n} 匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。
re{ n,} 精确匹配n个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b 匹配a或b
(re) 匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (...), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#...) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re) 匹配的独立模式,省去回溯。
\w 匹配数字字母下划线
\W 匹配非数字字母下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f]。
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9]。
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等。 匹配一个换行符。匹配一个制表符, 等
\1...\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

7.6 正则表达式修饰符

修饰符 描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

7.7 正则表达式实例

字符匹配

实例 描述
python 匹配 "python".

字符类

实例 描述
[Pp]ython 匹配 "Python" 或 "python"
rub[ye] 匹配 "ruby" 或 "rube"
[aeiou] 匹配中括号内的任意一个字母
[0-9] 匹配任何数字。类似于 [0123456789]
[a-z] 匹配任何小写字母
[A-Z] 匹配任何大写字母
[a-zA-Z0-9] 匹配任何字母及数字
[^aeiou] 除了aeiou字母以外的所有字符
[^0-9] 匹配除了数字外的字符

特殊字符类

实例 描述
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式
\d 匹配一个数字字符。等价于 [0-9]
\D 匹配一个非数字字符。等价于 [^0-9]
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'
上一篇 下一篇

猜你喜欢

热点阅读