2012-06-10 75 views
0

我已经工作连载一个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被正确传递的参数。

我在做什么错?

+2

是在注释掉的一个原因装饰的函数调用? –

+0

是的,所以调试'test_var_args'函数可以运行所有的时间''插入'运行显示哪些参数出现时。 – user1438003

+1

你能提供一个更简单的测试案例吗?一个显示使用你的装饰器在一个简单的无操作函数('def func(* args,** kwargs):pass')上的问题将是理想的。此外,最好还是准确地知道发生了什么问题 - 即列出您期望的输出和实际得到的输出。 – lvc

回答

2

一个问题似乎是,你正在使用*args扩大你args的说法,但是你在cursor作为参数的值传递没有一个元组加以包装。因此,你最终的电话号码是insert("foo", *cursor),当你似乎希望它是insert("foo", cursor)。试试做pass_many([["foo", "bar"], "pew"], insert, (cursor,))

我认为正在发生的事情是,当你这样做,你test_var_args功能消耗光标对象(这显然是迭代器),因此没有留下更多的参数在后续调用扩展到真正insert功能。

在您的回复后编辑:您是否确实想要将v传递给func电话?您所写的插入函数需要两个参数vcursor,但您只需要使用cursor即可。你为什么要包装insert?额外的论据应该做什么?你不在包装中使用它,并且你不会将它传递给底层函数,那么它的目的是什么?

+0

谢谢,给了我一个更好的结果:'TypeError:insert()至少需要2个参数(给出1)' – user1438003

+0

请参阅我编辑的回复。 – BrenBarn

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。这将微妙地失败。为了解决这个问题,你可以删除的图示操作*,或者,一个更好的选择,你可以当你调用pass_many,像这样包裹cursor对象的元组:

pass_many([["foo", "bar"], "pew"], insert, (cursor,)) 

这仍然会给出一个错误“没有这样的表格:wordlist”,但那实际上是因为你还没有定义这样的表格。(“单词表”是默认的参数insert()

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])