1

I want to define a function, call it test_controller(), and I want to pass this function to a constructor: my_thing = TestClass(test_controller). This function needs to be able to modify its class's data objects. I've heard of the nonlocal keyword for Python 3, but I'm running Python 2.7. Is it possible? How do I do this? Here's what I have tried already.

class TestClass(object):

    def __init__(self, ctrl_func):
        self.a = 4
        self.ctrl_func = ctrl_func

    def do_stuff(self):
        self.ctrl_func()

def test_controller():
    global a
    a = 20

my_thing = TestClass(test_controller)
print my_thing.a         #this prints 4
my_thing.ctrl_func()
print my_thing.a         #this prints 4 but I want it to print 20
Taylor
  • 1,393
  • 2
  • 16
  • 40

1 Answers1

3

You can pass in a reference to whatever object you intend to modify.

class TestClass(object):

    def __init__(self, ctrl_func):
        self.a = 4
        self.ctrl_func = ctrl_func

    def do_stuff(self):
        self.ctrl_func(self)

def test_controller(self):
    self.a = 20

my_thing = TestClass(test_controller)
print my_thing.a         #this prints 4
my_thing.ctrl_func(my_thing)
print my_thing.a         #this prints 4 but I want it to print 20

Alternatively, you can convert ctrl_func into a bound method of the object:

import types

class TestClass(object):

    def __init__(self, ctrl_func):
        self.a = 4
        self.ctrl_func = types.MethodType(ctrl_func, self)

    def do_stuff(self):
        self.ctrl_func()

def test_controller(self):
    self.a = 20

my_thing = TestClass(test_controller)
print my_thing.a         #this prints 4
my_thing.ctrl_func()
print my_thing.a         #this prints 4 but I want it to print 20

Reference:

Community
  • 1
  • 1
Robᵩ
  • 143,876
  • 16
  • 205
  • 276
  • 1
    @Taylor - note change in 2nd example. `types.MethodType()` appears to be preferred over `__get__()`. – Robᵩ Apr 20 '16 at 23:58