分类 Python 下的文章

环境配置
https://help.aliyun.com/document_detail/315439.html
新版文档(推荐:
https://help.aliyun.com/document_detail/315448.html?spm=a2c4g.11186623.0.0.9a7d5c2aq4loIO
获取access_key_id
https://ram.console.aliyun.com/manage/ak?spm=a2c6h.12873639.article-detail.8.76c06f779m4CWj
获取region_id,记得删尖括号
https://next.api.aliyun.com/api/Rds/2014-08-15/DescribeRegions?lang=PYTHON&tab=DEBUG
添加endpoint,可以在openai的例子里面查看
https://help.aliyun.com/document_detail/315444.html

示例

此处开发一个能够筛选某地域rds当中白名单内含有某条地址的对象,以官方例子为模板做演示讲下思路

思路:拆成两个部分:查询rds实例列表+查询某个rds的白名单,本地环境开发

先来看查询实例列表的api DescribeDBInstances
https://help.aliyun.com/document_detail/26232.html?spm=a2c4g.11186623.0.0.10197aca0hvjOE
点击文档上的调试,可以进入在线调试界面,同时在右侧可以看到自动生成的代码
我们可以看到这里regionid是必填参数,我们以cn-hangzhou为例子填入生成代码

# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import sys

from typing import List

from alibabacloud_rds20140815.client import Client as Rds20140815Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_rds20140815 import models as rds_20140815_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient


class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client(
        access_key_id: str,
        access_key_secret: str,
    ) -> Rds20140815Client:
        """
        使用AK&SK初始化账号Client
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
#client的配置,client的初始化在下面的函数中实现
#https://help.aliyun.com/document_detail/315449.html
        config = open_api_models.Config(
            # 必填,您的 AccessKey ID,
            access_key_id=access_key_id,
            # 必填,您的 AccessKey Secret,
            access_key_secret=access_key_secret
        )
        # 访问的域名
        config.endpoint = f'rds.aliyuncs.com'
        return Rds20140815Client(config)

    @staticmethod
    def main(
        args: List[str],
    ) -> None:
        # 工程代码泄露可能会导致AccessKey泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html
       #实例化client
        client = Sample.create_client('accessKeyId', 'accessKeySecret')
        #初始化request,api自己的各种参数都加在这里
        describe_dbinstances_request = rds_20140815_models.DescribeDBInstancesRequest(
            region_id='cn-hangzhou'
        )
        #新版 SDK 的超时机制为 RuntimeOption -> Config 设置 -> 默认
        runtime = util_models.RuntimeOptions()
        try:
            # 复制代码运行请自行打印 API 的返回值
            #client带有所有openapi,可以通过client直接调用,此处是带参式调用
            #https://help.aliyun.com/document_detail/315453.html
            client.describe_dbinstances_with_options(describe_dbinstances_request, runtime)
        except Exception as error:
            # 如有需要,请打印 error
            UtilClient.assert_as_string(error.message)

    @staticmethod
    async def main_async(
        args: List[str],
    ) -> None:
        # 工程代码泄露可能会导致AccessKey泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html
        client = Sample.create_client('accessKeyId', 'accessKeySecret')
        describe_dbinstances_request = rds_20140815_models.DescribeDBInstancesRequest(
            region_id='cn-hangzhou'
        )
        runtime = util_models.RuntimeOptions()
        try:
            # 复制代码运行请自行打印 API 的返回值
            await client.describe_dbinstances_with_options_async(describe_dbinstances_request, runtime)
        except Exception as error:
            # 如有需要,请打印 error
            UtilClient.assert_as_string(error.message)


if __name__ == '__main__':
    Sample.main(sys.argv[1:])

当你调用了这个api,他便会返回给你一个长得像json格式的结果,不过本地调用跟网页调用结果有点不一样
这是网页调用出来的结构

{
  "TotalRecordCount": 0,
  "PageRecordCount": 0,
  "RequestId": "B08AAD66-63A2-5432-9C62-3721ADA6DE8C",
  "NextToken": "",
  "PageNumber": 1,
  "Items": {
    "DBInstance": []
  }
}

如果是本地调用,外面会再套一层壳,类型为阿里云自己的一种对象,如果你想取出其中的一项值,直接用.去取就行
比如说,我想把items当中的dbinstance中的实例id和实例名称给取出来

#结果是个对象
list = {}
ret1 = client.describe_dbinstances_with_options(describe_dbinstances_request, runtime)
ret2 = ret1.body.items.dbinstance #实例列表,返回结果里面有响应头header和body两层,我们要的数据在body
for item in ret2:
    list[item.dbinstance_id]=item.dbinstance_description

具体有哪些结构、要取出哪些,可以对比输出结果和文档,注意小写和下划线

这时你可能注意到这个api的一个说明
本接口支持如下两种方式查看返回数据:

  • 方式一:通过传入MaxResults参数设置每页的记录数,再通过NextToken参数设置翻页凭证来展示下一页的内容。NextToken取值为上一次调用DescribeDBInstances接口返回的NextToken参数值。
  • 方式二:通过PageSize参数设置每页的记录数,通过PageNumber参数进行翻页。

说明
上述两种方式只能任选其一。当返回的记录数较多时,推荐使用方式一,可以获得更快的查询速度

意思很明显,虽然不知道这家伙是怎么想的,总之你不能一次性列出所有的实例了(除非你的实例数小于100),那么要怎样才能翻页、列出所有的数据呢,我们来看看这里面提到的几个参数

看下我们刚才打印出来的结果,你会注意到里面有个东西叫做NextToken,如果你使用网页调试,你也可以在参数配置里面看到翻页参数这一类,很显然,我们得要手动输入nexttoken才能翻页,这东西的实现方式就是在你刚才调用的api里面加上这个参数(而且这个参数似乎空值会报错),那么我们可以另外在写一个函数,在原来的基础上给他加上这个参数,然后在脚本里面写一个判断,当我们的结果列表长度等于我们设置的一页的结果个数时,就调用一下我们这个翻页函数

#核心部分
        describe_dbinstances_request = rds_20140815_models.DescribeDBInstancesRequest(
            region_id='cn-hangzhou',
            max_results=100, #别忘了在第一次调用的函数里面也加上这个参数
            next_token=token #传参,当然,记得保留上次调用结果的token,取的方式同上
        )

现在,我们拥有了一个包含所有实例id和名称的字典,我们来查看他们当中谁满足我们的条件:去调用白名单api来完成这一任务
https://help.aliyun.com/document_detail/26241.html
这api肉眼可见的简单,只需要传入一个dbinstanceid就可以查询出我们想要的结果,你如果想偷懒可以随便填个例子生成代码然后再在那基础上面修改,至于返回的结果,处理方式也同上,后面也就不再多说,字符串处理str.find,结果可以用csv库输出成文件保存

封装

将属性和方法封装到一个抽象的类种,外界使用类创建对象,调用其方法,具体内部的细节外部不需要知道

class Gun:
    def __init__(self,model):
        self.model = model
        self.bullet_count = 0
    def add_bullet(self,count):
        self.bullet_count += count
    def shoot(self):
        while True:
            if self.bullet_count == 0:
                print('没子弹啦!')
                break
            else:
                print('突')
                self.bullet_count -= 1

class Soldier:
    def __init__(self,name,gun=None):
        self.name = name
        self.gun = gun
    def fire(self):
        if self.gun == None:
            print("你没有枪呀!")
        else:
            self.gun.add_bullet(30)
            self.gun.shoot()

AK = Gun("AK47")
zhangsan = Soldier('张三',AK)
zhangsan.fire()

多态

不同的子类对象继承相同的父类,通过重写父类方法,产生不同的执行结果,增加代码的灵活性

class Phone:
    def __init__(self,name):
        self.name = name
    def func(self):
        print('bibibibi,来电话了')

class Nokia(Phone):
    def func(self):
        print("砸个核桃给秀儿吃")

class Samsung(Phone):
    def func(self):
        print("嘀嘀嘀嘀嘀嘀......Booooooooooom!")

class Person:
    def __init__(self,name):
        self.name = name

    def use_phone(self,phone):
        print(f'{self.name}正在使用{phone.name}')
        phone.func()

诺基亚 = Nokia('诺基亚')
三星Note7 = Samsung('三星Note7')

张三 = Person('张三')

张三.use_phone(诺基亚)
张三.use_phone(三星Note7)

我们可以对类进行约束来达到标准化的目的:

  1. 父类中定义方法,但是这个方法啥都不干,或者使用元类来描述一个抽象方法
  2. 子类中再具体实现方法
#抽象类写法
# import abc
# class Payment(metaclass=abc.ABCMeta):
#     @abc.abstractmethod
#     def pay(self,money):
#         raise AttributeError('子类必须实现这个方法')

class Payment:
    def pay(self,money):
        print('你还没有实现具体的pay方法')

class QQpay(Payment):
    def pay(self,money):
        print(f'QQ支付{money}元')

class Wechatpay(Payment):
    def pay(self,money):
        print(f'微信支付{money}元')

class Alipay(Payment):
    def pay(self,money):
        print(f'支付宝支付{money}元')

def pay(obj,money):
    obj.pay(money)

a = QQpay()
b = Wechatpay()
c = Alipay()
pay(a,200)
pay(b,200)
pay(c,200)

递归:在一个函数内再调用这个函数本身
递归的最大深度是997,可以在sys里面修改

def hannuo(n,a,b,c):
    if n == 1:
        print(a,'-->',c)
    else:
        hannuo(n-1,a,c,b)#把n-1层放到b
        print(a,'-->',c)#把最后一层放到c
        hannuo(n-1,b,a,c)#把b上的n-1层放到c

n = int(input('please input one number'))
hannuo(n,'a','b','c')

二分法


l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

def two_search(l):
    n = len(l)
    a = int(input('please input a number'))
    left = 0
    right = n
    while left <= right:
        if l[(left+right)//2] < a:
            left = (left+right)//2
        elif l[(left+right)//2] > a:
            right = (left+right)//2
        elif l[(left+right)//2] == a:
            print('找到了',(left+right)//2+1)
            break

two_search(l)


在不修改原函数的功能的情况下,增加额外的功能,装饰器的返回值也是一个函数对象

import time

def func(fun):
    def inner():
        start = time.time()
        print(start)
        fun()
        print(time.time()-start)
    return inner

@func
def call1():
    print('hello wordl!')

call1()

等同于

import time

def func(fun):
    def inner():
        start = time.time()
        print(start)
        fun()
        print(time.time()-start)
    return inner


def call1():
    print('hello wordl!')

call1 = func(call1)
call1()

带多种参数的装饰器

import time

def func(fun):
    def inner(*args,**kwargs):
        start = time.time()
        print(start)
        fun(*args,**kwargs)
        print(time.time()-start)
    return inner

@func
def call1(*args,**kwargs):
    print(args)
    print(kwargs)

call1(1,5,6,'asdcxsc',[1,555,9590],zhangsan = 666)

但要注意,像上面这种写法,装上装饰器之后,原函数里面的相关信息(如注释、函数名称)等就会失效,如果想要保留这些信息,则需要用到wrapper装饰器

import time
from functools import wraps
def func(fun):
    @wraps(fun)
    def wrapper(*args,**kwargs):
        start = time.time()
        print(start)
        fun(*args,**kwargs)
        print(time.time()-start)
    return wrapper

@func
def call1(*args,**kwargs):
    '''sssss'''
    print(args)
    print(kwargs)

call1(1,5,6,'asdcxsc',[1,555,9590],zhangsan = 666)

print(call1.__doc__)

# 1638601036.3845785
# (1, 5, 6, 'asdcxsc', [1, 555, 9590])
# {'zhangsan': 666}
# 0.0
# sssss

带控制的装饰器

import time
# from functools import wraps
def outer(flag):
    def func(fun):
        def inner(*args,**kwargs):
            if flag:
                start = time.time()
                print(start)
                fun(*args,**kwargs)
                print(time.time()-start)
        return inner
    return func

@outer(True)
def call1(*args,**kwargs):
    '''sssss'''
    print(args)
    print(kwargs)

call1(1,5,6,'asdcxsc',[1,555,9590],zhangsan = 666)

基础操作

  1. 打开file = open('1.txt',访问方式,encoding='编码方式')
  2. text = file.read()
  3. 关闭file.close()

访问方式

r:只读
w:只写,如果存在会覆盖,文件不存在创建新文件
a:追加,如果存在指针会放在文件结尾,不存在创建
r+:读写,指针在开头,不存在刨出异常
w+:读写,存在会覆盖,不存在创建
a+读写,指针在结尾,不存在创建

按行读取

text = file.readline().strip()#strip去除结尾换行

for i in file.readlines():
    # readlines返回一个可迭代对象并且每个元素都是一行

with结构

with open('xxx.txt') as file1:
    text = file1.read()

案例

修改文件

import os with open('a.txt') as read_f,open('a.txt.new','w') as write_f:
 data = read_f.read() 
 data = data.replace('Hello','nihao') 
 write_f.write(data) 
 
os.remove('a.txt') 
os.rename('a.txt.new','a.txt')

计算总价

文件a.txt内容:每一行内容分别为商品名字,价钱,个数。
apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3
通过代码,将其构建成这种数据类型:[{'name':'apple','price':10,'amount':3},
{'name':'tesla','price':1000000,'amount':1}......] 并计算出总价钱。
file = open('1.txt','r',encoding='utf-8')
line = []
list = []
for i in file.readlines():
     line = i.strip().split(' ')
     print(line)
     dict = {'name':line[0],'price':line[1],'count':line[2]}
     list.append(dict)

print(list)
sum = 0
for i in list:
    sum = sum + float(i['price'])*float(i['count'])

print(sum)

file.close()

模拟用户注册登陆


用户的信息需要保存在文件db.txt中
菜单:
供用户 选择时注册还是登陆
注册:
由用户输入用户名和密码
密码必须由字母和数字组成,长度不得小于8位
密码需要输入两次,并且判断密码是否相等,如果不相等注册失败
注册成功的话需要将用户信息写入db.txt中.
登陆:
由用户输入用户名和密码
用户名不存在时返回“用户不存在"
用户名存在密码错误时返回“密码错误”
密码重试超过三次,15秒之内不允许登陆
登陆成功时返回“欢迎登陆成功!”
import re
def SingUp():#注册
    file = open('db.txt','a')
    username = input('please input your username')
    while True:
        password = input('please input your password')
        passwor2 = input('please input your password once again')
        if re.match("^(?:(?=.*[A-Za-z])(?=.*[0-9])).*$",password):
            if len(password) >=8:
                if password == passwor2:
                    file.write(f'{username} {password} \n')
                    print(f'welcom {username}')
                    break
                else:
                    print('the two password are different!please input again!')
            else:
                print('your password is too short!')
        else:
            print('password must have number and words!')


    file.close()

def SignIn():#登录
    list = []
    k = 0
    flag = 0
    flag1 = 0
    file = open('db.txt','r')
    cont = file.readlines()
    for i in cont:
        tmp = i.strip().split(' ')
        person = {'username':tmp[0],'password':tmp[1]}
        list.append(person)
        k += 1
    username = input('please input your username')
    for i in list:
        if username == i['username']:
            flag = 1
            flag1 = list.index(i)
            break
            # password = input('please input your password')
            # if password == i['password']:
            #     print(f'hello {username}!')
            # else:
            #     print('wrong password!')
            #     flag += 1
            # if flag > 3:
            #     break

        else:
            print('user do not exist!')
            break
    if flag == 1:
        for i in range(3):
            password = input('please input your password')
            if list[flag1]['password'] == password:
                print(f'hello {username}!')
                break
            else:
                print('wrong password!')
    file.close()


def Menu():#菜单
    print('''
-------------Welcome-------------
Please input a number to choose :
--1. signup--
--2. signin--
---------------------------------
    ''')

if __name__ == '__main__':
    while True:
        Menu()
        num = input()
        if num == '1':
            SingUp()
        if num == '2':
            SignIn()
        else:
            print('please input a right number!')

加时间戳版本

import re
import time
def SingUp():#注册
    file = open('db.txt','a')
    username = input('please input your username')
    while True:
        password = input('please input your password')
        passwor2 = input('please input your password once again')
        if re.match("^(?:(?=.*[A-Za-z])(?=.*[0-9])).*$",password):
            if len(password) >=8:
                if password == passwor2:
                    file.write(f'{username} {password} 0\n')
                    print(f'welcom {username}')
                    break
                else:
                    print('the two password are different!please input again!')
            else:
                print('your password is too short!')
        else:
            print('password must have number and words!')


    file.close()

def SignIn():#登录
    list = []
    k = 0
    flag = 0
    flag1 = 0
    times = 0
    now = time.time()
    file = open('db.txt','r')
    cont = file.readlines()
    for i in cont:
        tmp = i.strip().split(' ')
        person = {'username':tmp[0],'password':tmp[1],'timemark':float(tmp[2])}
        list.append(person)
        k += 1
    # print(list)
    username = input('please input your username')
    for i in list:
        if username == i['username']:
            if ((now - i['timemark']) > 15):
                flag = 1
                flag1 = list.index(i)
                break
            else:print('wait! 15s !',now)
        else:
            if list.index(i) == len(list) - 1:
                print('user do not exist!')
                break
    if flag == 1:
        for i in range(3):
            password = input('please input your password')
            if list[flag1]['password'] == password:
                print(f'hello {username}!')
                break
            else:
                times += 1
                print('wrong password!')
                if times >= 3:
                    tt = list[flag1]['password']
                    cont[flag1] = f'{username} {tt} {time.time()}\n'
                    # print(cont)
                    with open('db.txt','w') as f:
                        for i in cont:
                            f.write(i)
    file.close()


def Menu():#菜单
    print('''
-------------Welcome-------------
Please input a number to choose :
--1. signup--
--2. signin--
---------------------------------
    ''')

if __name__ == '__main__':
    while True:
        Menu()
        num = input()
        if num == '1':
            SingUp()
        if num == '2':
            SignIn()
        else:
            print('please input a right number!')