0

I want to overwrite a function in a python library. Example: This is my library, already compiled, in example.py

def my_function():
      return "Hello World"

if __name__ == "__main__":
      return my_function()

Of course if I run example.py it prints "Hello World".

What I want to do is to be able to overwrite my_function() in terms to return another stuff (Example "Hello ...") and be able to run example.py and print "Hello ..."

I need that because I want to deliver a library used by my users in which they can customize some code, like in the example. How can I do it ?

---EDIT--- The users will not touch the "main" in example.py.

in the example.py I call my_function() but I want to overwrite my_function() in the example.py in the user code.

4
  • Why not pass an argument to the function? Commented Apr 22, 2022 at 14:38
  • Like... having a parameter in my_function(thing_to_print): return thing_to_print ? Or are you thinking something more "exotic" like decorators maybe? Can you explain more about what are you wanting your users to do? Commented Apr 22, 2022 at 14:38
  • You probably want to collect the arguments. You can use argparse library for that. Commented Apr 22, 2022 at 14:38
  • Decorators do the work Commented Apr 22, 2022 at 14:39

2 Answers 2

3

When your users will import the module they will do:

import the_module

to use your function then they would do

the_module.my_function()

This is technically possible to do something like

import the_module

def replacement():
    print("something else")

the_module.my_function = replacement

But I don’t see any added value here between this and them just creating the function themselves.

Where it can come with value, it is in OOP, where then you will create a class with a set of given method, and one can inherit your class and override some methods, still keeping others.

class Animal:
    def say(self):
        print("something")
     
    def sleep(self):
        print("sleeping")

class Cat(Animal):
    def say(self):
        print("Miaou")
Sign up to request clarification or add additional context in comments.

2 Comments

I've updated the question but how can I say to my "example.py" to take this class and not the one in the "example.py" file. I think I need to touch the PythonPath...
oh no, you don’t need this. The import is made based on the path, so it is just you will import the second and not the first.
1

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"

2 Comments

the point is that is not the user to run my_function() is the "main". I've updated the question but how can I say to my "example.py" to take this class and not the one in the "example.py" file. I think I need to touch the PythonPath...
@squirrel as long as my_function and if __name__ == "__main__": return my_function() are in the same file, it's not possible. The nearest my_function definition will always be called

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.