Which is the convention according to PEP 8 for writing variables that identify class names (not instances)?
That is, given two classes, A
and B
, which of the following statements would be the right one?
target_class = A if some_condition else B
instance = target_class()
or
TargetClass = A if some_condition else B
instance = TargetClass()
Class Names:
Class names should normally use the CapWords convention.
But also
Method Names and Instance Variables:
Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.
In my opinion, these two conventions clash and I can't find which one prevails.
I try to adhere to the style guide for Python code (also known as PEP 8). Accordingly, the preferred way to name a class is using CamelCase: Almost without exception, class names use the CapWords convention.
PEP 8 is, as python.org puts it, a style guide for Python code. It helps us write code which is easily readable, so that if we were to show to other developers, or even ourselves in the future, they would be able to understand what's going on from the first glimpse.
Naming conventions in PEP 8 Naming conventions are rules, which although not mandatory allow us to keep our code clean and Pythonic. Naming convetnions should be used when naming variables, functions and classes. We've already briefly discussed naming conventions in Python in on of our first tutorials about variables.
Names of type variables introduced in PEP 484 should normally use CapWords preferring short names: T, AnyStr, Num. It is recommended to add suffixes _co or _contra to the variables used to declare covariant or contravariant behavior correspondingly:
PEP 8 suggests lines should be limited to 79 characters. This is because it allows you to have multiple files open next to one another, while also avoiding line wrapping.
In lack of a specific covering of this case in PEP 8, one can make up an argument for both sides of the medal:
One side is: As A
and B
both are variables as well, but hold a reference to a class, use CamelCase (TargetClass
) in this case.
Nothing prevents you from doing
class A: pass
class B: pass
x = A
A = B
B = x
Now A
and B
point to the respectively other class, so they aren't really fixed to the class.
So A
and B
have the only responsibility to hold a class (no matter if they have the same name or a different one), and so has TargetClass
.
In order to remain unbiased, we as well can argue in the other way: A
and B
are special in so far as they are created along with their classes, and the classes' internals have the same name. In so far they are kind of "original", any other assignment should be marked special in so far as they are to be seen as a variable and thus in lower_case
.
The truth lies, as so often, somewhere in the middle. There are cases where I would go one way, and others where I would go the other way.
Example 1: You pass a class, which maybe should be instantiated, to a method or function:
def create_new_one(cls):
return cls()
class A: pass
class B: pass
print(create_new_one(A))
In this case, cls
is clearly of very temporary state and clearly a variable; can be different at every call. So it should be lower_case
.
Example 2: Aliasing of a class
class OldAPI: pass
class NewAPI: pass
class ThirdAPI: pass
CurrentAPI = ThirdAPI
In this case, CurrentAPI
is to be seen as a kind of alias for the other one and remains constant throughout the program run. Here I would prefer CamelCase
.
I personally think that whether the variable you mentioned, which holds a reference to a class, is defined as a temporary variable (for example in a procedure or function) or as a derivation from an existing class in the global spectrum has the most weight in the case of which one to use. So to summarise from the reply above:
If the variable is temporary, e.g. inside a function or used in a single instance in the solving of a problem, it should be lower_case
with underscore separation.
If the variable is within the global spectrum, and is defined along with the other classes as an alias or derivation to use to create objects in the body of the program, it should be defined using CamelCase
.
In case of doubt I would do the same as Python developers. They wrote the PEP-8 after all.
You can consider your line:
target_class = A if some_condition else B
as an in-line form of the pattern:
target_class = target_class_factory()
and there is a well-known example for it in the Python library, the namedtuple, which uses CamelCase.
I finally found some light in the style guide:
Class Names
[...]
The naming convention for functions may be used instead in cases where the interface is documented and used primarily as a callable.
may be used is not a strong statement, but it covers the case, as the variable was intended to be used as a callable.
So, for general purpose I think that
target_class = A if some_condition else B
instance = target_class()
is better than
TargetClass = A if some_condition else B
instance = TargetClass()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With