Are PEP8, Pylint & Type Hint Bad!?

Sheriff Babu
10 min readFeb 28, 2023

PEP8, also known as Python Enhancement Proposal 8, is a set of guidelines for coding style in Python. It covers everything from code layout to naming conventions, indentation, comments, and whitespace. The purpose of PEP8 is to promote consistency and readability across Python codebases, making it easier for developers to understand and maintain code.

PEP8 recommends specific guidelines for spacing inside objects, such as using a single space after commas separating elements in lists or tuples, and a single space before and after the assignment operator (=) in assignments. While these guidelines can help promote consistency and readability, there may be instances where following them strictly can be difficult or even disadvantageous.

One potential disadvantage of strictly following PEP8 guidelines for spacing inside objects is that it can lead to code that is more difficult to read and understand, especially for developers who are new to the codebase or unfamiliar with PEP8 conventions. For example, a long list of function arguments with consistent spacing may be more difficult to read and parse than one with more natural spacing that breaks up the elements in a more readable way. Additionally, following PEP8 guidelines for spacing can sometimes lead to longer lines of code, which can be more difficult to read and navigate in some cases.

Another potential disadvantage of strict adherence to PEP8 guidelines for spacing inside objects is that it can sometimes be unnecessary or even counterproductive. For example, in some cases, adding extra whitespace to separate elements in a list or tuple can actually make the code less readable or more difficult to follow. Similarly, in some cases, breaking up a long line of code into multiple lines with natural spacing can make the code easier to read and understand.

Despite these potential disadvantages, it is important to note that following PEP8 guidelines for spacing inside objects can still be valuable in many cases. By adhering to these conventions, developers can ensure consistency and readability across a codebase, making it easier for other developers to read, understand, and maintain the code over time. Additionally, following PEP8 guidelines for spacing can sometimes help catch errors or bugs in code, making it easier to identify and fix issues before they become more significant problems.

Ultimately, the decision to strictly follow PEP8 guidelines for spacing inside objects will depend on the specific needs and requirements of each codebase and development team. While there may be instances where deviating from these conventions can lead to more readable or efficient code, it is still important to prioritize consistency and readability wherever possible to ensure high-quality code that is easy to maintain and understand over time.

Here is a specific use case that illustrates the potential disadvantages of strictly following PEP8 guidelines for spacing inside objects:

Let’s say you have a long list of function arguments that you need to pass to a method, and you want to keep them all on a single line for brevity. Following PEP8 guidelines for spacing, you would separate each argument with a single space after the comma, like so:

result = my_function(arg1, arg2, arg3, arg4, arg5, arg6)

While this adheres to PEP8 guidelines for spacing, it can make the code more difficult to read and parse, especially if the arguments themselves are complex or have long names. In this case, breaking up the arguments onto multiple lines with natural spacing might actually make the code more readable and easier to understand, like so:

result = my_function(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6
)

This approach provides more whitespace around each argument, making it easier to distinguish between them and understand their purpose. While this approach does not strictly adhere to PEP8 guidelines for spacing, it can lead to more readable and maintainable code in some cases, especially for longer lists of arguments.

Of course, in other cases, strict adherence to PEP8 guidelines for spacing may be more appropriate or necessary, depending on the specific needs and requirements of the codebase and development team. The key is to strike a balance between following established conventions for consistency and readability, and adapting those conventions as needed to fit the specific circumstances of each codebase and project.

Another specific use case that illustrates the potential disadvantages of using tabs instead of spaces is in the use of tabular data.

In tabular data, such as a spreadsheet or a table in a database, it is common to use tabs to separate columns of data. However, when it comes to writing code, using tabs instead of spaces can lead to inconsistent and hard-to-read code, especially when different developers have different tab widths configured on their editors.

For example, consider the following code snippet that uses tabs instead of spaces to indent a block of code:

def my_function():
# this code block is indented with tabs
if some_condition:
# do something
pass
else:
# do something else
pass

Another specific use case that illustrates the potential disadvantages of using tabs instead of spaces is in the use of tabular data.

In tabular data, such as a spreadsheet or a table in a database, it is common to use tabs to separate columns of data. However, when it comes to writing code, using tabs instead of spaces can lead to inconsistent and hard-to-read code, especially when different developers have different tab widths configured on their editors.

For example, consider the following code snippet that uses tabs instead of spaces to indent a block of code:

def my_function():
# this code block is indented with tabs
if some_condition:
# do something
pass
else:
# do something else
pass

If a developer with a tab width of four spaces opens this code in their editor, it will look like this:

def my_function():
# this code block is indented with tabs
if some_condition:
# do something
pass
else:
# do something else
pass

As you can see, the code block is no longer indented consistently, making it more difficult to read and understand. If this code were to be shared with other developers with different tab widths configured on their editors, the inconsistencies could become even more pronounced, leading to even greater confusion and potential errors.

In contrast, if the code were indented using spaces instead of tabs, it would remain consistent and readable across different editors and configurations, like so:

def my_function():
# this code block is indented with spaces
if some_condition:
# do something
pass
else:
# do something else
pass

Of course, there may be cases where using tabs instead of spaces is more appropriate or necessary, depending on the specific needs and requirements of the codebase and development team. The key is to use a consistent and well-documented approach to indentation that works well for the specific project and team.

Pylint

Pylint, on the other hand, is a popular static code analysis tool that checks Python code for errors and enforces PEP8 guidelines. It analyzes code for syntax errors, unused variables, and other common issues. By providing feedback on code quality and adherence to PEP8 standards, Pylint helps developers catch and fix issues before they become more significant problems.

While Pylint is a useful tool for enforcing code quality and adherence to coding standards, it does have some disadvantages that are worth considering:

  1. False positives: Pylint may report issues that are not actually problems, leading to wasted time and effort in addressing non-existent issues. For example, Pylint may report an error for a variable that is only used in a subclass, but not in the parent class, even though it is not an actual issue.
  2. Overly strict rules: Pylint’s default configuration is quite strict, and it can be difficult to customize its settings to fit the specific needs of a codebase. This can lead to conflicts between Pylint’s rules and the needs of the development team or project, leading to frustration and wasted time.
  3. Limited scope: Pylint is designed to check for issues at the source code level, but it may not be able to catch issues that occur at runtime, such as unexpected behavior due to input validation or boundary conditions.
  4. Performance impact: Running Pylint can be resource-intensive, especially on large codebases. This can lead to longer build times, slower feedback cycles, and increased frustration among developers.
  5. False sense of security: While Pylint can catch some issues, it cannot catch all issues. Relying solely on Pylint to ensure code quality can lead to a false sense of security, and may result in issues slipping through the cracks.

One specific use case that illustrates the potential disadvantages of using Pylint is when it reports false positives that are not actually problems.

For example, Pylint may report an error for a variable that is only used in a subclass, but not in the parent class. While this may technically be a violation of Pylint’s rules, it is not necessarily a problem in the context of the codebase and may lead to wasted time and effort in addressing non-existent issues.

Consider the following code snippet:

class Parent:
def __init__(self, x):
self.x = x

class Child(Parent):
def __init__(self, x, y):
super().__init__(x)
self.y = y

If we run Pylint on this code, it may report an error for the x variable in the Parent class, since it is not used in the subclass Child. However, this is not actually a problem, as x is still being initialized and stored in the Parent class, which may be used elsewhere in the codebase.

While Pylint can be configured to ignore certain types of issues, it can be difficult to customize its settings to fit the specific needs of a codebase. This can lead to conflicts between Pylint’s rules and the needs of the development team or project, leading to frustration and wasted time.

In cases like this, it may be necessary to suppress or disable certain Pylint checks, or to adjust its configuration to fit the specific needs of the codebase and development team. Additionally, it may be necessary to invest in other tools and practices, such as code reviews and unit testing, to ensure comprehensive coverage of code quality issues.

Of course, these disadvantages do not mean that Pylint should be avoided altogether. Rather, it is important to use Pylint judiciously and in combination with other tools and practices to ensure high-quality code. Additionally, it may be necessary to customize Pylint’s settings to fit the specific needs of a codebase, and to invest in other tools and practices, such as unit testing and code reviews, to ensure comprehensive coverage of code quality issues.

Type Hints:

Type hints, introduced in Python 3.5, provide a way for developers to annotate function signatures and variable types to help catch type-related bugs during development. Type hints can help make code more self-documenting and easier to read, especially when working with large codebases or collaborating with other developers.

Despite the benefits of these tools and standards, there are some criticisms and limitations to consider. For example, there may be cases where adhering strictly to PEP8 guidelines can make code less readable or efficient. Similarly, some experts argue that type hints can sometimes be unnecessary or add unnecessary complexity to code.

In some cases, code that violates PEP8 or doesn’t use type hints may still work well or even have some advantages over compliant code. For instance, some developers may find that deviating from PEP8 standards can make code more readable or efficient in certain contexts. Additionally, omitting type hints can sometimes lead to more flexible code that can handle a wider range of input types.

However, it is important to keep in mind that these are exceptions and not the rule. In general, adhering to PEP8 guidelines and using type hints can help create more readable, maintainable, and high-quality code.

In my opinion, developers should strive to adhere to PEP8 guidelines and use type hints where appropriate to ensure code quality and consistency. However, it is also important to exercise judgment and flexibility in certain contexts where deviating from these standards can lead to more readable or efficient code. Ultimately, the key is to strike a balance between adhering to best practices and adapting to the unique needs of each project or codebase.

A specific use case of how type hints can be a disadvantage is when you want to write code that is flexible and dynamic. For example, if you have a function that can accept different types of arguments and perform different actions based on their types, using type hints might limit your options or make your code less readable. For example:

def concat(a: int, b: int) -> str:
return str(a) + str(b)

def concat(a: str, b: str) -> str:
return a + b

This code will raise an error because Python does not support function overloading based on type hints. You would have to use a different name for each function or use a generic type hint like Any. Alternatively, you could write a single function without type hints that checks the types of the arguments at runtime:

def concat(a, b):
if isinstance(a, int) and isinstance(b, int):
return str(a) + str(b)
elif isinstance(a, str) and isinstance(b, str):
return a + b
else:
raise TypeError("Invalid types for concatenation")

This code will work for any combination of integers and strings as arguments. However, it might be less clear what the function does or expects without reading the code body or documentation. Therefore, using type hints depends on your preferences and needs as a developer.

Conclusion

In conclusion, while there are criticisms and limitations to consider, PEP8, pylint, and type hints remain valuable tools for promoting code quality and consistency in Python development. By using these tools judiciously, developers can create more readable, maintainable, and high-quality code that is easier to understand and maintain over time.

Thank you for reading! I would love to hear from you and will do my best to respond promptly. Thank you again for your time, and have a great day! If you have any questions or feedback, please let us know in the comments below or email me.

Subscribe, follow and become a fan to get regular updates.

https://www.buymeacoffee.com/sheriffbabu

--

--

Sheriff Babu

Management #consultant and enthusiastic advocate of #sustainableag, #drones, #AI, and more. Let's explore the limitless possibilities of #innovation together!