Error: 'function' object has no attribute 'context' when using Predicate
perezzini opened this issue · comments
Hello,
I got an AttributeError when wrapping a function into a predicate like the following:
def f(a):
f.context["v"] = 3
return True
pred_f = Predicate(f)
pred_f.test(5) # AttributeError: 'function' object has no attribute 'context'
Using a the predicate
decorator, works correctly:
@predicate
def f(a):
f.context["v"] = 3
return True
f.test(5) # works fine, returns True
This behaviour is considered by design, or am I doing something wrong?
Thanks for your time.
Regards.
This can be confusing but is normal Python behaviour. f
is indeed the undecorated function, so it obviously has no context
attribute. On the other hand, pred_f
should have the context
attribute.
So, if I'd like to use Predicate
to wrap a function definition, I'd have to define f
like the following?:
def f(self, a):
self.context["v"] = 3
return True
pred_f = Predicate(f, bind=True)
pred_f.test(5) # works correctly, returns True
The latter is the approach I must take in this case, right? Or is it another work-around (I'd like to not use the predicate
decorator to wrap arbitrary functions into rules
's predicates)?
Thanks in advance for the help!
It's totally fine to use the Predicate
class directly instead of the decorator. This snippet looks good to me.
On the other hand, if the function tries to access self.context
it's not really just an "arbitrary function" -- it has explicit knowledge of rules and predicates. I don't know what you're trying to do, but my point is maybe wrapping the original function f
as a predicate is the best course of action -- plain invocations of it will throw an exception, as you found out -- so it can't be used for much else than a predicate.
Yes, you're right: it's not an "arbitrary function". The problem is that I'm currently in an scenario where we consume function definitons on-the-fly, and them could try to access context
. So the better approach, I think, is wrapping them using Predicate(f, bind=True)
class (obviously, each function definition must have a signature like def f(self, ...)
and access context like self.context
).
Btw, I'm using rules
as a generic framework for a rule-based system.
Thanks for your quick response @dfunckt !