I'm sure there can be some hack to do this with functions, but better to use Object-Oriented-Programming style to support this functionality in an understandable way. You can define a class containing your functions, and users can override some functions by inheriting this class and implmenting their own variants of the functions:
# my_library.py
class LibraryFunctionality:
def my_function():
return "My function"
def my_other_function():
return "My other function"
then users could do
# user.py
import my_library
class MyFunctionality(LibraryFunctionality):
def my_function():
return "My unique function"
MyFunctionality.my_function() # returns "My unique function"
MyFunctionality.my_other_function() # returns "My other function"
If you have a large method, that you want to let users to override by parts (without requiring them to repeat the same implementation), you can use a "Template method" design pattern, where you split a big method into many functions for all the steps, and then users can override some steps selectively. For example something as big as this:
# my_library.py
class LibraryFunctionality:
def before_initialization_step():
pass
def initialization_step():
return "My"
def after_initialization_step(state):
return state
def before_work_step(state):
return state
def work_step(state):
return state + " function"
def after_work_step(state):
return state
def before_return_step(state):
return state
def return_step(state):
return state
def my_function():
LibraryFunctionality.before_initialization_step()
state = LibraryFunctionality.initialization_step()
state = LibraryFunctionality.after_initialization_step(state)
state = LibraryFunctionality.before_work_step(state)
state = LibraryFunctionality.work_step(state)
state = LibraryFunctionality.after_work_step(state)
state = LibraryFunctionality.before_return_step(state)
return LibraryFunctionality.return_step(state)
Then users can override specific steps as I've already shown:
# user.py
import my_library
class MyFunctionality(LibraryFunctionality):
def before_work_step(state):
return state + " unique"
LibraryFunctionality.my_function() # returns "My function"
MyFunctionality.my_function() # returns "My unique function"