2016-04-12 21 views
0

私はキャッシュとして機能するキー値ストアであるexoredisを使用しています。 キーがすでに存在しない場合は、キーの値を設定するメソッドget_or_setがあります。ここでpython - 関数オブジェクトを期待する引数を渡す

exoredis.get_or_set('my_new_key', 'my new value') 

my new valueも同様に文字列を返す呼び出し可能になります1つの引数 "pk" を受け入れるように私の場合は

exoredis.get_or_set('some-timestamp-key', datetime.datetime.now) 

、私の呼び出し可能なニーズ:

def get_gender(pk): 
    return Users.objects.filter(pk=pk).gender 

この関数を呼び出し元として渡すにはどうすればよいですか? これは私のTypeError私の関数が1つの引数を期待していると言ってくれます。

pk = request.user.id 
print exoredis.get_or_set("gender:%s"%pk, get_gender) 

TypeError: get_gender() takes exactly 1 argument (0 given)


これはたびに機能を実行する(それが実行された場合には):

引数を取らないラムダ関数で
pk = request.user.id 
print exoredis.get_or_set("gender:%s"%pk, get_gender(pk)) 
+6

あなたの質問は何ですか? – Duncan

+0

完全なTracebackを投稿できますか? – syntonym

+0

'get_gender'を最終的に呼び出されるときに' pk'の現在の値で呼び出すようにしますか? **または**あなたが 'exoredis.get_or_set'に渡したときに' pk'が持っていた値で呼び出されたいのですか? –

答えて

1

これを行う方法は、引数の1つの関数を引数のない関数にラップし、その引数の0の引数を引数のない関数に渡すことです。

コメントに記載されているとおり、ここには2つのオプションがあります。
1)ラップされた関数が最終的に呼び出されると、そのパラメータの現在の値で呼び出されます。
2)ラップされた関数が最終的に呼び出されるとき、ラップされたときにそのパラメータが持つ古い値で呼び出されます。

次のコードは両方のオプションを示しています。関数定義が実行されたときに

myfunc bye 
myfunc hello 

class Test(object): 
    def __init__(self, f): 
     self.f = f 

def myfunc(s): 
    return 'myfunc ' + s 

s = 'hello' 
a = Test(lambda: myfunc(s)) 
s = 'bye' 
print(a.f()) 

s = 'hello' 
a = Test(lambda s=s: myfunc(s)) 
s = 'bye' 
print(a.f())  

出力2番目のオプションで使用する「トリック」はデフォルト引数が評価されているので、デフォルトの引数としてパラメータを設定することで、それがあります、関数が作成されたとき。

は技術的には、lambda s=s: myfunc(s)本当に一引数の関数であるが、我々は、ゼロ引数でそれを呼び出すことができますし、それはその引数のために提供されるデフォルト値を使用します。

1
pk = request.user.id 
print exoredis.get_or_set("gender:%s"%pk, lambda: get_gender(pk)) 

パス。これにより、get_genderはすぐにではなく後で呼び出されます。

+0

これは動作しますが、ハッキーに見えます、もっとPythonic *の方法はありますか? –

+1

これはPythonの方法です。もう1つの方法は 'functools.partial'です。 –

+1

@DarshanChaudhary:これはかなり一般的なPythonのイディオムです。 OTOH、Guidoはラムダの大ファンではありません。あなたは 'lambda'の代わりに名前付き関数を使うことができました。 'def get_user_gender():get_gender(request.user.id)'を返し、 'get_user_gender'を' exoredis.get_or_set'に渡しますが、ラムダを使用することは明らかにコンパクトで、あなたがいない場合は名前付き関数を作成する必要はありませんそれを何度も参照するつもりはない、IMHO。 –

関連する問題