python函数参数的pack与unpack
python函数参数的pack与unpack
上周在使用django做开发的时候用到了mixin(关于mixin我还要写一个博客专门讨论一下,现在请参见这里),其中又涉及到了一个关于函数参数打包(pack)的问题,导致延误了开发时间,所以在这里记录一下,稍后会说到具体的背景。
背景交代:
具体情景是这样的,我需要一个view可以在查询的同时可以分页,又可以在返回的 queryset 上做更多的查询操作。为了解决这个问题,我自己写了一个mixiin :
class MultipleOjbectQueryPageMixin(object):
'''
query_params = [['filter , 'tags__label__contains, 'wow' ],[],[]]
'''
query_params = None
paginate_by = None
page_size_kwargs = 'size'
#新加入的方法
def get_paginate_by(self, queryset):
if self.page_size_kwargs in self.request.kwargs:
self.paginate_by = int(self.request.kwargs[self.page_size_kwargs])
return self.paginate_by
def do_query(self, queryset):
if self.query_params:
iterator = iter(self.query_params)
try:
param = iterator.next()
try:
if params[1] is not None and params[0] is not None:
#函数参数解包的问题
queryset = getattr(queryset, params[0])(**{params[1] : params[2]})
return queryset
else:
queryset = getattr(queryset,params[0])()
return queryset
except AttributeError as e:
print e
except StopIteration as e:
print e
else:
return queryset.all()
#新加入的方法
def get_queryset(self):
if self.queryset is not None:
queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = self.do_query(queryset)
elif self.model is not None:
queryset = self.do_query(self.model._default_manager)
else:
raise ImproperlyConfigured(
"%(cls)s is missing a QuerySet. Define"
"%(cls)s.model, %(cls)s.queryset, or override"
"%(cls)s.get_queryset()." % {
'cls' : self.__class__.__name__
}
)
ordering = self.get_ordering()
if ordering:
if isinstance(ordering, six.string_types):
ordering = (ordering, )
queryset = queryset.order_by(*ordering)
return queryset
这个 mixin只自定义了2个方法,其中一个是从url中获取当前分页的页面大小,也就是page_size, 在MultipleObjectMixin类中这这个参数的名字叫做 paginate_by ,在 django.views.generic.ListView 中直接继承了这个mixin , 不过ListView只有基本的分页功能 (你可以直接在url中传入/?page=1,来进行分页,mixin中都写好了),并没有可以从url中获取页面大小,我增加的方法可以直接从url中获取要分页的页面大小,然后传入page参数就可以完成分页。
另外一个方法比较复杂,它拥有了基本的查询功能,我的初衷是要从url中得到博客的标签信息,然后根据标签查询到相应标签下的博客,所以就写了一个方法,这个方法由 get_queryset(self) 这个方法来调用, 这样就可以比较方便的在已有代码的基础上去做查询,实际使用中我写了一个功能类似于BaseListView类的View类来继承该mixin, 然后重写自己的get方法就可以了,在myapp.views中使用起来非常方便,直接继承自己写的view类,然后在类中定义需要的属性,就可以了,myapp.views中没有方法,看起来非常整洁,我认为这就是CBV的好处了。
如果你要说我直接自己写get方法,直接在request中获取tag的值,然后
pk = request.kwargs['id']
tag = Tag.objects.get(pk = pk)
blogs = tag.blogs.all()
那么我会说这完全是可以的,但是你以后需要再查询别的东西的时候,你必须一直写get方法,这样的写法,会导致CBV的优势荡然无存,那还不如直接去写FBV的好,大家都说FBV容易理解,其实我觉得让我写的话肯定是写CBV,不喜欢看到乱糟糟的代码。
函数参数的解包问题:
由于已经很久很久没有写python了,所以不免会忘记一些东西,这次跳的一个小坑就是在函数参数上出了问题。
我想实现的是这样的效果
params = { 'tags__label__conatains' : wow'}
Blog.objects.filter(params)
上面这样直接传入字典是不行的
因为filter中的参数是一个有默认值的tags__table__contains 参数,
我的目的是想给它一个值,这样在func(*args, **kwargs)里是解析不到kwargs里的,实际上传入一个字典的结果都在args 参数里,因为我们传入的是一个对象,而不是kv, 只有传入test(a=1, b=2)这样的值才会被解析到kwargs中,现在我们这样写
Blog.objects.filter(params.keys()[0] = params.values()[0])
还是不行
接着我们这样写
k = params.keys()[0]
v = params.values()[0]
Blog.objects.filter( k = v)
你会发现这样写可以,但是我们需要的参数变成k了,而不是 tags__label__contains
所以这样也是不行的。
然后我们又换了一种方法
Blog.objects.Filter({ k : v})
结果这个参数又跑到args里去了,
最后正确的写法是这样的
Blog.objects.Filter(**{k:v})
这样先解包就可以把带变量的参数传到kwargs
对于args来说是一样的
def test(*args, **kwargs):
print args
print kwargs
s = (1,2,3,4,)
test(s)
输出:
((1,2,3,4),)
很明显系统把s这个元组当成了一个对象,如果你打算传入之后对,args进行遍历操作话,会发现args里只有一个对象,但是我明明传入了一个有4个元素的元组啊。
正确的写法是:
test(*s)
输出为:
(1,2,3,4)
这个时候你就可以去遍历了,绝对没问题了
python函数参数的pack与unpack的更多相关文章
- Python函数参数默认值的陷阱和原理深究"
本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 本博客已经迁移至: http://cenalulu.github.io/ 本篇博文已经迁移,阅读全文 ...
- Python 关于Python函数参数传递方式的一点探索
关于Python函数参数传递方式的一点探索 by:授客 QQ:1033553122 实践代码 #!/usr/bin/env python # -*- coding:utf-8 -*- __author ...
- python 函数参数介绍
python 函数参数介绍 python 使用过程总,总会遇到 *args,**kw形式的参数,总是一头雾水,而且网上介绍的或是叫法不一,为此专门深入实践进而了解了函数参数的使用 具体请看代码 #-* ...
- python函数参数类型及其顺序
根据inspect模块官文文档中关于函数参数类型的相关说明,python函数参数共有五种类型,按顺序分别为:POSITIONAL_ONLY.POSITIONAL_OR_KEYWORD.VAR_POSI ...
- Python 函数参数类型大全(非常全!!!)
Python 函数参数类型大全(非常全!!!) 1.在python编写程序里面具有函数文档,它的主要作用是为了让别人可以更好的理解你的函数,所以这是一个好习惯,访问函数文档的方式是: MyFuncti ...
- Python函数参数默认值的陷阱和原理深究(转)
add by zhj: 在Python文档中清楚的说明了默认参数是怎么工作的,如下 "Default parameter values are evaluated when the func ...
- python函数-参数
python函数-参数 实验室 # 演示形参是可变类型 def register(name, hobby, hobby_list=[]): hobby_list.append(hobby) print ...
- 详解Python函数参数定义及传参(必备参数、关键字参数、默认可省略参数、可变不定长参数、*args、**kwargs)
详解Python函数参数定义及传参(必备参数.关键字参数.默认可省略参数.可变不定长参数.*args.**kwargs) Python函数参数传参的种类 Python中函数参数定义及调用函数时传参 ...
- Python函数参数详解
Python函数参数详解 形参与实参 什么是形参 在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名. 什么是实参 在调用函数阶段传入的值称为实际参数,简称实参.相当于"变量值& ...
随机推荐
- ACM第六周竞赛题目——B CodeForces 478B
B - B Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- 编写Lex和Yacc
大学课程设计中,有一次是编写Lex(词法分析器的生成器)和Yacc(语法分析器的生成器),编写这类工具软件不是一件容易的事情.这篇文章记录了当时编程时候的主要思想,主要还是编译原理的思想. 准备 Le ...
- 《University Calculus》-chaper13-向量场中的积分-线积分
线积分: 基于二重积分和三重积分的引入,我们对于线积分的引入过程将会轻车熟路. 对于一根不均匀密度的铜丝,我们如何求其总质量?如下图. 类似二重积分和三重积分的引入,我们首先基于实际问题给出黎曼和的形 ...
- poj1003
题目大意:超越悬挂 你可以把卡片最远堆到距离桌子多远?如果你有一张卡片,你可以堆卡片长度的一半如果有两张卡片那么可以堆1/2+1/3=5/6,如果有n张卡片那么可以堆1/2+1/3+1/4+..... ...
- 【转】AngularJs $location获取url参数
// 带#号的url,看?号的url,见下面 url = http://qiaole.sinaapp.com?#name=cccccc $location.absUrl(); // http://qi ...
- [转] Linux下查看文件和文件夹大小
当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力. du可以查看文件及文件夹的大小. ...
- TCP/IP协议原理与应用笔记07:HTTP、TCP/IP与socket区别
1. TCP/IP协议与HTTP协议区别: HTTP 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件 ...
- Android 连接 SQL Server (jtds方式)——上
本文将介绍开发Android程序,连接SQL Server,通过第三方包jtds的方式. 如果你有同样的需求,请跟着做一遍,博主将以最详细的方式,进行介绍. 首先说明,Java.Android连接SQ ...
- ST表poj3264
/* ST表多次查询区间最小值 设 g[j][i] 表示从第 i 个数到第 i + 2 ^ j - 1 个数之间的最小值 类似DP的说 ans[i][j]=min (ans[i][mid],ans ...
- 经验分享:CSS浮动(float,clear)通俗讲解(转载)
很早以前就接触过CSS,但对于浮动始终非常迷惑,可能是自身理解能力差,也可能是没能遇到一篇通俗的教程. 前些天小菜终于搞懂了浮动的基本原理,迫不及待的分享给大家. 写在前面的话: 由于CSS内容比较多 ...