Search code examples
pythonpython-3.xevalredo

Why does eval() not find the function?


def __remove_client(self, parameters):
        try:
            client = self.__client_service.remove_client_by_id(int(parameters[0]))

            FunctionsManager.add_undo_operation([self.__client_service, self.__rental_service],
                                                UndoHandler.delete_client_entry, [client[0], client[1]])
            FunctionsManager.add_redo_operation(eval('self.__add_new_client(client[0].id,client[0].name)'))

And this gives me : 'UI' object has no attribute '__add_new_client' What should I do? Or is there another way of adding that function to my repo() stack without calling the function while I am at it?


Solution

  • According to the docs on Private methods:

    Notice that code passed to exec() or eval() does not consider the classname of the invoking class to be the current class; this is similar to the effect of the global statement, the effect of which is likewise restricted to code that is byte-compiled together. The same restriction applies to getattr(), setattr() and delattr(), as well as when referencing __dict__ directly.

    As for why your eval() is pointless, this:

    eval('self.__add_new_client(client[0].id,client[0].name)')
    

    is exacty equivalent to if you just ran the code:

    self.__add_new_client(client[0].id,client[0].name)
    

    directly. It seems like maybe you were hoping for some kind of delayed lazy evaluation or something but that's not how it works. Perhaps you wanted to pass a partial evaluation of that method such as:

    from functools import partial
    FunctionsManager.add_redo_operation(partial(self.__add_new_client, client[0].id, client[0].name))
    

    If this is your own code, you shouldn't actually use the __ methods unless you know exactly what you're doing. There is generally no good reason to use this (Guido has even I think regretted the feature in the past). It's mostly just useful in the special case described in the docs, where you might intend a subclass to override a special method, and you want to keep a "private" copy of that method that cannot be overridden.

    Otherwise just use the single _ convention for internal attributes and methods.