The underscore in Python is used to very weakly denote an implementation detail.
It indicates a method that’s used solely inside a class for carrying out some work, but which should never be called by anything using that class. As a basic example:
class DoStuff
def do_now(self):
_carry_out_work()
def _carry_out_work():
print("Hello!")
In this instance, you’d run:
stuff = DoStuff()
stuff.do_now()
But you would never run:
stuff._carry_out_work()
Because you’d be accessing a function that may be dependent upon something happening in do_now
or may even be changed or renamed in future. An implementation detail, rather than a specific part of the class API.
In the case of flotilla, both on_connect
and on_disconnect
are part of the class API, and provide functions which can be used as decorators. They’re not an implementation detail, and what they do will stay broadly the same throughout versions of Flotilla. However you would generally call them like so:
@flotilla.on_connect():
def my_connect_handler():
print("Connected!)
Confusingly, the class variables self._on_connect
and self._on_disconnect
exist too, these are totally discrete from on_connect
and on_disconnect
and just provide a place to store the connect/disconnect handlers that you might register.
A method like _handle_module_command
is an internal command that relies upon some preparation that happens in _handle_command
, it’s a structural choice rather than something intended to be part of the public class API.
In future I might break down _handle_module_command
into more manageable chunks, break it out into a subclass for parsing commands, or who knows what- the underscore prefix denotes that you should never rely upon or trust that it will stay the same.
So in summary:
_some_method
is a private implementation detail subject to change/removal/refactoring across versions
whereas:
some_method
is a method that, breaking changes aside, you can always depend upon to be available