-1

When we define a class in Python, i.e. we are the authors of the class,

  • are we allowed to create attributes of a class, whose names both begin and end with double underscores, and don't conflict with special attributes e.g. __base__, __class__, __name__, __dict__, and special methods such as __new__, __init__, __str__, __repr__, __hash__, __call__, __get__?

  • If yes, will the lookup for such attributes (e.g. __madeupAttribute__) that we define be the same as the lookup for those special attributes? Note that the lookup process for those special attributes is different from the lookup process for regular attributes (e.g. attribute1, attribute2), as mentioned in Python in a Nutshell

    A few attribute dunder-names are special, C.__name__, C.__bases__, x.__class__. When you refer to an attribute with one of these special names, the attribute reference looks directly into a dedicated slot in the class or instance object and fetches the value it finds there. You cannot unbind these attributes.

  • are we allowed to create attributes of a class, whose names begin with a single underscore?

  • are we allowed to create attributes of a class, whose names begin with two underscores?

Note that I have read What is the meaning of a single- and a double-underscore before an object name?. My questions in this post are: what kinds of attributes the author of a Python class can create and what not.

Thanks.

Tim
  • 1
  • 141
  • 372
  • 590
  • You can use `__author__` at the beginning of your module – amarynets Oct 05 '17 at 20:45
  • @AndMar Thanks. will the lookup for such attributes (e.g. `__madeupAttribute__`) that we define be the same as the lookup for those special attributes? Note that the lookup process for those special attributes is different from the lookup process for regular attributes (e.g. `attribute1`, `attribute2`). – Tim Oct 05 '17 at 20:46
  • These are just naming conventions, they don't have any special meaning to Python. – Barmar Oct 05 '17 at 20:46
  • Yes you're allowed to use `__name__` in your class but that's awful. For builtin look ups it's always `type(I).attr` where `I` is an instance of a class. – GIZ Oct 05 '17 at 20:46
  • @Tim see here for the full [Attribute Look-up Rules](https://1drv.ms/t/s!As3947iGKPArz3EdKQCrKpb39HA7). I've written this a long time ago and it details the rules of Attribute look ups. – GIZ Oct 05 '17 at 20:50
  • 1
    `__author__` is a [module-level name](https://www.python.org/dev/peps/pep-0008/#module-level-dunder-names). For classes, stick with what it says in the [Descriptive: Naming Styles](https://www.python.org/dev/peps/pep-0008/#descriptive-naming-styles) section. See specifically the "special forms" **`__double_leading_underscore`**, **`_single_leading_underscore`** and **`__double_leading_and_trailing_underscore`** —you should avoid ever creating any of your own attribute names that follow those patterns. – martineau Oct 05 '17 at 20:53
  • @direprobs Thanks. Will `__madeupAttribute__` which I made up be looked up in the same way as `__new__` and `__name__`, or as `attribute1` which I also made up? – Tim Oct 05 '17 at 20:53
  • @Tim It depends on how `__madeupAttribute__` is fetched and I mean by that implicitly fetched by builtin operation or explicitly fetched like the majority of the case. Everything is detailed at the text file I provided. – GIZ Oct 05 '17 at 20:58
  • 1
    You can make whatever attributes you want. [With a metaclass, you can even override most of the "special" attributes.](https://ideone.com/akMCko) – user2357112 Oct 05 '17 at 20:59
  • `__madeupAttribute__` might be safe, however it will be "mangled" outside of the class (i.e. need to be prefixed with an underscore and the class name like `_FooBar_madeupAttribute__` (although PEP 8 recommends **not** using `camelCase` names that start with a lowercase character, which means they're only good for a `ClassName`). – martineau Oct 05 '17 at 21:04
  • The link that I provided is dead see here instead: [Attribute Look-up Rules](https://paste.ubuntu.com/25681970/). – GIZ Oct 05 '17 at 21:08
  • @Barmar: I strongly disagree. Some **do** have special meaning in Python and should be avoided. – martineau Oct 05 '17 at 21:08
  • 1
    @martineau Specific names have special meaning, but the underscores themselves are not special. The rules require the special names to follow the underscore conventions. – Barmar Oct 05 '17 at 21:11
  • @Barmar: The rules are that any name with double underscores will be mangled at certain times—so they're not special unless there are two of them at the beginning of an identifier. This is not true of single underscore prefix. – martineau Oct 05 '17 at 21:14

1 Answers1

1

are we allowed to create attributes of a class, whose names both begin and end with double underscores, and don't conflict with special attributes? If yes, will the lookup for such attributes (e.g. __madeupAttribute__) that we define be the same as the lookup for those special attributes?

If you create an attribute which name has double underscores on both sides, it gets no special treatment whatsoever. Only the attribute names reserved by the language have a special look-up treatment. Some of those may or may not be directly created by the class author. Most names intended for methods that are responsible to implement operations with the objects of that class, such as __add__, __mul__ can be freely writable. Others, will be overwritten on class creation, but are free to be changed afterwards, such as __name__, while still others are created along with the class and are imutable, such as __mro__. Names not listed on the documentation are just like ordinary names, but may get in conflict with future special names added to the language object model.You will be able to locate most special attribute and method names in the language data model, although some attributes can be used by specific stdlib modules and not be listed there. (They have no special meaning for the language as well, just for that module. One example is __reduce__, used by pickle)

are we allowed to create attributes of a class, whose names begin with a single underscore?

Yes - single underscore has no special meaning for Python at all, it is just a convention that code outside the class/package that created anything starting with an underscore should not change that directly or rely on its value or on its existence. This convention is what replaces "private" attributes and names in use in other languages

are we allowed to create attributes of a class, whose names begin with two underscores?

For attributes of a class prefixed by two underscores, there is a special treatment at compile time that mangles those names, baking the class's name into the attribute name itself. All code written inside a class body (including inside methods, and inside nested functions into those methods) is changed in the same way. This name modification makes it so that classes that inherit from that one, if they use the same attribute name in their code, that attribute will not clash and be independent from the attribute on the parent class. This feature may be used to provide encapsulation for attributes you don't intend derived class to read or write, but again that is more due to convention and convenience, since the name mangling rules are well known. Early Python documentation often implied that this should be used for "private attributes". That is somewhat incorrect: "private" in Python is by convention only, and for readability purposes, often relies on a single prefixed underscore.

jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • Thanks. Does the lookup process for special data attributes `__dict__ __name__, __class__`, also apply to special method attributes `__new__, __init__, __str__, __repr__`? – Tim Oct 05 '17 at 21:22
  • @Tim: Only when it makes sense to do so. `__dict__` and `__class__` are instance attributes, so looking them up on the type wouldn't work. `__new__` is a *static* hook method that applies specifically to classes to create new instances. Specifically, the rule applies only to special **methods**, so yes, `__init__`,`__str__` and `__repr__` are all subject to the rule. – Martijn Pieters Oct 05 '17 at 21:34
  • @MartijnPieters Thanks for pointing out the differences between the attributes. Does what Python in a Nutshell says in the following apply to `__dict__, __class__, __name__, __new__, __init__, _-str__, __repr__`? "When you refer to an attribute with one of these special names, the attribute reference looks directly into a dedicated slot in **the class or instance object** and fetches the value it finds there. " – Tim Oct 05 '17 at 21:49
  • @Tim: That snippet applies to the specific names listed in the text. For example, see the [`type_name` function](https://github.com/python/cpython/blob/v3.6.3/Objects/typeobject.c#L369-L388) which is the descriptor for `classobj.__name__`. Note that it is *still a descriptor object*, so `classobj.__name__` still uses the metatype `__getattribute__` hook to find that descriptor and bind it. – Martijn Pieters Oct 05 '17 at 22:05