Reputation: 2233
I am using exoredis, a key-value store that works great as a cache.
It has a method get_or_set
that sets the value of the key if it doesn't exist already.
exoredis.get_or_set('my_new_key', 'my new value')
Here, my new value
can also be a callable that returns a string like:
exoredis.get_or_set('some-timestamp-key', datetime.datetime.now)
In my case, my callable needs to accept one argument "pk
":
def get_gender(pk):
return Users.objects.filter(pk=pk).gender
How do I pass this function as a callable?
This gives me a TypeError
saying my function expects one argument. (In the event that it is executed)
pk = request.user.id
print exoredis.get_or_set("gender:%s"%pk, get_gender)
TypeError: get_gender() takes exactly 1 argument (0 given)
This executes the function each time:
pk = request.user.id
print exoredis.get_or_set("gender:%s"%pk, get_gender(pk))
Upvotes: 0
Views: 334
Reputation: 55499
The way to do this is to wrap the one-argument function in a zero-argument function, and then pass that zero-arg function to the function that wants a zero-arg function.
As I mentioned in the comments there are two options here:
1) When the wrapped function is eventually called it's called with the current value of its parameter.
2) When the wrapped function is eventually called it's called with the old value that its parameter had when it got wrapped.
The code below illustrates both options.
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())
output
myfunc bye
myfunc hello
The "trick" used in the second option is to set the parameter as a default argument, since default arguments are evaluated when the function definition is executed, that is, when the function is created.
Technically, lambda s=s: myfunc(s)
is really a one-arg function, but we can call it with zero args and it will use the supplied default value for its argument.
Upvotes: 2
Reputation: 362047
pk = request.user.id
print exoredis.get_or_set("gender:%s"%pk, lambda: get_gender(pk))
Pass in a lambda function that takes no arguments. This will ensure get_gender
is called later rather than immediately.
Upvotes: 1