Python基础知识点

**

基础知识点

**

代码调式

调试方式1:

print(输出可能出现错误的数据)

调试方式2

断言调式
需要输出错误信息的位置处 不使用print 而是使用assert
格式:
assert 满足需求的条件, 出现不满足条件的数据提示的错误信息
说明:
如果满足条件 代码继续向下执行
不满足条件 直接在断言的位置报错 提示错误信息

调试方法3:

模块logging中的内容
把输出错误信息的位置 替换成logging
1. 导入模块logging
2. 在需要输出错误信息的位置
   logging.info(提示的数据)
   如果只写这一句 不会显示想输出的数据内容 如果想显示提示的数据 在导入模块的下方添加
   logging.basicConfig(level=logging.INFO) ----> 使设置的info中的信息被输出

调试方法4:

pdb调试 --- 可以实现让代码一行一行执行
使用pdb测试的时候 需要启动pdb  启动语句是在控制台Terminal上书写的
	前提进入到py文件所在的路径
	指令: python -m pdb 执行的py文件
	进入到pdb环境下 输入n执行单行代码
	进入pdb环境下可以指令p 变量名 查看该变量的值
	结束调试 输入q

调试方法5:

debug断点调试

单元测试

单元测试:
	对一个模块, 一个函数或者是一个类进行正确检验的测试工具
比如:
	系统提供的函数:
		int() ----> 将数据转化为整型
需要导入模块 unittest
并且设置一个测试类 继承自unittest.TestCase

# value = [12, 13]
# res = int(value)
# print(res)

def cus_int(n):
    import math
    if type(n) == int:
        return n
    elif isinstance(n, float):
        return math.floor(n)
    elif isinstance(n, str):
        if n.isdigit():
            return eval(n)
        else:
            raise ValueError("数据不能转化为整型")
    elif isinstance(n, bool):
        return 1 if n else 0
    else:
        raise TypeError("不能转换指定类型")


def sort_list(src_list):
    #排序算法 : 冒泡 对列表数据大小进行降序排序
    for out in range(1, len(src_list)):
        for inner in range(0, len(src_list) - out):
            if src_list[inner] < src_list[inner+1]:
                src_list[inner], src_list[inner + 1] = src_list[inner + 1], src_list[inner]
    return src_list


from unittest_pack.test import cus_int, sort_list

import unittest

class Test(unittest.TestCase):
    #测试的方法
    def test_cus_int(self):
        '''
        第一个参数 要进行测验的执行函数
        第二个参数 设置函数运行之后的预期值
        第三个参数 如果函数运行结果 与 预期值不一致 提示的错误信息
        '''
        self.assertEqual(cus_int(5.12), 5, "转换结果不一致")

    def test_sort_list(self):
        self.assertEqual(sort_list([19, 27, 35, 41]), [41, 27, 35, 19], "排序失败")

if __name__ == '__main__':
    unittest.main()

SQL语句的优化

在虚拟环境中安装第三方插件django-debug-toolbar,然后在settings,urls文件中配置所需要的条件,配置好之后,刷新一下浏览器,就会出现debug-toolbar这个插件,在上面我们可以看到页面加载所需要的时间,和页面加载所需要的所有的sql语句等,然后根据加载时间和sql语句对代码进行优化,可以使用redis来进行缓存加载,对于一些sql语句所查询的对象,一般先对redis缓存进行查询,如果存在就直接缓存加载,如果不存在就去数据库查询,然后set到redis当中,当下次加载直接进入缓存获取。

  1. 请简述项目中优化sql语句执行的效率的方法

(1)选择最有效率的表名顺序

(2)WHERE子句中的连接顺序

(3)SELECT子句中避免使用‘*’

(4)用Where子句替换HAVING子句

(5)通过内部函数提高SQL效率

(6)避免在索引列上使用计算。

(7)提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉。

memcached缓存

memcached与redis相比的缺点是它的数据不能持久化,仅作为缓存来用。

对于单个对象的缓存适合用memcache

缓存整个页面

from django.views.decorators.cache import cache_page

@cache_page(60)

def index(request,page=1)

Celery

Celery是一个用Python开发的异步的分布式任务调度模块

当用户触发的一个操作需要较长时间才能执行完成时,可以把它作为任务交给Celery去异步执行,执行完再返回给用户。这段时间用户不需要等待,提高了网站的整体吞吐量和响应时间。

Celery有一下5个核心角色

Task

就是任务,有异步任务和定时任务

Broker

中间人,接收生产者发来的消息即Task,将任务存入队列。任务的消费者是Worker。Celery本身不提供队列服务,推荐用Redis或RabbitMQ实现队列服务。

Worker

执行任务的单元,它实时监控消息队列,如果有任务就获取任务并执行它。

Beat

定时任务调度器,根据配置定时将任务发送给Broker。

Backend

用于存储任务的执行结果

它的优点:

高可用性

倘若连接丢失或失败,职程和客户端会自动尝试连接,中间人会通过主/主,或主/从的方式复制来提高可用性

快速

单个celery进程每分钟可处理数以百万计的任务,而保持往返延迟在亚毫秒级别

灵活

celery几乎所有部分都可以拓展或单独使用。

session和cookie

  1. 简述Session的原理,并说明session和cookies的区别。

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

1、cookie数据存放在客户的浏览器上,

session数据放在服务器上

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗

考虑到安全应当使用session

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能

考虑到减轻服务器性能方面,应当使用COOKIE

  1. 什么是http无状态协议,怎么解决?

http协议无状态中的【状态】到底指的是什么?!

先来看这句话的另外两个概念:(标准的http协议是无状态的,无连接的)

标准的http协议指的是不包括cookies, session,application的http协议,他们都不属于标准协议,虽然各种网络应用提供商,实现语言、web容器等,都默认支持它

无连接指的是什么

每一个访问都是无连接,服务器挨个处理访问队列里的访问,处理完一个就关闭连接,这事儿就完了,然后处理下一个新的

无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接

两种用于保持HTTP连接状态的技术就应运而生了,一个是Cookie,而另一个则是Session

http和https

  1. http和https的区别和优缺点。

\1. http 的URL 以http:// 开头,https以https:// 开头。

\2. http 标准端口是80 ,https是443。

3.https 协议需要到ca申请证书,http不需要。

4.http 是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。

5.http 的连接很简单,是无状态的,https协议是由SSL+http协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全。

优点:

  1. 通过证书可以更信任服务器。
  2. 更安全,防篡改。

缺点:

  1. https 需要证书。
  2. 因为对传输进行加密,会一定程度增加cpu消耗。
  3. 由于https 要还密钥和确认加密算法的需要,所以首次建立连接会慢一些。
  4. 带宽消耗会增加。
    TCP和UDP
    tcp传输控制协议
    tcp传输控制协议是面向连接的,面向连接就是在正式通信前必须要与对方建立起连接,比如你给别人打电话,必须等线路接通了,对方拿起话筒才能相互通话。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,我们这里只做简单、形象的介绍
    我们来看看这三次对话的简单过程:
    \1. 主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;
    \2. 主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;
    \3. 主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。
    三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
    tcp传输控制协议可以提供可靠的服务,通过tcp连接传送的数据,无差错,不丢失,且按序到达,但是它的传输效率相对较低
    udp协议
    udp协议是面向非连接的协议,面向非连接协议就是在正式通信前不必与对方先建立连接,不管对方状态就直接发送,比如给别人发短信,你在发短信的时候,只需要输入对方手机号就OK了。
    UDP传输效率高,适用于对高速传输和实时性有较高的通信或广播通信。
    UDP支持一对一,一对多,多对一和多对多的交互通信。但是它的传输的数据容易有差错和会丢失数据。
    token会话机制
    用户使用终端向服务器提供可信凭证(一般登录是用户名密码,微信公众平台是appid+appsecret),服务端确认凭证正确,则返回授权的令牌(以下称Token)。这个Token是随机的字符串且与本次授权唯一相关。返回Token给终端的同时服务端也要一并保存Token,这样终端和服务端都只认Token,终端所有请求发送都需要携带此Token,服务端会验证和控制此Token。此时Token就有两个,一个是终端Token,一个是服务端Token,其中一个不对或没有,服务端都是拒绝的。
    举个例子,你上12306购票,购买过程就是授权你Token的过程,你的纸质票就是Token,另外一半对应的Token保存在12306那的DB里头,所有门闸就是网关,当你过门闸时会验证你Token是否对应DB的Token。你下车后,12306就把DB的Token标记处理掉,这样服务端就不会再认你手上的纸质票,票也就作废了。
    MTV

Django也是一个MVC框架,但在Django中,控制器接受用户输入的部分由框架自行处理,所以Django中更关注的是视图(Views),称为MTV模式:

M 代表模型(Model),数据存取层,该层处理与数据相关的所有事物:如何存取、包含哪些行为以及数据之间的关系等

T 代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面和其他类型的文档中进行显示

V 代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模型的相关逻辑,可看作模板与模型之间的桥梁

MVC的优缺点

2018年09月05日 22:02:57 SHUIPING_YANG 阅读数 1744

版权声明:经验之谈,不知能否换包辣条,另,转载请注明出处。 https://blog.csdn.net/zhezhebie/article/details/82431612

MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制(Controller)。 MVC模式的目的就是实现Web系统的职能分工。

Model层实现系统中的业务逻辑。

View层用于与用户的交互。

Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。

1、优点

1、耦合性低

视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。

模型是自包含的,并且与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。如果把数据库从MySQL移植到Oracle,或者改变基于RDBMS数据源到LDAP,只需改变模型即可。一旦正确的实现了模型,不管数据来自数据库或是LDAP服务器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互独立,改变其中一个不会影响其它两个,所以依据这种设计思想能构造良好的松耦合的构件。

2、重用性高

随着技术的不断进步,需要用越来越多的方式来访问应用程序。MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码,因为多个视图能共享一个模型,它包括任何WEB(HTTP)浏览器或者无线浏览器(wap),比如,用户可以通过电脑也可通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。例如,很多数据可能用HTML来表示,但是也有可能用WAP来表示,而这些表示所需要的命令是改变视图层的实现方式,而控制层和模型层无需做任何改变。由于已经将数据和业务规则从表示层分开,所以可以最大化的重用代码了。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。

3、生命周期成本低

MVC使开发和维护用户接口的技术含量降低。

4、部署快

使用MVC模式使开发时间得到相当大的缩减,它使程后端序员集中精力于业务逻辑,前端程序员集中精力于表现形式上。

5、可维护性高

分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。

6、有利软件工程化管理

由于不同的层各司其职,每一层不同的应用具有某些相同的特征,有利于通过工程化、工具化管理程序代码。控制器也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。

2、缺点

1、没有明确的定义

完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。同时由于模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。

2、不适合小型,中等规模的应用程序

花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。

3、增加系统结构和实现的复杂性

对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。

4、视图与控制器间的过于紧密的连接

视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。

5、视图对模型数据的低效率访问

依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

6、一般高级的界面工具或构造器不支持模式

改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,会造成MVC使用的困难。

oop

下面浅谈下我对OOP思想的理解,OOP思想中很重要的有五点,类,对象,还有面向对象的三大特征:封装、继承和多态。

封装:封装分为广义上的封装和狭义上的封装,广义上的封装呢就是函数的封装,将一些常用的代码封装成方法。而狭义的封装呢就是将无需对外暴露的内容隐藏起来,进行一个对象属性的私有化,然后提供对应的设置和获取的接口

继承:继承呢就是我们将一些共有的一些属性提取出来,然后自定义一个类,作为一个父类,然后我们可以继承这个父类,通过继承这个父类呢,子类就可以将这些共有的属性继承过来,继承性很好的解决了软件的可重用性问题。

多态:同一个父类实例化出来的子对象,通过调用同一个方法,且可以得到不相同的结果,这就是多态。

  • 多态可以增加代码的灵活度;
  • 以继承和重写父类方法为前提;
  • 是调用方法的技巧,不会影响到类的内部设计;
  1. Python的装饰器是什么,它的原理和作用分别是什么?

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

功能:1.引入日志;2.函数执行时间统计;3.执行函数前预备处理;4.执行函数后清理功能;5.权限校验;6.缓存

django rest framework

Django REST framework 的核心任务

 使用Django Rest framework的话,和之前使用Django时没多大差别,当然,更复杂的差别我也不知道

              1.   多了个serializers.py文件

   这个文件的作用是Serializers把querysets和model instances这些复杂的数据结构转化为native Python 以便于以json,xml或其它内容类型的形式render出去。

序列化器的主要工作就是将前端传入后端的JSON数据转换为ORM模型映射

              2. 视图的核心功能变了

                       3. 将数据库数据序列化为前端需要的格式,并返回

                       4. 将前端发送过来的数据反序列化为模型类对象,并保存到数据库中

什么是RESTful

REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

Django REST framework特性

  • 直观的 API web 界面
  • 多种身份认证和权限认证方式的支持
  • 内置了 OAuth1 和 OAuth2 的支持
  • 内置了限流系统
  • 根据 Django ORM 或者其它库自动序列化
  • 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要
  • 可扩展性,插件丰富
  • 广泛使用,文档丰富

RESTful API资料

drf总结:

django rest framework 是一种提供API接口的web程序开发框架,它是一个功能强大且灵活的工具包,用于构建webAPI,rest它不是一种技术而是一种软架构风格,中文翻译为表述性状态转移,它与一般的web程序开发框架最本质的区别就是,它是以资源的角度审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源。

Django REST framework 的核心任务

序列化器的主要工作就是将前端传入后端的JSON数据转换为ORM模型映射

  1. 视图的核心功能变了
    将数据库数据序列化为前端需要的格式,并返回给客户端
    将客户端发送过来的数据反序列化为模型类对象,并保存到数据库中

三范式简介:

概念:经过研究和对使用中问题的总结,对于设计数据库提出了一些规范,这些规范被称为范式
范式:
    1、列不可拆分
    2、唯一标识
    3、引用主键
说明:后一个范式,都是在前一个范式的基础上建立的

外键foreign key

作用:

    用于预防破坏表之间连接的动作

    也能防止非法数据插入外键列,因为它的值必须指向那个关系表中的值之一

谈一谈你对ORM的理解

ORM是“对象-关系-映射”的简称。

MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动

什么是中间件并简述其作用

中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。

中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。

django中间件的五个方法:

1、process_request:请求进来时,权限认证

2、process_view:路由匹配之后能够得到视图函数

3、process_exception:异常时执行

4、process_template_responseprocess:模板渲染时执行

5、process_response:请求有响应时执行

*args和**kwargs的作用

*args:(表示的就是将实参中按照位置传值,多出来的值都给args,且以元组的方式呈现)

**kwargs:(表示的就是形参中按照关键字传值把多余的传值以字典的方式呈现)

Python垃圾回收机制1

Python 主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。

1 引用计数

PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。

优点:

简单 实时性 缺点:

维护引用计数消耗资源 循环引用

2 标记-清除机制

基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。

3 分代技术

分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。

Python默认定义了三代对象集合,索引数越大,对象存活时间越长。

简述生成器、迭代器、可迭代对象以及应用场景

如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)刚才说过,很多容器都是可迭代对象,此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。但凡是可以返回一个 迭代器 的对象都可称之为可迭代对象

那么什么迭代器呢?它是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 next() (python2中实现 next() )方法的对象都是迭代器

生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。生成器(yield)不需要再像上面的类一样写 iter() 和 next() 方法了,只需要一个 yiled 关键字。 生成器有如下特征是它一定也是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。

闭包:

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

二分法查找

#只对排好序的列表进行查找 ‐‐‐ 以升序为例
def half_search(src_list, key):
        #设置查找初始区间
        min_index = 0
        max_index = len(src_list) ‐ 1
        #获得初始区间对应的中间索引
        mid_index = (min_index + max_index) // 2
        #循环查找: 要查找的元素 与 中间索引对应的元素不相等
        while key != src_list[mid_index]:
            if key > src_list[mid_index]:
                #更新查找区间 取后面查找
                min_index = mid_index + 1
            elif key < src_list[mid_index]:
                #更新区间 去前面找
                max_index = mid_index ‐ 1
            #上面的两种情况 都更新了区间范围 需要判断区间的合理性
            #[0, 1]
            if max_index >= min_index:
              #区间是合法的 获取该区间下的中间索引
              mid_index = (min_index + max_index) // 2
            else:
                #区间不合法了 结束查找
                return ‐1
        #出了循环 代表数据已经找到了 返回对应的位置
        return mid_index
res = half_search([34, 51, 66, 72, 83], 183)
print(res)

linux命令

常用命令

显示目录和文件的命令

   Ls:用于查看所有文件夹的命令。

   Dir:用于显示指定文件夹和目录的命令   Tree: 以树状图列出目录内容

   Du:显示目录或文件大小 

 
修改目录,文件权限和属主及数组命令
   Chmod:用于改变指定目录或文件的权限命令。

   Chown:用于改变文件拥有属性的命令。

   Chgrp:用于改变文件群组的命令。

   Chattr:用于设置文件具有不可删除和修改权限。

   Lsattr:用于显示文件或目录的隐藏属性。

 
创建和删除目录的命令
   Mkdir:用于创建目录

   Rmdir:用于删除空的目录

   Rm -f:用于删除不为空的目录

 

创建和删除,重命名,复制文件的命令

  Touch:创建一个新的文件

   Vi:创建一个新的文件

   Rm:删除文件或目录

   Mv:重命名或移动文件的命令

   Cp:复制命令

   Scp:用于将本地的文件或目录复制到远程服务器

   Wget:用于下载ftp或http服务器文件到本地。

 

显示文件内容的命令
   Cat:用于显示指定文件的全部内容

   More:用分页的形式显示指定文件的内容

   Less:用分页的形式显示指定文件的内容,区别是more和less翻页使用的操作键不同。

   Head:用于显示文件的前n行内容。

   Tail:用于显示文件的后n行内容。

   Tail -f:用于自动刷新的显示文件后n行数据内容。

 

查找命令

   Find:查找指定目录或文件的命令。

   Whereis:查找指定的文件源和二进制文件和手册等

   Which:用于查询命令或别名的位置。

   Locate:快速查找系统数据库中指定的内容。

   Grep:在指定的文件或标准输出,标准输入内,查找满足条件的内容。

 
关机和重启计算机的命令
     

   Shutdown:-r 关机后立即重启

             -k 并不真正的关机,而只是发出警告信息给所有用户

             -h 关机后不重新启动

   Poweroff:用于关机和关闭电源

   Init:改变系统运行级别

        0级用于关闭系统

        1 级用于单一使用者模式

        2级用来进行多用户使用模式(但不带网络功能)

        3级用来进行多用户使用模式(带网络全功能)

        4级用来进行用户自定义使用模式

        5级表示进入x  windows时的模式

        6级用来重启系统

   Reboot: 用于计算机重启

   Halt:用于关闭计算机系统

 
压缩和打包命令
   Tar:用于多个文件或目录进行打包,但不压缩,同时也用命令进行解包

   Gzip:用于文件进行压缩和解压缩命令,文件扩展名为.gz结尾。

   Gunzip:用于对gzip压缩文档进行解压缩。

   Bzip2:用于对文件或目录进行压缩和解压缩

   Bzcat:用于显示压缩文件的内容。

   Compress/un compress: 压缩/解压缩.Z文件

   Zcat:查看z或gz结尾的压缩文件内容。

   Gzexe:压缩可执行的文件

   Unarg:解压缩.arj文件

   Zip/unzip:压缩解压缩.zip文件

 
用户操作命令
   Su:切换用户命令

   Sudo:一系统管理员的身份执行命令

   Passwd:用于修改用户的密码

 
改变目录和查看当前目录命令
   Cd:进入工作目录

   Cd ..:会退到上一级命令

   Pwd:显示当前用户所在工作目录位置

 

文件连接命令

   Ln:为源文件创建一个连接,并不将源文件复制一份,即占用的空间很小。

        可以分为软件连接和硬链接。

        软连接:也称为符号连接,即为文件或目录创建一个快捷方式。

硬链接:给一个文件取多于一个名字,放在不同目录中,方便用户使用。

 

Ln命令参数如下:

   -f:在创建连接时,先将与目的对象同名的文件或目录删除。

   -d:允许系统管理者硬链接自己的目录。

   -i:在删除与目的对象同名文件或目录时先询问用户。

   -n:在创建软连接时,将目的对象视为一般的文件。

   -s:创建软连接,即符号连接。

   -v:在连接之前显示文件或目录名。

   -b:将在连接时会被覆盖或删除的文件进行备份。

 

帮助命令-----man

其他命令
   Who:显示系统中有那些用户在使用。

        -ami  显示当前用户

        -u:显示使用者的动作/工作

        -s:使用简短的格式来显示

        -v:显示程序版本

   Free:查看当前系统的内存使用情况

   Uptime:显示系统运行了多长时间

   Ps:显示瞬间进程的动态

   Pstree:以树状方式显示系统中所有的进程

   Date:显示或设定系统的日期与时间。

   Last:显示每月登陆系统的用户信息

   Kill: 杀死一些特定的进程

   Logout:退出系统

   Useradd/userdel:添加用户/删除用户

   Clear:清屏

   Passwd:设置用户密码

 

 

vi编辑器

   首先用vi命令打开一个文件

末行模式命令:

   :n,m w path/filename 保存指定范围文档( n表开始行,m表结束行)

   :q!    对文件做过修改后,强制退出

   :q     没有对文件做过修改退出

   Wq或x  保存退出

   dd   删除光标所在行

   : set number 显示行号

   :n 跳转到n行

   :s  替换字符串 :s/test/test2/g  /g全局替换 /也可以用%代替

   / 查找字符串

 

网络通信常用的命令

   Arp:网络地址显示及控制

   ftp:文件传输

   Lftp:文件传输

   Mail:发送/接收电子邮件

   Mesg:允许或拒绝其他用户向自己所用的终端发送信息

   Mutt E-mail 管理程序

   Ncftp :文件传输

   Netstat:显示网络连接.路由表和网络接口信息

   Pine:收发电子邮件,浏览新闻组

   Ping:用于查看网络是否连接通畅

   Ssh:安全模式下远程登陆

   Telnet:远程登录

   Talk:与另一用户对话

   Traceroute:显示到达某一主机所经由的路径及所使用的时间。

   Wget:从网路上自动下载文件

   Write:向其它用户终端写信息    Rlogin:远程登录

top        #每隔5秒显示所有进程的资源占用情况
top -d 2   #每隔两秒显示所有进程的资源占用情况
top -c     #每隔5秒显示所有进程的资源占用情况,并显示进程的命令行参数
top -p 12345 -p 6789 #每隔五秒显示pid为12345和pid为6789的两个进程的资源占用情况
top -d 2 -c -p 123456#每隔两秒显示pid为12345的进程的资源使用情况,并显示该进程启动的命令行参数

Linux进程查看命令 PS

ps命令
ps aux  #显示所有的进程
要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而ps命令就是最基本同时也是非常强大的进程查看命令.使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵尸、哪些进程占用了过多的资源等等.总之大部分信息都是可以通过执行该命令得到的.
ps命令最常用的还是用于监控后台进程的工作情况,因为后台进程是不和屏幕键盘这些标准输入/输出设备进行通信的,所以如果需要检测其情况,便可以使用ps命令了.
1)ps a 显示现行终端机下的所有程序,包括其他用户的程序。
2)ps -A 显示所有程序。
3)ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
4)ps -e 此参数的效果和指定"A"参数相同。
5)ps e 列出程序时,显示每个程序所使用的环境变量。
6)ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
7)ps -H 显示树状结构,表示程序间的相互关系。
8)ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
9)ps s 采用程序信号的格式显示程序状况。
10)ps S 列出程序时,包括已中断的子程序资料。
11)ps -t<终端机编号>  指定终端机编号,并列出属于该终端机的程序的状况。
12)ps u  以用户为主的格式来显示程序状况。
13)ps x  显示所有程序,不以终端机来区分。
最常用的方法是ps -aux,然后再利用一个管道符号导向到grep去查找特定的进程,然后再对特定的进程进行操作。

Linux查看端口号

netstat -a  #Linux查看所有的服务端口
netstat -t  #只显示tcp端口
netstat -u  #只显示udp端口
netstat -p  #显示进程标识符和程序名称
netstat -n  #不进行DNS轮询,显示ip(这样可以加快查询的时间)
#grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。 
netstat -ntlp|grep 3306 #使用grep命令进行所需端口的筛选查看
lsof -i  #查看端口的占用情况

python基础

UTF-8编码方式的特点:可以采用变长的存储形式在内存中存储数据

UTF-8和gbk的区别:

中文符号:

          utf-8 占三个字节

          gbk 占两个字节

英文符号:

          不管是那种都是占用1个字节

Python列表和元组的详细区别

1、列表是一个动态数组,我们可以根据自己的需要随意改变它的内容,另外我们还可以给列表添加新的数据来增加它的大小,这是因为动态数组支持resize操作,通过预留空间的做法,可以增加数组的容量。

2、元组是固定且不可改变的。这意味着一旦元组被创建,它的内容无法被修改或它的大小也无法该变,而且元组中元素的数据地址不允许发生变化,当元组中只有一个元素时需要在后面加哥逗号

3、元组缓存于python运行时环境,这意味着我们每次使用元组时无须访问内核去分配内存

4、用于列表的排序、替换、添加等方法也不适用于元组,适用于元组的主要运算有元组的合并、遍历、求元组的最大值和最小值等操作方法。

Linux查看系统资源命令

转载于:http://lxbins.blog.51cto.com/1089997/283663

top:

主要参数

d:指定更新的间隔,以秒计算。

q:没有任何延迟的更新。如果使用者有超级用户,则top命令将会以最高的优先序执行。

c:显示进程完整的路径与名称。

S:累积模式,会将己完成或消失的子行程的CPU时间累积起来。

s:安全模式。

i:不显示任何闲置(Idle)或无用(Zombie)的行程。

n:显示更新的次数,完成后将会退出to

显示参数:

PID(Process ID):进程标示号。

USER:进程所有者的用户名。

PR:进程的优先级别。

NI:进程的优先级别数值。

VIRT:进程占用的虚拟内存值。

RES:进程占用的物理内存值。

SHR:进程使用的共享内存值。

S:进程的状态,其中S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值是负数。

%CPU:该进程占用的CPU使用率。

%MEM:该进程占用的物理内存和总内存的百分比。

TIME+:该进程启动后占用的总的CPU时间。

Command:进程启动的启动命令名称,如果这一行显示不下,进程会有一个完整的命令行。

top命令使用过程中,还可以使用一些交互的命令来完成其它参数的功能。这些命令是通过快捷键启动的。

<空格>:立刻刷新。

P:根据CPU使用大小进行排序。

T:根据时间、累计时间排序。

q:退出top命令。

m:切换显示内存信息。

t:切换显示进程和CPU状态信息。

c:切换显示命令名称和完整命令行。

M:根据使用内存大小进行排序。

W:将当前设置写入~/.toprc文件中。这是写top配置文件的推荐方法。

还有一种办法是 ps -ef | sort -k7 ,将进程按运行时间排序,看哪个进程消耗的cpu时间最多。

数据库

事务的特性

1、原子性:事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行

2、一致性:几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。

3、隔离性:事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的

4、持久性:对任意已提交的事务,系统必须保证该事务对数据库的改变不丢失,即使数据库出现故障

redis和mysql的区别

redis是内存数据库,数据保存在内存中,速度快

mysql是关系型数据库,持久化存储,存放在磁盘里面,功能强大。检索的话,会涉及到一定的IO,数据访问也就慢

redis受到攻击怎么办

主从配置

持久化存储

redis不以root账户启动

设置复杂的密码

不允许key方式登录

mysql数据库引擎的区别

myisam默认引擎,不支持事务

innodb支持事务,原子性操作

flask与django的区别

flask:

1、flask是一个轻量级web框架,只有一个内核,默认依赖两个外部库:jinja2模板引擎和werkzeug WSGI工具集,自由、灵活、可拓展性强,开发者可以根据需求自己造轮子
2、适用于做小型网站以及web服务的API,开发大网站无压力,架构需自行设计
3、与关系型数据库结合不弱于django,而与非关系型数据库的结合远远优于django

django:

1、django是一个重量级的web框架,它走的是大而全的方向,注重的是高效的开发,功能齐全,它的内部有许多已经封装好的工具包,第三方库丰富,我们可以直接拿过来使用,能让开发者不用在选择应用上花费大量的时间
2、自带的ORM关系映射模型和模板引擎支持jinja等非官方模板引擎,灵活度不高
3、自带ORM使django和关系型数据库耦合度过高,如果要使用非关系型数据库,需要使用第三方库
4、自带自动化的后台管理
5、相对于flask,django的整体封闭性比较好,适合做企业级网站的开发
6、上手容易,开发文档详细、完善,资料丰富

python实现斐波那契数列

普通方法实现

a = 0
b = 1
while b <1000:
  print(b)
  a,b = b,a+b

递归方式实现

#递归方式实现,生成前20项
lis = []
for i in range(20):
  if i==0 or i==1:#第一二项 都为1
    lis.append(1)
  else:
    lis.append(lis[i-2]+lis[i-1])#从第三项开始每项为前两项之和
print(lis)    

设置缓存的两种方式

1、redis缓存

简单的连接方式

import redis
conn = redis.Redis(host='127.0.0.1',port=6379)
conn.set('key','vlaue')
#conn.setex('key','vlaue',20)
print(conn.get('key'))

2、memchache

import memcache
mc = memchache.Client(['127.0.0.1:11211'],debug=True)
mc.set('key','vlaue',timeout=60)
ret = mc.get('key')
print(ret)

celery运行原理图

面试知识准备

面试刷题网站:https://www.cnblogs.com/ZJGG/p/9875863.html

二、简历知识点

代码调式

调试方式1:

print(输出可能出现错误的数据)

调试方式2

断言调式
需要输出错误信息的位置处 不使用print 而是使用assert
格式:
assert 满足需求的条件, 出现不满足条件的数据提示的错误信息
说明:
如果满足条件 代码继续向下执行
不满足条件 直接在断言的位置报错 提示错误信息

调试方法3:

模块logging中的内容
把输出错误信息的位置 替换成logging
1. 导入模块logging
2. 在需要输出错误信息的位置
   logging.info(提示的数据)
   如果只写这一句 不会显示想输出的数据内容 如果想显示提示的数据 在导入模块的下方添加
   logging.basicConfig(level=logging.INFO) ----> 使设置的info中的信息被输出

调试方法4:

pdb调试 --- 可以实现让代码一行一行执行
使用pdb测试的时候 需要启动pdb  启动语句是在控制台Terminal上书写的
	前提进入到py文件所在的路径
	指令: python -m pdb 执行的py文件
	进入到pdb环境下 输入n执行单行代码
	进入pdb环境下可以指令p 变量名 查看该变量的值
	结束调试 输入q

调试方法5:

debug断点调试

单元测试

单元测试:
	对一个模块, 一个函数或者是一个类进行正确检验的测试工具
比如:
	系统提供的函数:
		int() ----> 将数据转化为整型
需要导入模块 unittest
并且设置一个测试类 继承自unittest.TestCase

# value = [12, 13]
# res = int(value)
# print(res)

def cus_int(n):
    import math
    if type(n) == int:
        return n
    elif isinstance(n, float):
        return math.floor(n)
    elif isinstance(n, str):
        if n.isdigit():
            return eval(n)
        else:
            raise ValueError("数据不能转化为整型")
    elif isinstance(n, bool):
        return 1 if n else 0
    else:
        raise TypeError("不能转换指定类型")


def sort_list(src_list):
    #排序算法 : 冒泡 对列表数据大小进行降序排序
    for out in range(1, len(src_list)):
        for inner in range(0, len(src_list) - out):
            if src_list[inner] < src_list[inner+1]:
                src_list[inner], src_list[inner + 1] = src_list[inner + 1], src_list[inner]
    return src_list


from unittest_pack.test import cus_int, sort_list

import unittest

class Test(unittest.TestCase):
    #测试的方法
    def test_cus_int(self):
        '''
        第一个参数 要进行测验的执行函数
        第二个参数 设置函数运行之后的预期值
        第三个参数 如果函数运行结果 与 预期值不一致 提示的错误信息
        '''
        self.assertEqual(cus_int(5.12), 5, "转换结果不一致")

    def test_sort_list(self):
        self.assertEqual(sort_list([19, 27, 35, 41]), [41, 27, 35, 19], "排序失败")

if __name__ == '__main__':
    unittest.main()

SQL语句的优化

在虚拟环境中安装第三方插件django-debug-toolbar,然后在settings,urls文件中配置所需要的条件,配置好之后,刷新一下浏览器,就会出现debug-toolbar这个插件,在上面我们可以看到页面加载所需要的时间,和页面加载所需要的所有的sql语句等,然后根据加载时间和sql语句对代码进行优化,可以使用redis来进行缓存加载,对于一些sql语句所查询的对象,一般先对redis缓存进行查询,如果存在就直接缓存加载,如果不存在就去数据库查询,然后set到redis当中,当下次加载直接进入缓存获取。

  1. 请简述项目中优化sql语句执行的效率的方法

(1)选择最有效率的表名顺序

(2)WHERE子句中的连接顺序

(3)SELECT子句中避免使用‘*’

(4)用Where子句替换HAVING子句

(5)通过内部函数提高SQL效率

(6)避免在索引列上使用计算。

(7)提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉。

memcached缓存

memcached与redis相比的缺点是它的数据不能持久化,仅作为缓存来用。

对于单个对象的缓存适合用memcache

缓存整个页面

from django.views.decorators.cache import cache_page

@cache_page(60)

def index(request,page=1)

Celery

Celery是一个用Python开发的异步的分布式任务调度模块

当用户触发的一个操作需要较长时间才能执行完成时,可以把它作为任务交给Celery去异步执行,执行完再返回给用户。这段时间用户不需要等待,提高了网站的整体吞吐量和响应时间。

Celery有一下5个核心角色

Task

就是任务,有异步任务和定时任务

Broker

中间人,接收生产者发来的消息即Task,将任务存入队列。任务的消费者是Worker。Celery本身不提供队列服务,推荐用Redis或RabbitMQ实现队列服务。

Worker

执行任务的单元,它实时监控消息队列,如果有任务就获取任务并执行它。

Beat

定时任务调度器,根据配置定时将任务发送给Broker。

Backend

用于存储任务的执行结果

它的优点:

高可用性

倘若连接丢失或失败,职程和客户端会自动尝试连接,中间人会通过主/主,或主/从的方式复制来提高可用性

快速

单个celery进程每分钟可处理数以百万计的任务,而保持往返延迟在亚毫秒级别

灵活

celery几乎所有部分都可以拓展或单独使用。

session和cookie

  1. 简述Session的原理,并说明session和cookies的区别。

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

1、cookie数据存放在客户的浏览器上,

session数据放在服务器上

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗

考虑到安全应当使用session

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能

考虑到减轻服务器性能方面,应当使用COOKIE

  1. 什么是http无状态协议,怎么解决?

http协议无状态中的【状态】到底指的是什么?!

先来看这句话的另外两个概念:(标准的http协议是无状态的,无连接的)

标准的http协议指的是不包括cookies, session,application的http协议,他们都不属于标准协议,虽然各种网络应用提供商,实现语言、web容器等,都默认支持它

无连接指的是什么

每一个访问都是无连接,服务器挨个处理访问队列里的访问,处理完一个就关闭连接,这事儿就完了,然后处理下一个新的

无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接

两种用于保持HTTP连接状态的技术就应运而生了,一个是Cookie,而另一个则是Session

http和https

  1. http和https的区别和优缺点。

\1. http 的URL 以http:// 开头,https以https:// 开头。

\2. http 标准端口是80 ,https是443。

3.https 协议需要到ca申请证书,http不需要。

4.http 是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。

5.http 的连接很简单,是无状态的,https协议是由SSL+http协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全。

优点:

  1. 通过证书可以更信任服务器。
  2. 更安全,防篡改。

缺点:

  1. https 需要证书。
  2. 因为对传输进行加密,会一定程度增加cpu消耗。
  3. 由于https 要还密钥和确认加密算法的需要,所以首次建立连接会慢一些。
  4. 带宽消耗会增加。
    TCP和UDP
    tcp传输控制协议
    tcp传输控制协议是面向连接的,面向连接就是在正式通信前必须要与对方建立起连接,比如你给别人打电话,必须等线路接通了,对方拿起话筒才能相互通话。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,我们这里只做简单、形象的介绍
    我们来看看这三次对话的简单过程:
    \1. 主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;
    \2. 主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;
    \3. 主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。
    三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
    tcp传输控制协议可以提供可靠的服务,通过tcp连接传送的数据,无差错,不丢失,且按序到达,但是它的传输效率相对较低
    udp协议
    udp协议是面向非连接的协议,面向非连接协议就是在正式通信前不必与对方先建立连接,不管对方状态就直接发送,比如给别人发短信,你在发短信的时候,只需要输入对方手机号就OK了。
    UDP传输效率高,适用于对高速传输和实时性有较高的通信或广播通信。
    UDP支持一对一,一对多,多对一和多对多的交互通信。但是它的传输的数据容易有差错和会丢失数据。
    token会话机制
    用户使用终端向服务器提供可信凭证(一般登录是用户名密码,微信公众平台是appid+appsecret),服务端确认凭证正确,则返回授权的令牌(以下称Token)。这个Token是随机的字符串且与本次授权唯一相关。返回Token给终端的同时服务端也要一并保存Token,这样终端和服务端都只认Token,终端所有请求发送都需要携带此Token,服务端会验证和控制此Token。此时Token就有两个,一个是终端Token,一个是服务端Token,其中一个不对或没有,服务端都是拒绝的。
    举个例子,你上12306购票,购买过程就是授权你Token的过程,你的纸质票就是Token,另外一半对应的Token保存在12306那的DB里头,所有门闸就是网关,当你过门闸时会验证你Token是否对应DB的Token。你下车后,12306就把DB的Token标记处理掉,这样服务端就不会再认你手上的纸质票,票也就作废了。
    MTV

Django也是一个MVC框架,但在Django中,控制器接受用户输入的部分由框架自行处理,所以Django中更关注的是视图(Views),称为MTV模式:

M 代表模型(Model),数据存取层,该层处理与数据相关的所有事物:如何存取、包含哪些行为以及数据之间的关系等

T 代表模板(Template),即表现层。该层处理与表现相关的决定:如何在页面和其他类型的文档中进行显示

V 代表视图(View),即业务逻辑层。该层包含存取模型及调取恰当模型的相关逻辑,可看作模板与模型之间的桥梁

MVC的优缺点

2018年09月05日 22:02:57 SHUIPING_YANG 阅读数 1744

版权声明:经验之谈,不知能否换包辣条,另,转载请注明出处。 https://blog.csdn.net/zhezhebie/article/details/82431612

MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制(Controller)。 MVC模式的目的就是实现Web系统的职能分工。

Model层实现系统中的业务逻辑。

View层用于与用户的交互。

Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。

1、优点

1、耦合性低

视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。

模型是自包含的,并且与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。如果把数据库从MySQL移植到Oracle,或者改变基于RDBMS数据源到LDAP,只需改变模型即可。一旦正确的实现了模型,不管数据来自数据库或是LDAP服务器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互独立,改变其中一个不会影响其它两个,所以依据这种设计思想能构造良好的松耦合的构件。

2、重用性高

随着技术的不断进步,需要用越来越多的方式来访问应用程序。MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码,因为多个视图能共享一个模型,它包括任何WEB(HTTP)浏览器或者无线浏览器(wap),比如,用户可以通过电脑也可通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。例如,很多数据可能用HTML来表示,但是也有可能用WAP来表示,而这些表示所需要的命令是改变视图层的实现方式,而控制层和模型层无需做任何改变。由于已经将数据和业务规则从表示层分开,所以可以最大化的重用代码了。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。

3、生命周期成本低

MVC使开发和维护用户接口的技术含量降低。

4、部署快

使用MVC模式使开发时间得到相当大的缩减,它使程后端序员集中精力于业务逻辑,前端程序员集中精力于表现形式上。

5、可维护性高

分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。

6、有利软件工程化管理

由于不同的层各司其职,每一层不同的应用具有某些相同的特征,有利于通过工程化、工具化管理程序代码。控制器也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。

2、缺点

1、没有明确的定义

完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。同时由于模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。

2、不适合小型,中等规模的应用程序

花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。

3、增加系统结构和实现的复杂性

对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。

4、视图与控制器间的过于紧密的连接

视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。

5、视图对模型数据的低效率访问

依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

6、一般高级的界面工具或构造器不支持模式

改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,会造成MVC使用的困难。

oop

下面浅谈下我对OOP思想的理解,OOP思想中很重要的有五点,类,对象,还有面向对象的三大特征:封装、继承和多态。

封装:封装分为广义上的封装和狭义上的封装,广义上的封装呢就是函数的封装,将一些常用的代码封装成方法。而狭义的封装呢就是将无需对外暴露的内容隐藏起来,进行一个对象属性的私有化,然后提供对应的设置和获取的接口

继承:继承呢就是我们将一些共有的一些属性提取出来,然后自定义一个类,作为一个父类,然后我们可以继承这个父类,通过继承这个父类呢,子类就可以将这些共有的属性继承过来,继承性很好的解决了软件的可重用性问题。

多态:同一个父类实例化出来的子对象,通过调用同一个方法,且可以得到不相同的结果,这就是多态。

  • 多态可以增加代码的灵活度;
  • 以继承和重写父类方法为前提;
  • 是调用方法的技巧,不会影响到类的内部设计;
  1. Python的装饰器是什么,它的原理和作用分别是什么?

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

功能:1.引入日志;2.函数执行时间统计;3.执行函数前预备处理;4.执行函数后清理功能;5.权限校验;6.缓存

django rest framework

Django REST framework 的核心任务

 使用Django Rest framework的话,和之前使用Django时没多大差别,当然,更复杂的差别我也不知道

              1.   多了个serializers.py文件

   这个文件的作用是Serializers把querysets和model instances这些复杂的数据结构转化为native Python 以便于以json,xml或其它内容类型的形式render出去。

序列化器的主要工作就是将前端传入后端的JSON数据转换为ORM模型映射

              2. 视图的核心功能变了

                       3. 将数据库数据序列化为前端需要的格式,并返回

                       4. 将前端发送过来的数据反序列化为模型类对象,并保存到数据库中

什么是RESTful

REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

Django REST framework特性

  • 直观的 API web 界面
  • 多种身份认证和权限认证方式的支持
  • 内置了 OAuth1 和 OAuth2 的支持
  • 内置了限流系统
  • 根据 Django ORM 或者其它库自动序列化
  • 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要
  • 可扩展性,插件丰富
  • 广泛使用,文档丰富

RESTful API资料

drf总结:

django rest framework 是一种提供API接口的web程序开发框架,它是一个功能强大且灵活的工具包,用于构建webAPI,rest它不是一种技术而是一种软架构风格,中文翻译为表述性状态转移,它与一般的web程序开发框架最本质的区别就是,它是以资源的角度审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源。

Django REST framework 的核心任务

序列化器的主要工作就是将前端传入后端的JSON数据转换为ORM模型映射

  1. 视图的核心功能变了
    将数据库数据序列化为前端需要的格式,并返回给客户端
    将客户端发送过来的数据反序列化为模型类对象,并保存到数据库中

三范式简介:

概念:经过研究和对使用中问题的总结,对于设计数据库提出了一些规范,这些规范被称为范式
范式:
    1、列不可拆分
    2、唯一标识
    3、引用主键
说明:后一个范式,都是在前一个范式的基础上建立的

外键foreign key

作用:

    用于预防破坏表之间连接的动作

    也能防止非法数据插入外键列,因为它的值必须指向那个关系表中的值之一

谈一谈你对ORM的理解

ORM是“对象-关系-映射”的简称。

MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动

什么是中间件并简述其作用

中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。

中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。

django中间件的五个方法:

1、process_request:请求进来时,权限认证

2、process_view:路由匹配之后能够得到视图函数

3、process_exception:异常时执行

4、process_template_responseprocess:模板渲染时执行

5、process_response:请求有响应时执行

*args和**kwargs的作用

*args:(表示的就是将实参中按照位置传值,多出来的值都给args,且以元组的方式呈现)

**kwargs:(表示的就是形参中按照关键字传值把多余的传值以字典的方式呈现)

Python垃圾回收机制1

Python 主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。

1 引用计数

PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。

优点:

简单 实时性 缺点:

维护引用计数消耗资源 循环引用

2 标记-清除机制

基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。

3 分代技术

分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。

Python默认定义了三代对象集合,索引数越大,对象存活时间越长。

简述生成器、迭代器、可迭代对象以及应用场景

如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)刚才说过,很多容器都是可迭代对象,此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。但凡是可以返回一个 迭代器 的对象都可称之为可迭代对象

那么什么迭代器呢?它是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 next() (python2中实现 next() )方法的对象都是迭代器

生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。生成器(yield)不需要再像上面的类一样写 iter() 和 next() 方法了,只需要一个 yiled 关键字。 生成器有如下特征是它一定也是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。

闭包:

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

二分法查找

#只对排好序的列表进行查找 ‐‐‐ 以升序为例
def half_search(src_list, key):
        #设置查找初始区间
        min_index = 0
        max_index = len(src_list) ‐ 1
        #获得初始区间对应的中间索引
        mid_index = (min_index + max_index) // 2
        #循环查找: 要查找的元素 与 中间索引对应的元素不相等
        while key != src_list[mid_index]:
            if key > src_list[mid_index]:
                #更新查找区间 取后面查找
                min_index = mid_index + 1
            elif key < src_list[mid_index]:
                #更新区间 去前面找
                max_index = mid_index ‐ 1
            #上面的两种情况 都更新了区间范围 需要判断区间的合理性
            #[0, 1]
            if max_index >= min_index:
              #区间是合法的 获取该区间下的中间索引
              mid_index = (min_index + max_index) // 2
            else:
                #区间不合法了 结束查找
                return ‐1
        #出了循环 代表数据已经找到了 返回对应的位置
        return mid_index
res = half_search([34, 51, 66, 72, 83], 183)
print(res)

linux命令

常用命令

显示目录和文件的命令

   Ls:用于查看所有文件夹的命令。

   Dir:用于显示指定文件夹和目录的命令   Tree: 以树状图列出目录内容

   Du:显示目录或文件大小 

 
修改目录,文件权限和属主及数组命令
   Chmod:用于改变指定目录或文件的权限命令。

   Chown:用于改变文件拥有属性的命令。

   Chgrp:用于改变文件群组的命令。

   Chattr:用于设置文件具有不可删除和修改权限。

   Lsattr:用于显示文件或目录的隐藏属性。

 
创建和删除目录的命令
   Mkdir:用于创建目录

   Rmdir:用于删除空的目录

   Rm -f:用于删除不为空的目录

 

创建和删除,重命名,复制文件的命令

  Touch:创建一个新的文件

   Vi:创建一个新的文件

   Rm:删除文件或目录

   Mv:重命名或移动文件的命令

   Cp:复制命令

   Scp:用于将本地的文件或目录复制到远程服务器

   Wget:用于下载ftp或http服务器文件到本地。

 

显示文件内容的命令
   Cat:用于显示指定文件的全部内容

   More:用分页的形式显示指定文件的内容

   Less:用分页的形式显示指定文件的内容,区别是more和less翻页使用的操作键不同。

   Head:用于显示文件的前n行内容。

   Tail:用于显示文件的后n行内容。

   Tail -f:用于自动刷新的显示文件后n行数据内容。

 

查找命令

   Find:查找指定目录或文件的命令。

   Whereis:查找指定的文件源和二进制文件和手册等

   Which:用于查询命令或别名的位置。

   Locate:快速查找系统数据库中指定的内容。

   Grep:在指定的文件或标准输出,标准输入内,查找满足条件的内容。

 
关机和重启计算机的命令
     

   Shutdown:-r 关机后立即重启

             -k 并不真正的关机,而只是发出警告信息给所有用户

             -h 关机后不重新启动

   Poweroff:用于关机和关闭电源

   Init:改变系统运行级别

        0级用于关闭系统

        1 级用于单一使用者模式

        2级用来进行多用户使用模式(但不带网络功能)

        3级用来进行多用户使用模式(带网络全功能)

        4级用来进行用户自定义使用模式

        5级表示进入x  windows时的模式

        6级用来重启系统

   Reboot: 用于计算机重启

   Halt:用于关闭计算机系统

 
压缩和打包命令
   Tar:用于多个文件或目录进行打包,但不压缩,同时也用命令进行解包

   Gzip:用于文件进行压缩和解压缩命令,文件扩展名为.gz结尾。

   Gunzip:用于对gzip压缩文档进行解压缩。

   Bzip2:用于对文件或目录进行压缩和解压缩

   Bzcat:用于显示压缩文件的内容。

   Compress/un compress: 压缩/解压缩.Z文件

   Zcat:查看z或gz结尾的压缩文件内容。

   Gzexe:压缩可执行的文件

   Unarg:解压缩.arj文件

   Zip/unzip:压缩解压缩.zip文件

 
用户操作命令
   Su:切换用户命令

   Sudo:一系统管理员的身份执行命令

   Passwd:用于修改用户的密码

 
改变目录和查看当前目录命令
   Cd:进入工作目录

   Cd ..:会退到上一级命令

   Pwd:显示当前用户所在工作目录位置

 

文件连接命令

   Ln:为源文件创建一个连接,并不将源文件复制一份,即占用的空间很小。

        可以分为软件连接和硬链接。

        软连接:也称为符号连接,即为文件或目录创建一个快捷方式。

硬链接:给一个文件取多于一个名字,放在不同目录中,方便用户使用。

 

Ln命令参数如下:

   -f:在创建连接时,先将与目的对象同名的文件或目录删除。

   -d:允许系统管理者硬链接自己的目录。

   -i:在删除与目的对象同名文件或目录时先询问用户。

   -n:在创建软连接时,将目的对象视为一般的文件。

   -s:创建软连接,即符号连接。

   -v:在连接之前显示文件或目录名。

   -b:将在连接时会被覆盖或删除的文件进行备份。

 

帮助命令-----man

其他命令
   Who:显示系统中有那些用户在使用。

        -ami  显示当前用户

        -u:显示使用者的动作/工作

        -s:使用简短的格式来显示

        -v:显示程序版本

   Free:查看当前系统的内存使用情况

   Uptime:显示系统运行了多长时间

   Ps:显示瞬间进程的动态

   Pstree:以树状方式显示系统中所有的进程

   Date:显示或设定系统的日期与时间。

   Last:显示每月登陆系统的用户信息

   Kill: 杀死一些特定的进程

   Logout:退出系统

   Useradd/userdel:添加用户/删除用户

   Clear:清屏

   Passwd:设置用户密码

 

 

vi编辑器

   首先用vi命令打开一个文件

末行模式命令:

   :n,m w path/filename 保存指定范围文档( n表开始行,m表结束行)

   :q!    对文件做过修改后,强制退出

   :q     没有对文件做过修改退出

   Wq或x  保存退出

   dd   删除光标所在行

   : set number 显示行号

   :n 跳转到n行

   :s  替换字符串 :s/test/test2/g  /g全局替换 /也可以用%代替

   / 查找字符串

 

网络通信常用的命令

   Arp:网络地址显示及控制

   ftp:文件传输

   Lftp:文件传输

   Mail:发送/接收电子邮件

   Mesg:允许或拒绝其他用户向自己所用的终端发送信息

   Mutt E-mail 管理程序

   Ncftp :文件传输

   Netstat:显示网络连接.路由表和网络接口信息

   Pine:收发电子邮件,浏览新闻组

   Ping:用于查看网络是否连接通畅

   Ssh:安全模式下远程登陆

   Telnet:远程登录

   Talk:与另一用户对话

   Traceroute:显示到达某一主机所经由的路径及所使用的时间。

   Wget:从网路上自动下载文件

   Write:向其它用户终端写信息    Rlogin:远程登录

top        #每隔5秒显示所有进程的资源占用情况
top -d 2   #每隔两秒显示所有进程的资源占用情况
top -c     #每隔5秒显示所有进程的资源占用情况,并显示进程的命令行参数
top -p 12345 -p 6789 #每隔五秒显示pid为12345和pid为6789的两个进程的资源占用情况
top -d 2 -c -p 123456#每隔两秒显示pid为12345的进程的资源使用情况,并显示该进程启动的命令行参数

Linux进程查看命令 PS

ps命令
ps aux  #显示所有的进程
要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而ps命令就是最基本同时也是非常强大的进程查看命令.使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵尸、哪些进程占用了过多的资源等等.总之大部分信息都是可以通过执行该命令得到的.
ps命令最常用的还是用于监控后台进程的工作情况,因为后台进程是不和屏幕键盘这些标准输入/输出设备进行通信的,所以如果需要检测其情况,便可以使用ps命令了.
1)ps a 显示现行终端机下的所有程序,包括其他用户的程序。
2)ps -A 显示所有程序。
3)ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
4)ps -e 此参数的效果和指定"A"参数相同。
5)ps e 列出程序时,显示每个程序所使用的环境变量。
6)ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
7)ps -H 显示树状结构,表示程序间的相互关系。
8)ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
9)ps s 采用程序信号的格式显示程序状况。
10)ps S 列出程序时,包括已中断的子程序资料。
11)ps -t<终端机编号>  指定终端机编号,并列出属于该终端机的程序的状况。
12)ps u  以用户为主的格式来显示程序状况。
13)ps x  显示所有程序,不以终端机来区分。
最常用的方法是ps -aux,然后再利用一个管道符号导向到grep去查找特定的进程,然后再对特定的进程进行操作。

Linux查看端口号

netstat -a  #Linux查看所有的服务端口
netstat -t  #只显示tcp端口
netstat -u  #只显示udp端口
netstat -p  #显示进程标识符和程序名称
netstat -n  #不进行DNS轮询,显示ip(这样可以加快查询的时间)
#grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。 
netstat -ntlp|grep 3306 #使用grep命令进行所需端口的筛选查看
lsof -i  #查看端口的占用情况

python基础

UTF-8编码方式的特点:可以采用变长的存储形式在内存中存储数据

UTF-8和gbk的区别:

中文符号:

          utf-8 占三个字节

          gbk 占两个字节

英文符号:

          不管是那种都是占用1个字节

Python列表和元组的详细区别

1、列表是一个动态数组,我们可以根据自己的需要随意改变它的内容,另外我们还可以给列表添加新的数据来增加它的大小,这是因为动态数组支持resize操作,通过预留空间的做法,可以增加数组的容量。

2、元组是固定且不可改变的。这意味着一旦元组被创建,它的内容无法被修改或它的大小也无法该变,而且元组中元素的数据地址不允许发生变化,当元组中只有一个元素时需要在后面加哥逗号

3、元组缓存于python运行时环境,这意味着我们每次使用元组时无须访问内核去分配内存

4、用于列表的排序、替换、添加等方法也不适用于元组,适用于元组的主要运算有元组的合并、遍历、求元组的最大值和最小值等操作方法。

Linux查看系统资源命令

转载于:http://lxbins.blog.51cto.com/1089997/283663

top:

主要参数

d:指定更新的间隔,以秒计算。

q:没有任何延迟的更新。如果使用者有超级用户,则top命令将会以最高的优先序执行。

c:显示进程完整的路径与名称。

S:累积模式,会将己完成或消失的子行程的CPU时间累积起来。

s:安全模式。

i:不显示任何闲置(Idle)或无用(Zombie)的行程。

n:显示更新的次数,完成后将会退出to

显示参数:

PID(Process ID):进程标示号。

USER:进程所有者的用户名。

PR:进程的优先级别。

NI:进程的优先级别数值。

VIRT:进程占用的虚拟内存值。

RES:进程占用的物理内存值。

SHR:进程使用的共享内存值。

S:进程的状态,其中S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值是负数。

%CPU:该进程占用的CPU使用率。

%MEM:该进程占用的物理内存和总内存的百分比。

TIME+:该进程启动后占用的总的CPU时间。

Command:进程启动的启动命令名称,如果这一行显示不下,进程会有一个完整的命令行。

top命令使用过程中,还可以使用一些交互的命令来完成其它参数的功能。这些命令是通过快捷键启动的。

<空格>:立刻刷新。

P:根据CPU使用大小进行排序。

T:根据时间、累计时间排序。

q:退出top命令。

m:切换显示内存信息。

t:切换显示进程和CPU状态信息。

c:切换显示命令名称和完整命令行。

M:根据使用内存大小进行排序。

W:将当前设置写入~/.toprc文件中。这是写top配置文件的推荐方法。

还有一种办法是 ps -ef | sort -k7 ,将进程按运行时间排序,看哪个进程消耗的cpu时间最多。

数据库

事务的特性

1、原子性:事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行

2、一致性:几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。

3、隔离性:事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的

4、持久性:对任意已提交的事务,系统必须保证该事务对数据库的改变不丢失,即使数据库出现故障

redis和mysql的区别

redis是内存数据库,数据保存在内存中,速度快

mysql是关系型数据库,持久化存储,存放在磁盘里面,功能强大。检索的话,会涉及到一定的IO,数据访问也就慢

redis受到攻击怎么办

主从配置

持久化存储

redis不以root账户启动

设置复杂的密码

不允许key方式登录

mysql数据库引擎的区别

myisam默认引擎,不支持事务

innodb支持事务,原子性操作

flask与django的区别

flask:

1、flask是一个轻量级web框架,只有一个内核,默认依赖两个外部库:jinja2模板引擎和werkzeug WSGI工具集,自由、灵活、可拓展性强,开发者可以根据需求自己造轮子
2、适用于做小型网站以及web服务的API,开发大网站无压力,架构需自行设计
3、与关系型数据库结合不弱于django,而与非关系型数据库的结合远远优于django

django:

1、django是一个重量级的web框架,它走的是大而全的方向,注重的是高效的开发,功能齐全,它的内部有许多已经封装好的工具包,第三方库丰富,我们可以直接拿过来使用,能让开发者不用在选择应用上花费大量的时间
2、自带的ORM关系映射模型和模板引擎支持jinja等非官方模板引擎,灵活度不高
3、自带ORM使django和关系型数据库耦合度过高,如果要使用非关系型数据库,需要使用第三方库
4、自带自动化的后台管理
5、相对于flask,django的整体封闭性比较好,适合做企业级网站的开发
6、上手容易,开发文档详细、完善,资料丰富

python实现斐波那契数列

普通方法实现

a = 0
b = 1
while b <1000:
  print(b)
  a,b = b,a+b

递归方式实现

#递归方式实现,生成前20项
lis = []
for i in range(20):
  if i==0 or i==1:#第一二项 都为1
    lis.append(1)
  else:
    lis.append(lis[i-2]+lis[i-1])#从第三项开始每项为前两项之和
print(lis)    

设置缓存的两种方式

1、redis缓存

简单的连接方式

import redis
conn = redis.Redis(host='127.0.0.1',port=6379)
conn.set('key','vlaue')
#conn.setex('key','vlaue',20)
print(conn.get('key'))

2、memchache

import memcache
mc = memchache.Client(['127.0.0.1:11211'],debug=True)
mc.set('key','vlaue',timeout=60)
ret = mc.get('key')
print(ret)

celery运行原理图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值