when you code in many languages, you usually need to dig a bit to find answers to questions that are not immediately obvious in a specific language. Mine was whether closures can simulate real private variables in python (i.e that really can’t be accessed as opposed to the __ mangling method).
I decided to test if this would work with closures, as shown below
def outer(a,b): class this: pass #-------------------------- # real private variables and methods go here this.a = a this.b = b def sum_(): return this.a + this.b def product_(): return this.a * this.b def set_nums_(a, b): this.a, this.b = a, b #-------------------------- # public variables and methods go here class inner: def get_nums(self): return this.a, this.b def set_nums(self, a, b): set_nums_(a,b) def sum(self): return sum_() def product(self): return product_() return inner()
and the result:
>>> x = outer(5,3) >>> x.get_nums() (5, 3) >>> x.set_nums(5,4) >>> x.get_nums() (5, 4) >>> x.product() 20 >>> x <__main__.outer..inner object at 0x0000023C581E21C0> >>>
Yay! seems like it works.
Of course, a bit of further digging showed that every python object has the
__closure__ property through which you can access the closure for that object, and changing the values of the “private” variables above (bypassing the set_nums method) just becomes a matter of:
>>> loophole = x.sum.__closure__.cell_contents.__closure__.cell_contents >>> loophole <class '__main__.outer.<locals>.this'> >>> loophole.a = 8 >>> loophole.b = 9 >>> x.get_nums() (8, 9) >>>