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. Ubuntu安装ARM架构GCC工具链(ubuntu install ARM toolchain)最简单办法

    一.安装ARM-Linux-GCC工具链 只需要一句命令: sudo apt-get install gcc-arm-linux-gnueabi 前提是你的Ubuntu系统版本是官网支持的最新的版本, ...

  2. java JDK安装

    JDK安装包下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 图释安装 ...

  3. C# 匿名方法 委托 Action委托 Delegate委托

    原文地址:https://msdn.microsoft.com/zh-cn/library/bb882516.aspx 匿名函数是一个“内联”语句或表达式,可在需要委托类型的任何地方使用. 可以使用匿 ...

  4. redis和ehcache

    Ehcache在java项目广泛的使用.它是一个开源的.设计于提高在数据从RDBMS中取出来的高花费.高延迟采取的一种缓存方案.正因为Ehcache具有健壮性(基于java开发).被认证(具有apac ...

  5. Linux用户root忘记密码的解决(unbuntu16.04)

    参考: http://www.linuxidc.com/Linux/2012-04/59069.htm http://www.68idc.cn/help/server/linux/2015060735 ...

  6. struct--------构造函数对结构体初始化的影响

    struct--------构造函数对结构体初始化的影响. 没有构造函数时使用如下: struct ClassBook{  int number;  int age; }; int main() { ...

  7. base64 小测试:

    base64工作原理:Base64是MIME邮件中常用的编码方式之一.它的主要思想是将输入的字符串或数据编码成只含有{'A'-'Z', 'a'-'z', '0'-'9', '+', '/'}这64个可 ...

  8. POJ 1686 Lazy Math Instructor (模似题+栈的运用) 各种坑

    Problem Description A math instructor is too lazy to grade a question in the exam papers in which st ...

  9. [Angular 2] ng-model and ng-for with Select and Option elements

    You can use Select and Option elements in combination with ng-for and ng-model to create mini-forms ...

  10. Android应用打包安装过程具体解释

    Android应用打包安装过程(Run as Android Application ): 1,过程:Android Project --> Compilation and Packaging ...