Considere a seguinte classe:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
Meus colegas de trabalho tendem a defini-lo assim:
class Person:
name = None
age = None
def __init__(self, name, age):
self.name = name
self.age = age
A principal razão para isso é que o editor de sua escolha mostra as propriedades do preenchimento automático.
Pessoalmente, não gosto do último, porque não faz sentido que uma classe tenha essas propriedades definidas None.
Qual seria a melhor prática e por que razões?
__init__já fornece preenchimento automático etc. Além disso, o uso Noneevita que o IDE deduza um tipo melhor para o atributo, por isso é melhor usar um padrão sensato (quando possível).
typingmódulo, que permitem fornecer dicas para o IDE e linter, se esse tipo de coisa lhe apeteça ...
self. Mesmo se self.nameou self.agenão foram atribuídos em __init__que não iria aparecer na instância self, eles só aparecem na classe Person.