Python private instance data updated

I read various "there is no really personal data in Python instances", but we all know how to use closure in Perl and JavaScript to efficiently retrieve private data. So why not Python? For instance:

import codecs class Secret: def __private(): secret_data = None def __init__(self, string): nonlocal secret_data if secret_data is None: secret_data = string def getSecret(self): return codecs.encode(secret_data, 'rot_13') return __init__, getSecret __init__, getSecret = __private() 

Now we do:

 >>> thing = Secret("gibberish") >>> thing.getSecret() 'tvoorevfu' >>> dir(thing) ['_Secret__private', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'getSecret'] 

What can you do for an instance to get read access to the original string (ignoring my weak encryption) or write access to it?

I am teaching Python lessons to my students this week, and I am trying to understand why, given the closure, the methods for JavaScript and Perl will not work for Python.

Thanks.

+5
source share
2 answers

If you just want to access the original, it's not that difficult, as the Python function implements a fairly thorough api check. You can access the original secret with something like this:

 thing = Secret("gibberish") # __init__ doesn't need to be used here; anything defined within the closure will do thing.__init__.__func__.__closure__[0].cell_contents 

And hey! We get the original value.

This is more difficult, but not impossible --- to change the value (see here ). Changed for this setting:

 import ctypes ... thing = Secret("gibberish") cell = ctypes.py_object(thing.__init__.__func__.__closure__[0]) new_value = ctypes.py_object('whatever') ctypes.pythonapi.PyCell_Set(cell, new_value) thing.getSecret() 
+4
source

Usually you did not do this, but you can dig an instance using the inspect module.

 >>> thing = Secret("gibberish") >>> thing.getSecret() 'tvoorevfu' >>> import inspect >>> inspect.getclosurevars(thing.getSecret).nonlocals['secret_data'] 'gibberish' >>> inspect.getclosurevars(thing.__init__).nonlocals['secret_data'] 'gibberish' 

Given one of the functions in a closure, you can access closure variables. I have not yet found a way to change the variable.

So it’s not impossible if you are ready to make some efforts. Why you do this in the normal course of programming, I don’t know.

+3
source

Source: https://habr.com/ru/post/1242751/


All Articles