0

I have two classes. a and b.

In one of class a's methods, I created an object of class b. One of class b attributes takes a function. So say I gave it a random function but does this function of class b have access to class a's attribute? even though I didn't pass it in directly as a parameter?

class b:
    def __init__(self):
        self.attribute_function = None

class a:
    def __init__(self):
        self.temp = 10
        self.counter = 0

    def temp(self):
        obj = b()
        obj.attribute_function = lambda self: self.counter < self.temp
        return obj.attribute_function()


if __name__ == "__main__":
    #pass
    obj = a()
    print obj.temp()

In the above example, I tried to provide a really basic example, but if you run it, it doesn't work...

Revised Code, class a should look like this:

class a:
    def __init__(self):
        self.temp = 10
        self.counter = 0

    def temp(self):
        obj = b()
        obj.attribute_function = lambda args: self.counter < self.temp
        return obj.attribute_function(1) # i added this 1 to fill in arg

2 Answers 2

3

This works:

class b:
    def __init__(self):
        self.attribute_function = None

class a:
    def __init__(self):
        self._temp = 10
        self.counter = 0

    def temp(self):
        obj = b()
        obj.attribute_function = lambda self=self: self.counter < self._temp
        return obj.attribute_function()


if __name__ == "__main__":
    obj = a()
    print obj.temp()

On problem you had is self.temp = 10 which shadowed your method temp().

Another problem: lambda self: self.counter < self._temp. Your lambda function was expecting an argument. But omitting self is not a good idea lambda : self.counter < self._temp, because if you call obj.attribute_function() somewhere where self is not available or has changed - it will not find self or use another self. self=self fixes that.

But generally such magic is an anti-pattern. Tell us what are your trying to achieve, and there should be a better way to do what you want. Otherwise this kind of code will ensure many headaches.

I think this is a better solution (called strategy pattern):

class B:
    def __init__(self, a):
        self.a = a
    def temp(self):
        return self.a.temp()

class A:
    def __init__(self):
        self._temp = 10
        self.counter = 0

    def temp(self):
        return self.counter < self._temp


if __name__ == "__main__":
    obj = B(A())
    print obj.temp()
Sign up to request clarification or add additional context in comments.

3 Comments

I apologize for the bad sample code. Im working on a rather complicated project and explaining it over SO is tough. But to correct my error, the attribute_function's self parameter in my original code is another parameter for something entirely different. the self reference within the attribute_function is entirely from the creator class's attribute.
Please see my above revised code; with you help I get it. But just to confirm, referencing the attributes of that class a without implicitly passing in the parameter works correct? Is this safe?
> But just to confirm, referencing the attributes of that class a without implicitly passing in the parameter works correct? Is this safe?< It should work, and this is called closure. Think twice if you need it. The only think I would do: obj.attribute_function = lambda args, self=self: self.counter < self.temp to ensure that the correct self is used when your lambda is called. See this question
0

Your example does not work because you have a name collision at temp

You have assigned temp to be both a method:

def temp(self):

and an attribute:

self.temp = 10

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.