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的更多相关文章

  1. Python函数参数默认值的陷阱和原理深究"

    本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 本博客已经迁移至: http://cenalulu.github.io/ 本篇博文已经迁移,阅读全文 ...

  2. Python 关于Python函数参数传递方式的一点探索

    关于Python函数参数传递方式的一点探索 by:授客 QQ:1033553122 实践代码 #!/usr/bin/env python # -*- coding:utf-8 -*- __author ...

  3. python 函数参数介绍

    python 函数参数介绍 python 使用过程总,总会遇到 *args,**kw形式的参数,总是一头雾水,而且网上介绍的或是叫法不一,为此专门深入实践进而了解了函数参数的使用 具体请看代码 #-* ...

  4. python函数参数类型及其顺序

    根据inspect模块官文文档中关于函数参数类型的相关说明,python函数参数共有五种类型,按顺序分别为:POSITIONAL_ONLY.POSITIONAL_OR_KEYWORD.VAR_POSI ...

  5. Python 函数参数类型大全(非常全!!!)

    Python 函数参数类型大全(非常全!!!) 1.在python编写程序里面具有函数文档,它的主要作用是为了让别人可以更好的理解你的函数,所以这是一个好习惯,访问函数文档的方式是: MyFuncti ...

  6. Python函数参数默认值的陷阱和原理深究(转)

    add by zhj: 在Python文档中清楚的说明了默认参数是怎么工作的,如下 "Default parameter values are evaluated when the func ...

  7. python函数-参数

    python函数-参数 实验室 # 演示形参是可变类型 def register(name, hobby, hobby_list=[]): hobby_list.append(hobby) print ...

  8. 详解Python函数参数定义及传参(必备参数、关键字参数、默认可省略参数、可变不定长参数、*args、**kwargs)

    详解Python函数参数定义及传参(必备参数.关键字参数.默认可省略参数.可变不定长参数.*args.**kwargs) Python函数参数传参的种类   Python中函数参数定义及调用函数时传参 ...

  9. Python函数参数详解

    Python函数参数详解 形参与实参 什么是形参 在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名. 什么是实参 在调用函数阶段传入的值称为实际参数,简称实参.相当于"变量值& ...

随机推荐

  1. 《University Calculus》-chape4-导数的应用-微分中值定理

    罗尔定理:如果函数f(x)在[a,b]上连续并且在(a,b)处处可微,并且有f(a) = f(b),则我们必然何以找到一个c∈(a,b),使得f’(c) = 0. 证明:我们从函数f(x)的最大值和最 ...

  2. poj4474 Scout YYF I(概率dp+矩阵快速幂)

    Scout YYF I Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4100   Accepted: 1051 Descr ...

  3. 安装Wamp后 Apache无法启动的解决方法

    安装Wamp后 Apache无法启动的解决方法,网上的解决方案可以说是五花八门,有些说了一大推,一点作用都起不到. 其实解决方法只需两步: 1.安装路径不能包含有中文,这个我不知道为什么,总之如果安装 ...

  4. shell 二元操作符 =~

    17:14 [logc@a005.client.hadoop.qingdao.youku]$ a=1 17:14 [logc@a005.client.hadoop.qingdao.youku]$ if ...

  5. redis linux 基本命令

    找到一个哥们 写的都是一步步打基础的学习东西 不光是知识也是学习方式 都值得学习.. reids 传送们-->> http://xuelianbobo.iteye.com/category ...

  6. jeety and tomcat plugins In Maven

    (转自)maven jetty 插件使用 本机环境 JDK 7 Maven 3.2 Jetty 9.2 Eclipse Luna pom.xml 配置 在你的 pom.xml 文件中添加 jetty ...

  7. 小学生玩ACM----深搜

    Square Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  8. Delphi 2007体验!

    Delphi 2007体验! baidu 内容摘要:CodeGear(From Borland) 公司公布了最新的Delphi 2007 For Win32版本号.作为一个 Delphi 的使用者,第 ...

  9. Appium服务器端从启动到case完成的活动分析

    此文的目的主要是通过分析Appium Server打印出来的log,加深对Appium Server所扮演角色的理解. 这整一个过程是由一个Test Case开始执行到结束,测试的对象是SDK自带的N ...

  10. 数据存储简单了解(NSUserDefaults)

    数据存储-使用NSUserDefaults 两个类介绍: NSUserDefaults适合存储轻量级的本地数据,比如要保存一个登陆界面的数据,用户名.密码之类的,个人觉得使用NSUserDefault ...