2021年12月

封装

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

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)

动态规划的思想是把一个大问题拆分成一个个小问题,并在解决这些小问题之后把其最优解保留下来,解后面的大问题时会用到这些小问题的解

例一:01背包:现有音响(3000元,重4),电脑(2000元,重3),吉他(1500元,重1),你有一个能装最大重量为4的背包,现在请找出能够获取最大利益的装货方式

一开始我们只考虑吉他,这种情况下,背包容量从1-4的最优装法都只有装入吉他这一种,最终的解为(1500)

avatar

接下来我们把音响也加入考虑,当背包容量在1-3的时候,依旧是只有拿吉他这种解法,但当容量到4的时候,这时候选择往背包里面装入音响比装入吉他利益要来的更高,所以我们在4这一格选择就放入音响,得到了这一行的结果

avatar

接下来我们把电脑加入考虑,当背包容量是1-2的时候,依旧还是拿吉他(1500),但当变成3的时候,我们发现选择拿电脑更合适(2000),而到4的时候,我们发现,如果拿电脑,我们还余下1的余量,而余量1的最优解是1500,于是我们同时拿了电脑和吉他,共3500,大于只拿音响的3000,于是最终解变成了电脑与吉他

avatar

我们不难发现,其实celli=max{celli-1,price[i]+celli-1](即当前物品价值加上剩余空间最大价值)},在计算时我们用到了前面的计算结果

例二:最大子段和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

思路:采用动态规划法,每一个元素都有以其为结尾的数组,这个数组的最大值取值有两种情况:如果前面以num[i-1]为结尾的数组大于零,则他的值等于前面那个数组的值加上自身,如果前面那个数组小于零,则这个数组的最大值就是这个元素本身,即sum[i]=max{sum[i-1]+num[i],num[i]},当整个数组遍历完,返回sum数组里面的最大值

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        length = len(nums)
        sum = [ i  for i  in range(length)]
        sum[0] = nums[0]
        if length > 0:
            for i in range(1,length):
                if sum[i-1] > 0:
                    sum[i] = sum[i-1] + nums[i]
                else:
                    sum[i] = nums[i]
            return max(sum)
        else:
            return nums[0]

基础操作

  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!')