3

I would like to use a name mangled name in Python, to avoid subclasses from accessing the attribute. I know I can just do _classname__attributename, but according to the documentation, "If the transformed name is extremely long (longer than 255 characters), implementation defined truncation may happen. If the class name consists only of underscores, no transformation is done." I'm particularly worried about the "implementation defined" part. It seems there are also some subtleties. Is there a standard library function to convert a class name plus an attribute name into its name mangled equivalent?

Background

I want to decorate a class's docstring to be able to say whether or not it requires certain optional external dependencies, so that it can be automatically enabled or disabled in the doctest runner (full details at https://github.com/sympy/sympy/pull/1969).

Ideally, to do this, you would add an attribute to the docstring, but Python does not allow adding attributes to strings. So instead, you have to add an attribute to the class. What I need is an attribute that is not inherited by subclasses, since docstrings are not inherited. Otherwise, subclasses will have their docstrings incorrectly decorated. My original solution was to use a descriptor object that disables the attribute for subclasses, but this is a little complicated when something like name mangling already exists that basically already does this, excepting this one subtlety.

martineau
  • 119,623
  • 25
  • 170
  • 301
asmeurer
  • 86,894
  • 26
  • 169
  • 240
  • 1
    possible duplicate of [Python name mangling function](http://stackoverflow.com/questions/11024344/python-name-mangling-function) – jamylak Apr 06 '13 at 01:13
  • By the way, I realize that you can also achieve this by using descriptors, but name mangling seems like a much simpler way to do it, except for this one subtlety. – asmeurer Apr 06 '13 at 01:14
  • Oh yeah, that is a duplicate. It's too bad that `compile` no longer exists in Python 3. That kind of defeats the whole purpose of the "implementation specific" part. Does anyone know if alternate Pythons like PyPy, Jython, or IronPython also use 256? – asmeurer Apr 06 '13 at 01:16
  • I guess you should mention that you use Python 3 (or need it to be implementation specific) if that's a problem for you so this doesn't get closed as a duplicate now – jamylak Apr 06 '13 at 01:19
  • Is this a class you're writing? If so, why are you using mangled attributes if you're going to need to access them from outside the class? – BrenBarn Apr 06 '13 at 01:23
  • I explained why in the other question, but I'll edit this question with some more information. – asmeurer Apr 06 '13 at 01:50
  • @BrenBarn I edited the question with why I want to do this. – asmeurer Apr 06 '13 at 01:54
  • I can't seem to reproduce the truncation. If I create a class with a really long name and add a name mangled attribute with a really long name (each longer than 256 characters), the mangled name is not truncated. – asmeurer Apr 06 '13 at 01:58
  • But in PyPy, really long class names are truncated. So it seems like this is a real issue (at least if such a thing comes up, which actually isn't very likely). – asmeurer Apr 06 '13 at 02:00
  • Oups, the fact that PyPy truncates is inherited from some old version of CPython (2.4?). Now CPython no longer truncates, indeed. It will be fixed in future PyPy's. – Armin Rigo Apr 06 '13 at 10:16
  • A simple workaround which should work in most cases is `difflib.get_close_matches('_ClassName_attribute_name', the_instance.__dict__, 1, 0.8)`(where `_ClassName_attribute_name` *isn't* truncated) Or you could sort the attributes of the object using `SequenceMatcher.ratio` and check to see if the most similar is the one you are looking for. – Bakuriu Apr 06 '13 at 13:24

0 Answers0