PEP8 and PyQt, how to reconcile function capitalization?

Question:

I’m starting to use PyQt in some projects and I’m running into a stylistic dilemma. PyQt’s functions use camel case, but PEP8, which I prefer to follow, says to use underscores and all lowercase for function names.

So on the one hand, I can continue to follow PEP8, meaning that my code will have mixed functions calls to camel case and underscore functions, and even my classes will have mixed function names, since I’ll need to be overloading functions like mousePressEvent. Or, I can break PEP8 and adopt camel case for all my function names in the name of consistency.

I realize this is subjective and it’s really just what I personally prefer, but I like to hear from others about what they do and why they chose to do it that way.

Asked By: Colin

||

Answers:

In your shoes, I wouldn’t fight your framework, just like, as a general principle, I don’t fight City Hall;-). I happen to share your preference for lowercase-with-underscore function names as PEP 8 specifies, but when I’m programming in a framework that forces a different capitalization style, I resign myself to adopting that style too, since I can’t convince the framework to adopt the “better” style, and style inconsistencies (haphazard mixes of different styles) are really worse.

Of course, some mixage is inevitable if you’re using more than one framework… e.g., PyQt with its camelcase, and standard Python library functions with their lowercase and underscores!-). But since frameworks like Qt are often intended to be extended by subclassing, while the standard Python library has less aspects of such a design, in most case where the capitalization style is forced (because you need to override a method, so you can’t choose a different capitalization), it will be forced to camelcase (by Qt), only rarely to lowercase (by the standard Python library). So, I think that adopting Qt style in this case is still the lesser evil.

Answered By: Alex Martelli

Use what fits best.

If you’re subclassing Qt classes, or have a function heavily integrated with them UseCamelCase.

Otherwise, use_underscores.

Answered By: Joe D

Maybe sensible use of modules to separate the styles in different modules can help. At least try to modularize basic PEP8 style code to own module of helper functions.

Answered By: Tony Veijalainen

You can use underscores if you subclass this. And you can name your methods with underscores and PyQt4 will be able to use them as if you have named them with camelCase.

class SomeClass(object):
    def __getattr__(self, attr):
        if '_' in attr:
            new = [c for c in attr]
            while True:
                try:
                    new_char = new[new.index('_') + 1].upper()
                    new[new.index('_'):new.index('_') + 2] = new_char
                except (IndexError, ValueError):
                    break
        else:
            for c in attr:
                if c.isupper():
                    new = []
                    for i, c in enumerate(attr):
                        if i != 0 and c.isupper():
                            new.append('_')
                        new.append(c.lower())
                    break
        try:
            return super(type(self), self).__getattribute__(''.join(new))
        except Exception:
            return super(type(self), self).__getattribute__(attr)
Answered By: Artur Gaspar

The pep8 document says what to do in this case (emphasis mine):

New modules and packages (including third party frameworks) should be written to these standards, but where an existing library has a different style, internal consistency is preferred.

Answered By: Daenyth

In december 2020, with the release of Qt 6.0, the Qt for Python 6 / PySide6 (the official Python bindings for Qt) was also released, introducing a new option called __feature__. With this option you can have Qt objects with PEP8-compliant snake case methods and true properties.

Old style:

table = QTableWidget()
table.setColumnCount(2)

button = QPushButton("Add")
button.setEnabled(False)

layout = QVBoxLayout()
layout.addWidget(table)
layout.addWidget(button)

New PySide6 style:

from __feature__ import snake_case, true_property

table = QTableWidget()
table.column_count = 2

button = QPushButton("Add")
button.enabled = False

layout = QVBoxLayout()
layout.add_widget(table)
layout.add_widget(button)
Answered By: Jeyekomon