0

私はn次元配列を1次元「配列」データベースにシリアル化することに取り組んできました。

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に引数が正しく渡されていないようです。

私は何が間違っているのですか?

4

3 に答える 3

2

1つの問題は、引数*argsを展開するために使用しているようですが、タプルでラップせずにその引数の値としてargs渡します。したがって、あなたがそれを望んでいるように見えるとき、cursorあなたの最終的な呼び出しはです。やってみてください。insert("foo", *cursor)insert("foo", cursor)pass_many([["foo", "bar"], "pew"], insert, (cursor,))

test_var_argsこれを行うと、関数がカーソルオブジェクト(明らかに反復可能)を消費しているため、実際のinsert関数への後続の呼び出しで展開される引数が残っていないことが起こっていると思います。

あなたの応答の後に編集された:あなたは実際vにあなたのfunc電話に渡りたくないですか?記述された挿入関数は2つの引数とを取りますvcursor、それを呼び出すのは。だけcursorです。なんでラッピングするのinsert?何をすることになっている余分な議論は何ですか?ラッパーで使用せず、基になる関数に渡さないので、その目的は何ですか?

于 2012-06-10T07:47:12.127 に答える
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演算子を削除するか、次のように呼び出すときにオブジェクトをタプルで*ラップすることをお勧めします。cursorpass_many

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

これでも「そのようなテーブルはありません:wordlist」というエラーが表示されますが、これは実際にはそのようなテーブルを定義していないためです。('wordlist'はのデフォルトの引数ですinsert()

于 2012-06-10T08:10:32.560 に答える
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])
于 2012-06-10T10:02:56.437 に答える