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
user1234440
  • 22,521
  • 18
  • 61
  • 103

2 Answers2

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()
warvariuc
  • 57,116
  • 41
  • 173
  • 227
  • 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. – user1234440 Mar 26 '14 at 04:50
  • 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? – user1234440 Mar 26 '14 at 04:54
  • > 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](http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python) – warvariuc Mar 26 '14 at 06:38
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
qwwqwwq
  • 6,999
  • 2
  • 26
  • 49