最近项目忙成狗,都没时间好好看看开发的东西了,正好最近开始看rest api的东西,真是个好东西啊。可以前后端分离,但是在学习的过程中,遇到各种问题。还是基础不够扎实。本次rest api的会一边遇坑一边补习之前的东西。

一 functools库

真是一个神奇的python库,以前一直没注意。

1 偏函数 partial

先找文档学习一下,最后看源码,源码能看懂就看,看不懂那就是真的看不懂了。

文档参考 https://blog.csdn.net/appleyk/article/details/77609114

partial 一共有三个部分:

(1)第一部分也就是第一个参数,是一个函数,这个函数可以是你定义的,也可以是Python内置函数

(2)第二部分是一个可变参数,*args,比如内置函数max的参数就是一个可变参数,max(1,2,3,4,5)=5

(3)第三部分是一个关键字参数,比如内置函数int的第二个参数就是命名关键字参数,默认base=10,表示int转换时默认是10进制的:

partial函数的作用就是:将所作用的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数的后续参数,原函数有关键字参数的一定要带上关键字,没有的话,按原有参数顺序进行补充。

使用一下吧

A、偏函数的第二个部分(可变参数),按原有函数的参数顺序进行补充,参数将作用在原函数上,最后偏函数返回一个新函数(类似于,装饰器decorator,对于函数进行二次包装,产生特殊效果;但又不同于装饰器,偏函数产生了一个新函数,而装饰器,可改变被装饰函数的函数入口地址也可以不影响原函数)

这里我的理解是:首先偏函数能做的事情,装饰器也能做,其次偏函数可以操作源函数的参数,可是装饰器可以操作函数的入口。那为啥还有偏函数,估计是因为比装饰器简单吧。用起来应该很爽。

案例:我们定义一个sum函数,参数为*args可变,计算这些可变参数的和。

扩展:我们想要对sum函数求和后的结果,再加上10加上20甚至加更多,得到一个新的结果。

实现:我们分别用decorator和partial来实现,对比一下二者的区别。

好激动,因为可以紧跟作者脚步可以复习一下装饰器的东西了。

(1)装饰器实现

基础:http://www.cnblogs.com/wanstack/p/9009932.html

    # /usr/bin/env Python3
# -*- encoding:UTF-8 -*- from functools import wraps def sum_add(*args1): #我们要给我们的装饰器decorator,带上参数
def decorator(func):
@wraps(func) #加上这句,原函数func被decorator作用后,函数性质不变
def my_sum(*args2): #注意,参数要和原函数保持一致,真正实行扩展功能的是外层的装饰器
my_s = 0
for n in args1:
my_s = my_s +n #这个是我们新加的求和结果
return func(*args2) + my_s #这个,我们在原求和函数的结果上再加上s,并返回这个值
return my_sum #返回my_sum函数,该函数扩展原函数的功能
return decorator #返回我们的装饰器 @sum_add(10,20) #启用装饰器 对sum函数进行功能扩展
def sum(*args):
s = 0
for n in args:
s = s+n
return s
print(sum(1,2,3,4,5))
print(sum.__name__)

  

这里以前一直有一个疑问,今天突然间理解了,以前一直觉得为啥装饰器带上参数就需要写三层嵌套函数,因为@decorator没有()所以是不需要执行的,而加上参数@decorator(*args)是已经开始执行了啊。尼玛就是这么简单,当时困扰了好久。归根结底还是不理解。有时候想想做技术真的是理解了就是理解了,不理解死记硬背也不理解。

看看偏函数的实现:

# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
from functools import partial def sum(*args):
s = 0
for n in args:
s = s + n
return s sum_add_10 = partial(sum,10) #10 作用在sum第一个参数的位置
sum_add_10_20 = partial(sum,10,20) #10 20 分别作用在sum第一个和第二个参数的位置
print('A____________我们看下原函数sum的函数地址入口:')
print(sum)
print('B______我们看下partial函数返回函数的地址入口:')
print(partial(sum,10))
print(sum_add_10(1,2,3,4,5)) # --> 10 + 1 + 2 + 3 + 4 + 5 = 25
print(sum_add_10_20(1,2,3,4,5)) # --> 10 + 20 + 1 + 2 + 3 + 4 + 5 = 45

  

一步到位,当然还有其他方式一步到位的写法。这里的partial(函数,函数的第一个参数位置) 这部就是可以对已经存在的函数的参数中,继续传递参数吗。

B、偏函数的第三个部分(关键字参数),按原有函数的关键字参数进行填补,参数将作用在原函数上,最后偏函数返回一个新函数

案例:我们定义一个mod求余函数,两个参数,一个是被除数,一个是除数,除数我们这里用命名关键字参数表示,默认值2

扩展:我们的除数不固定,可以是对2就行求余,也可以对3,对4,总之我们需要指定除数的值

返回结果: True 或 False

实现:原函数实现和partial函数实现

# /usr/bin/env Python3
# -*- encoding:UTF-8 -*-
import functools
def mod(m,*,key=2):
return m % key == 0
mod_to_2 = functools.partial(mod,key=2)
print('A__3___使用原函数的默认关键字参数对2进行求余:')
print(mod(3)) #对2进行求余-- 原函数 使用默认参数
print('B__3___使用偏函数对2进行求余:')
print(mod_to_2(3)) #对2进行求余-- 新函数 --偏函数产生
mod_to_5 = functools.partial(mod,key=5)
print('C__25___使用原函数的关键字参数对5进行求余:')
print(mod(25,key=5)) #对5进行求余 -- 原函数
print('D__25___使用偏函数对5进行求余:')
print(mod_to_5(25)) #对5进行求余 -- 新函数--偏函数产生

  

2 wraps

其实上面已经用到了wraps,一般在使用装饰器的时候会使用这个,他也是一个装饰器,至于为什么会用他,因为我们在使用装饰器的时候,会损失一些基本信息,比如fun.__name__等等,用上他,就不会了。

啥也不说了,直接上代码。

# coding:utf-8
from functools import partial WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
'__annotations__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Update a wrapper function to look like the wrapped function wrapper is the function to be updated
wrapped is the original function
assigned is a tuple naming the attributes assigned directly
from the wrapped function to the wrapper function (defaults to
functools.WRAPPER_ASSIGNMENTS)
updated is a tuple naming the attributes of the wrapper that
are updated with the corresponding attribute from the wrapped
function (defaults to functools.WRAPPER_UPDATES)
"""
"""
try:
<语句>
except <name>:
<语句> #如果在try部份引发了名为'name'的异常,则执行这段代码
else:
<语句> #如果没有异常发生,则执行这段代码
finally:
print("不管有没有异常,我总是被执行了")
"""
print("wrapper==========" ,wrapper) # 这里的wrapper是一个inner函数
for attr in assigned:
try:
# 这里的wrapped应该是被装饰的函数,从wrapped中获取assigned的属性
value = getattr(wrapped, attr)
print("value============",value)
except AttributeError:
pass
else:
# 这里try执行了,这里就把value的值赋值给wrapper对象
setattr(wrapper, attr, value)
v = getattr(wrapper,attr)
print('v------',v)
for attr in updated:
print("getattr(wrapper, attr)",getattr(wrapper, attr)) # 这是个字典
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
# Issue #17482: set __wrapped__ last so we don't inadvertently copy it
# from the wrapped function when updating __dict__
wrapper.__wrapped__ = wrapped
# Return the wrapper so this can be used as a decorator via partial()
return wrapper # 这个wrapper是一个inner def wraps(wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Decorator factory to apply update_wrapper() to a wrapper function Returns a decorator that invokes update_wrapper() with the decorated
function as the wrapper argument and the arguments to wraps() as the
remaining arguments. Default arguments are as for update_wrapper().
This is a convenience function to simplify applying partial() to
update_wrapper().
"""
# 其中update_wrapper是一个函数,wtrapped,assigned,updated是这个函数的关键字参数
# 这里执行update_wrapper函数,返回一个wrapper
return partial(update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated) def decorator(func):
"""
1. value = getattr(wrapped, attr) 从func中拿到一些属性信息
2. setattr(wrapper, attr, value) 把这些属性信息赋值给inner
3. return wrapper 返回inner
:param func:
:return:
"""
@wraps(func) # func = wraps(func)
def inner():
print('起床先睁眼')
func()
return inner @decorator # func = decorator(func)
def func():
print('早上起床') func() # 执行inner()
print(func.__name__)
print(func.__dict__)

  

可能看着有点乱,但是只要就是

    1. value = getattr(wrapped, attr) 从func中拿到一些属性信息
2. setattr(wrapper, attr, value) 把这些属性信息赋值给inner
3. return wrapper 返回inner

做了这三件事情,当然了__dict__中的我没写,但是大概就是这么个流程,现在知道了即使,我们返回的是inner函数,也会对应的是func的信息。中间通过反射进行取值和赋值的操作。

restframework api(基础1)的更多相关文章

  1. 从头编写 asp.net core 2.0 web api 基础框架 (1)

    工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (Chrome的App) 3.Chrome (最好是) 关于.net core或者.net core 2.0的相 ...

  2. 【转载】从头编写 asp.net core 2.0 web api 基础框架 (1)

    工具: 1.Visual Studio 2017 V15.3.5+ 2.Postman (Chrome的App) 3.Chrome (最好是) 关于.net core或者.net core 2.0的相 ...

  3. 从头编写asp.net core 2.0 web api 基础框架 (5) + 使用Identity Server 4建立Authorization Server (7) 可运行前后台源码

    前台使用angular 5, 后台是asp.net core 2.0 web api + identity server 4. 从头编写asp.net core 2.0 web api 基础框架: 第 ...

  4. 《Node.js高级编程》之Node 核心API基础

    Node 核心API基础 第三章 加载模块 第四章 应用缓冲区 第五章 事件发射器模式简化事件绑定 第六章 使用定时器制定函数执行计划 第三章 加载模块 本章提要 加载模块 创建模块 使用node_m ...

  5. 从零开始学习 asp.net core 2.1 web api 后端api基础框架(二)-创建项目

    原文:从零开始学习 asp.net core 2.1 web api 后端api基础框架(二)-创建项目 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.ne ...

  6. 从零开始学习 asp.net core 2.1 web api 后端api基础框架(三)-创建Data Transfer Object

    原文:从零开始学习 asp.net core 2.1 web api 后端api基础框架(三)-创建Data Transfer Object 版权声明:本文为博主原创文章,未经博主允许不得转载. ht ...

  7. 从零开始学习 asp.net core 2.1 web api 后端api基础框架(四)-创建Controller

    原文:从零开始学习 asp.net core 2.1 web api 后端api基础框架(四)-创建Controller 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog ...

  8. 从零开始学习 asp.net core 2.1 web api 后端api基础框架(一)-环境介绍

    原文:从零开始学习 asp.net core 2.1 web api 后端api基础框架(一)-环境介绍 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.ne ...

  9. restframework api(基础3CBV)

    一 CBV源码流程 urls.py from django.conf.urls import url from django.contrib import admin from app01 impor ...

随机推荐

  1. 从两道题看go channel的用法

    在知乎看到有人分享了几道笔试题,自己总结了一下其中与channel有关的题目.全部题目在这里: https://zhuanlan.zhihu.com/p/35058068 题目 5.请找出下面代码的问 ...

  2. 下拉刷新&上拉加载

    效果演示 核心codehtml <ion-view view-title="学生list"> <ion-content > <ion-refreshe ...

  3. Codeforces Round #408 (Div. 2) D - Police Stations

    地址:http://codeforces.com/contest/796/problem/D 题目: D. Police Stations time limit per test 2 seconds ...

  4. 对Docker的一点理解

    Docker是什么? Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来.并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会相互影响.那么就不需要专门 ...

  5. ls命令输出的文件颜色

    ls的输出颜色不止3种,有以下几种,白色:表示普通文件蓝色:表示目录绿色:表示可执行文件红色:表示压缩文件浅蓝色:链接文件红色闪烁:表示链接的文件有问题 黄色:表示设备文件 灰色:表示其他文件 这是l ...

  6. Python 实例2—购物车

    老男孩教学学习笔记 """启动程序后,让用户输入工资,然后打印商品列表允许用户根据商品编号购买商品用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒可随机退出,退出 ...

  7. 【Head First Servlets and JSP】笔记 27: web 应用安全

    典型的安全问题:假冒者.窃听者.非法升级者 认证方式: Base64 .摘要认证 .客户端证书.表单认证,重点熟悉摘要算法( HASH . MD5 等) 安全机制:授权.认证.数据完整性.机密性 80 ...

  8. 安装vmware虚拟机和linux(centos)

    打开 WMware Workstation 8,然后选择新建虚拟机 2 新建虚拟机向导 选择 自定义(高级)(C)然后点击[下一步]按钮 3 选择虚拟机硬件兼容性 选择 workstation 8.0 ...

  9. 20145329 《JAVA程序设计》课后习题代码编写总结

    20145329<Java程序设计>课后习题学习总结 学习内容总结 package cc.openhome; public class Hello2 { public static voi ...

  10. 20135320赵瀚青LINUX第一章读书笔记

    第一章-Linux内核简介 Unix的历史 依旧被认为是最强大和最优秀的系统 由一个失败的操作系统Multics中产生 被移植到PDP-11型机中 由其他组织进一步开发 重写了虚拟内存系统,最终官方版 ...