2012-06-10 94 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])