我一直致力于将n维数组序列化为一维“数组”数据库:
from collections import Iterable, Mapping
import sqlite3
def pass_many(vals, some_funct, args=()):
if not vals:
return
if isinstance(vals, Iterable) and not isinstance(vals, (basestring, Mapping)):
for v in vals:
pass_many(v, some_funct, args)
else:
some_funct(vals, *args)
def counter(func):
def wrapper(v, *args, **kwargs): # added 'v' arg to no avail
wrapper.count = wrapper.count + 1
test_var_args(v, *args, **kwargs)
#return func(*args, **kwargs)
wrapper.count = 0
return wrapper
def test_var_args(farg, *args):
print "formal arg:", farg
for arg in args:
print "another arg:", arg
@counter
def insert(val, cursor, table="wordlist", logfile="queries.log"):
print val, cursor, table, logfile
if val:
if isinstance(val, (basestring, Mapping)):
val = '\"' + val + '\"'
else: val = str(val)
query = "insert into tablename values (?);".replace('tablename', table).replace('?', val)
#if logfile: to_logfile(query + '\n', logfile)
cursor.execute(query)
if __name__ == '__main__':
connection = sqlite3.connect('andthensome.db')
cursor = connection.cursor()
cursor.execute("create table array (word text);")
pass_many([["foo", "bar"], "pew"], insert, cursor)
connection.commit()
cursor.execute("select * from array;") # wrapped select function omitted for brevity
print "insert() was called", insert.count, "times, and db now contains:\n", cursor.fetchall()
cursor.close()
输出:
formal arg: foo
formal arg: bar
formal arg: pew
insert() was called 3 times, and db now contains:
[]
输出取消注释#return func(*args, **kwargs)
:
formal arg: foo
Traceback (most recent call last):
Line 42, in <module>
pass_many([["foo", "bar"], "pew"], insert, cursor)
Line 9, in pass_many
pass_many(v, some_funct, args)
Line 9, in pass_many
pass_many(v, some_funct, args)
Line 11, in pass_many
some_funct(vals, *args)
Line 17, in wrapper
return func(*args, **kwargs)
TypeError: insert() takes at least 2 arguments (0 given)
预期输出(省略调试功能):
insert() was called 3 times, and db now contains:
["foo","bar","pew"]
不幸的是,用insert
修饰的counter
函数似乎没有正确传递参数。
我做错了什么?
答案 0 :(得分:2)
似乎有一个问题是你使用*args
来扩展args
参数,但是传入cursor
作为该参数的值而不将其包含在元组中。因此,当您似乎希望它为insert("foo", *cursor)
时,您的最终通话为insert("foo", cursor)
。尝试pass_many([["foo", "bar"], "pew"], insert, (cursor,))
。
我认为正在发生的事情是,当你这样做时,你的test_var_args
函数正在消耗游标对象(显然是可迭代的),因此在随后的对real的调用中不再需要扩展参数{ {1}}功能。
在回复后编辑:你真的不想将insert
传递给v
来电吗?您编写的插入函数有两个参数,func
和v
,但您只用cursor
调用它。你为什么要包裹cursor
?应该做的额外争论是什么?你不在包装器中使用它,并且你没有将它传递给底层函数,那么它的目的是什么?
答案 1 :(得分:0)
有两件事:首先,在wrapper()
:
def counter(func):
def wrapper(v, *args, **kwargs): # added 'v' arg to no avail
wrapper.count = wrapper.count + 1
test_var_args(v, *args, **kwargs)
return func(*args, **kwargs)
...
您已将第一个参数映射到v
,但您没有将其传递给真实的func
。最好完全删除它。
第二,也是最重要的:
def pass_many(vals, some_funct, args=()):
if not vals:
return
if isinstance(vals, Iterable) and not isinstance(vals, (basestring, Mapping)):
for v in vals:
pass_many(v, some_funct, args)
else:
some_funct(vals, *args)
请注意,当您致电some_funct()
时,您正在解构args
参数。问题是,当您致电pass_many()
时,您为cursor
参数提供了args
个对象。这将巧妙地失败。要解决此问题,您可以删除splat运算符*
,或者更好的选择,当您调用cursor
时,可以将pass_many
对象包装在元组中,如下所示:
pass_many([["foo", "bar"], "pew"], insert, (cursor,))
这仍然会出现“没有这样的表:wordlist”的错误,但这实际上是因为你还没有定义这样的表。 ('wordlist'是insert()
的默认参数)
答案 2 :(得分:0)
从@BrenBarn的建议我把它修改为:
def counter(func):
def wrapper(v, *args, **kwargs):
wrapper.count = wrapper.count + 1
test_var_args(v, *args, **kwargs)
return func(v, *args, **kwargs)
wrapper.count = 0
return wrapper
pass_many([["foo", "bar"], "pew"], insert, [cursor])