Python: имя класса PEP 8 как переменная
Каково соглашение в соответствии с PEP 8 для записи переменных, которые идентифицируют имена классов (а не экземпляры)?
То есть, учитывая два класса, A
и B
, какой из следующих утверждений был бы правильным?
target_class = A if some_condition else B
instance = target_class()
или
TargetClass = A if some_condition else B
instance = TargetClass()
Как указано в руководстве по стилю,
Имена классов:
Имена классов обычно должны использовать соглашение CapWords.
Но также
Имена методов и переменные экземпляра:
Используйте правила именования функций: в нижнем регистре со словами, разделенными символами подчеркивания, для повышения удобочитаемости.
По-моему, эти две конвенции сталкиваются, и я не могу найти, какой из них преобладает.
Ответы
Ответ 1
Наконец-то я нашел некоторый свет в руководстве :
Имена классов
[...]
Соглашение об именах для функций может использоваться вместо этого в случаях, когда интерфейс документирован и используется в основном как вызываемый.
может использоваться не как сильное утверждение, но оно охватывает случай, поскольку переменная должна была использоваться как вызываемая.
Итак, для общего назначения я считаю, что
target_class = A if some_condition else B
instance = target_class()
лучше, чем
TargetClass = A if some_condition else B
instance = TargetClass()
Ответ 2
При отсутствии конкретного покрытия этого случая в PEP 8 можно составить аргумент для обеих сторон медали:
Одна сторона: Поскольку A
и B
оба являются переменными, но сохраняйте ссылку на класс, используйте CamelCase (TargetClass
) в этом случае.
Ничто не мешает вам делать
class A: pass
class B: pass
x = A
A = B
B = x
Теперь A
и B
указывают на соответствующий класс, поэтому они действительно не привязаны к классу.
So A
и B
несут единственную ответственность за сохранение класса (независимо от того, имеют ли они одно и то же имя или другое) и поэтому имеет TargetClass
.
Чтобы оставаться беспристрастным, мы также можем спорить по-другому: A
и B
являются особыми, поскольку они создаются вместе с их классами, а внутренности классов имеют одинаковое имя. Пока они являются "оригинальными", любое другое задание должно быть отмечено специальным, поскольку оно должно рассматриваться как переменная и, следовательно, в lower_case
.
Истина заключается, как часто, где-то посередине. Есть случаи, когда я бы пошел в одну сторону, а другие, где бы я пошел другим путем.
Пример 1: вы передаете класс, который, возможно, должен быть создан, методу или функции:
def create_new_one(cls):
return cls()
class A: pass
class B: pass
print(create_new_one(A))
В этом случае cls
явно имеет очень временное состояние и, очевидно, переменную; могут быть разными при каждом вызове. Поэтому это должно быть lower_case
.
Пример 2: Смещение класса
class OldAPI: pass
class NewAPI: pass
class ThirdAPI: pass
CurrentAPI = ThirdAPI
В этом случае CurrentAPI
следует рассматривать как своего рода псевдоним для другого и остается постоянным во время прогона программы. Здесь я бы предпочел CamelCase
.
Ответ 3
Я лично считаю, что если указанная вами переменная, содержащая ссылку на класс, определяется как временная переменная (например, в процедуре или функции) или как вывод из существующего класса в глобальном спектре, самый вес в случае использования. Итак, подведем итог из вышеприведенного ответа:
-
Если переменная является временной, например. внутри функции или используется в одном экземпляре при решении проблемы, она должна быть lower_case
с подчеркиванием разделения.
-
Если переменная находится в глобальном спектре и определяется вместе с другими классами как псевдоним или деривация, используемые для создания объектов в теле программы, его следует определить с помощью CamelCase
.
Ответ 4
В случае сомнений я бы сделал то же самое, что и разработчики Python. Они все-таки писали PEP-8.
Вы можете рассмотреть свою строку:
target_class = A if some_condition else B
в виде строки в виде строки:
target_class = target_class_factory()
и для него есть известный пример в библиотеке Python, namedtuple, который использует CamelCase.