Naming convention for added attributes

Sometimes it is quite useful to attach an own attribute to a “foreign” object, i.e. an object not created/controlled by the application itself. It’s not a very clean style, but practical and often the most readable solution by far.

The main problem is that the attribute name must not be used by anybody else. Adding attrs with general names like .name or .extra is a bad idea. Even using ‘unlikely’ names cannot rule out a name clash completely. A change in a future library version or another combination of libraries
might create a problem.

My proposal is to create a naming convention. Just a documented recommendation, no language change.

To start the discussion, I was thinking about reserving an unique prefix:

x__<packagename>_varname    # two underscores after the x
X__<packagename>_CONSTNAME

where <packagename> is equal to the __package__ string. My working name for this is “xunder”.

The rules are simple and predictable:

  1. A class definition should avoid using names starting with x__ (also in upper case).
  2. If an application adds its attribute to a foreign object, it should follow the name format shown above.
Notes
  • Inspired by the X- prefix rule used in email header names for decades
  • One underscore is not enough. Names like .x_offset, .y_offset are common when working with coordinates.

Personally I’d only ever do this with particular foreign objects, such as functions or instances for class C from library xyz. In those cases you can check what names are already in use.

If you insist on doing this with a generic foreign object, I think you can use double-leading-underscore fairly safely. When the class uses double underscore, the name gets “mangled” (technical term). If you name your attribute __{packagename}_{varname} (or some variation thereof), you’re only going to get conflicts if another library decides to use the same trick you do, and (for reasons unknown) decides to use your library name as part of their attribute naming scheme.

I don’t see how you’re going to get more safety than that. Even if it’s documented they shouldn’t, another library could easily create a class that does use attribute name x__{your packagename}_{some varname}. But if you use double leading underscore, you can only get into conflict with other libraries that use the same obscure trick, and use your library name as part of their naming scheme (for reasons unknown).

attrs puts the __attrs_attrs__ attribute onto classes it decorates, and I’ve never heard of that causing problems.

1 Like

There is a downside that linters complain about “access to a protected member”.

that’s a rule you can turn off, no?
I’m imagining you’re using this trick in an isolated library, or in just a few files. In the first case you can add the exemption to the pyproject.toml/ruff.toml/equivalent, in that latter case you can put #noqa {linter}: W0212 or something in that direction at the top of the files.

Frankly you are doing something naughty, so it is appropriate that the linter warns you. But that doesn’t mean you definitely shouldn’t do it, just that you should think carefully whether this is something you really want to do, and whether there is no better alternative.

1 Like