Недавно я начал работать над собственной библиотечкой Smart PageObject для Python тестов, и заметил, что наследование аттрибутов в Python зависит от имени аттрибута, что было неожиданно для меня, хотя я пишу на этом языке уже давно (и периодически продолжаю удивляться, да).
Рассмотрим простой пример:
Здесь стоит обратить внимание на то, что аттрибут, начинающийся с двух подчеркиваний, измененяет имя - он стал называться _a__my_attr3, хотя изначально я ожидал, что он будет называться просто __my_attr3.
При наследовании этого аттрибута другим классом мы получаем сюрпризы, так как внутренние методы класса а могут обращаться к аттрибуту __my_attr3 напрямую, при этом если мы переопределяем этот метод в классе b, то мы уже не можем обращаться к этому аттрибуту, точнее можем обращаться под другим имененем.
Подберем простой пример:
Есть класс а, у которого есть метод с двойным подчеркиванием в начале имени. Мы создаем новый класс b и наследуем его от класса a. После этого мы хотим раширить функционал класса b, добавив новую функцию:
Теперь, если мы не хотим переопределять метод input, внутри класса b мы обызаны работать с аттрибутом _a__numbers вместо __numbers, и постоянно помнить об этом.
Поэтому если вы пишете код класса, который будет наследоваться и раширяться другими разработчиками, помните про то, что имена всех методов и свойств, начинающиеся с двойного подчеркивания, будут изменены. При этом внутри нашего класса а аттрибут доступен под его изначальным именем.
Редко когда действительно необходимо использовать аттрибуты с двойным подчеркиванием в начале имени, поэтому неудивительно, что поведение при наследовании для них отличается.
Здесь стоит обратить внимание на то, что аттрибут, начинающийся с двух подчеркиваний, измененяет имя - он стал называться _a__my_attr3, хотя изначально я ожидал, что он будет называться просто __my_attr3.
При наследовании этого аттрибута другим классом мы получаем сюрпризы, так как внутренние методы класса а могут обращаться к аттрибуту __my_attr3 напрямую, при этом если мы переопределяем этот метод в классе b, то мы уже не можем обращаться к этому аттрибуту, точнее можем обращаться под другим имененем.
Подберем простой пример:
Есть класс а, у которого есть метод с двойным подчеркиванием в начале имени. Мы создаем новый класс b и наследуем его от класса a. После этого мы хотим раширить функционал класса b, добавив новую функцию:
Теперь, если мы не хотим переопределять метод input, внутри класса b мы обызаны работать с аттрибутом _a__numbers вместо __numbers, и постоянно помнить об этом.
Поэтому если вы пишете код класса, который будет наследоваться и раширяться другими разработчиками, помните про то, что имена всех методов и свойств, начинающиеся с двойного подчеркивания, будут изменены. При этом внутри нашего класса а аттрибут доступен под его изначальным именем.
Редко когда действительно необходимо использовать аттрибуты с двойным подчеркиванием в начале имени, поэтому неудивительно, что поведение при наследовании для них отличается.