Providing QGIS expression within a plugin

You can ship them in your plugin.

Create a Python file called, for example, qgis_expression.py:

from qgis.utils import qgsfunction

@qgsfunction(
    args='auto', group='Your group', usesGeometry=False, referencedColumns=[], helpText='Define the help string here')
def your_expression(params, feature, parent):
    # UPDATE the qgsfunction above
    # ADD HERE THE EXPRESSION CODE THAT YOU WROTE IN QGIS.
    return 'your_result'

In the entry point of your plugin, in the file containing initGui and unload:

# Simply import the function, the decorator qgsfunction will register it in QGIS.
from qgis.core import QgsExpression
from .qgis_expression import your_expression


def unload(self):
    # Do not forget to unload your expression with the plugin
    QgsExpression.unregisterFunction(your_expression.name())

You can add your custom functions to your plugin. The main file of plugin should be like this:

from qgis.utils import iface, qgsfunction
from qgis.core import QgsExpression


#### YOUR CUSTOM FUNCTION ####
@qgsfunction(args='auto', group='customFunctions', register = False)
def custom_function1(values, feature, parent):
    #
    # CODE
    #
    # return

#############################

class customFunctions: # main class of plugin
    def __init__(self, iface):
        self.iface = iface

    def initGui(self):        
        ### REGISTER ###
        QgsExpression.registerFunction(custom_function1)        
        #####################

    def unload(self):        
        ### UNREGISTER ###
        QgsExpression.unregisterFunction('custom_function1')
        ##################

In the end I ended up combining Kadir's and etrimaille's answers and adding one crucial part.

I used etrimaille's idea of having the function in its own file and importing that into my plugin, as that fits better with the structure of the existing plugin. To have this to work, I needed to put the import statements into the file with the function in it.

from qgis.utils import iface, qgsfunction
from qgis.core import QgsExpression

@qgsfunction(
args='auto', group= (...)

When doing this, I also needed to add the name of the file with the function to the python_files: line in the pb_tool.cfg file. This was needed to have the file packaged and deployed.

(The plugin is based on the plugin builder, the entire source code can be found at https://github.com/sickel/altitudecorrector - the custom function is still (3rd march '20) just a dummy function)