70 votes

Comment contourner la définition de fonction python avec le décorateur ?

J'aimerais savoir s'il est possible de contrôler la définition de la fonction Python en fonction des paramètres globaux (par exemple, le système d'exploitation). Exemple:

 @linux
def my_callback(*args, **kwargs):
    print("Doing something @ Linux")
    return

@windows
def my_callback(*args, **kwargs):
    print("Doing something @ Windows")
    return

Ensuite, si quelqu'un utilise Linux, la première définition de my_callback sera utilisée et la seconde sera ignorée en silence.

Il ne s'agit pas de déterminer le système d'exploitation, mais de définir les fonctions / décorateurs.

42voto

MisterMiyagi Points 2734

Alors que la @decorator semble agréable, vous obtenez exactement le même comportement que souhaité avec un simple if .

 linux = platform.system() == "Linux"
windows = platform.system() == "Windows"
macos = platform.system() == "Darwin"

if linux:
    def my_callback(*args, **kwargs):
        print("Doing something @ Linux")
        return

if windows:
    def my_callback(*args, **kwargs):
        print("Doing something @ Windows")
        return

Si nécessaire, cela permet également de vérifier facilement que certains cas correspondent.

 if linux:
    def my_callback(*args, **kwargs):
        print("Doing something @ Linux")
        return

elif windows:
    def my_callback(*args, **kwargs):
        print("Doing something @ Windows")
        return

else:
     raise NotImplementedError("This platform is not supported")

5voto

Junyeong Jeong Points 51

J'ai écrit mon code avant de lire d'autres réponses. Après avoir terminé mon code, j'ai trouvé que le code de @Todd est la meilleure réponse. Quoi qu'il en soit, je poste ma réponse parce que je me sentais amusant pendant que je résolvais ce problème. J'ai appris de nouvelles choses grâce à cette bonne question. L'inconvénient de mon code est qu'il existe une surcharge pour récupérer les dictionnaires à chaque fois que des fonctions sont appelées.

 from collections import defaultdict
import inspect
import os


class PlatformFunction(object):
    mod_funcs = defaultdict(dict)

    @classmethod
    def get_function(cls, mod, func_name):
        return cls.mod_funcs[mod][func_name]

    @classmethod
    def set_function(cls, mod, func_name, func):
        cls.mod_funcs[mod][func_name] = func


def linux(func):
    frame_info = inspect.stack()[1]
    mod = inspect.getmodule(frame_info.frame)
    if os.environ['OS'] == 'linux':
        PlatformFunction.set_function(mod, func.__name__, func)

    def call(*args, **kwargs):
        return PlatformFunction.get_function(mod, func.__name__)(*args,
                                                                 **kwargs)

    return call


def windows(func):
    frame_info = inspect.stack()[1]
    mod = inspect.getmodule(frame_info.frame)
    if os.environ['OS'] == 'windows':
        PlatformFunction.set_function(mod, func.__name__, func)

    def call(*args, **kwargs):
        return PlatformFunction.get_function(mod, func.__name__)(*args,
                                                                 **kwargs)

    return call


@linux
def myfunc(a, b):
    print('linux', a, b)


@windows
def myfunc(a, b):
    print('windows', a, b)


if __name__ == '__main__':
    myfunc(1, 2)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X