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函数参数详解 形参与实参 什么是形参 在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名. 什么是实参 在调用函数阶段传入的值称为实际参数,简称实参.相当于"变量值& ...
随机推荐
- bzoj 1010 [HNOI2008]玩具装箱toy(DP的斜率优化)
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7874 Solved: 3047[Submit][St ...
- bithrtree
#include "stdio.h" #include "stdlib.h" #define OK 1 #define ERROR 0 typedef char ...
- Registering Shell Extension Handlers
最近在做Windows shell extension 的开发工作,对shell extension handler的注册机制有点疑问,以下摘自MSDN:http://msdn.microsoft.c ...
- js输入框只能输入数字和小数点
<input name="number" onKeyPress="if (event.keyCode!=46 && (event.keyCode&l ...
- C++重载解析
重载解析(overloading resolution)的规则决定了编译器为一个函数调用选用哪个函数定义.一般过程如下: 将名称相同的函数/模板函数找到并创建候选列表 从中挑选参数数目正确,符合完全匹 ...
- Android下 scrollview的滚动停止事件的监听方法
使用递归调用的方法,每隔5毫秒检查一下是否已经停止,如果已经停止,就拿到事件啦! 不扯蛋,直接上代码. scrollContent就是我的scrollview. [代码]java代码: ? 1 2 3 ...
- php做站点购物车 你搞懂了吗?
网上购物现已成为时尚,客户选择一个商品将其放入到购物车,然后返回继续购物或者去收银台,这个功能怎样实现呢?今天capucivar就将使用PHP来实现这个购物车的功能. 首先,做一个简单的首页,从数据库 ...
- [PWA] 14. Loop cursor
import idb from 'idb'; var dbPromise = idb.open('test-db', 4, function (upgradeDb) { switch (upgrade ...
- 安装Stomp扩展时错误提示error: 'zend_class_entry' has no member named 'default_properties'
在安装stomp扩展时, 有这样的提示 error: 'zend_class_entry' has no member named 'default_properties' 交待下安装上下文, sto ...
- css font的简写规则
font的属性简写里面常用的有5个是可以写在一起的: font-style设定斜体 如:font-style: italic;font-weight设定文字粗细 如:font-weight: bold ...