pourquoi une fonction vide est nécessaire


9

J'ai commencé à apprendre le python et je me demande pourquoi une fonction vide est nécessaire dans un langage de programmation

par exemple en python:

def empty_func():
    pass

même dans les scripts shell, des fonctions vides sont disponibles.

Mes compréhensions et ma question:

  1. Pourquoi le langage de programmation avait-il besoin de fonctions vides? Est-ce juste pour jouer avec le langage de programmation ou rien d'autre qui compte vraiment?

  2. Si cela a un but, quelqu'un peut-il décrire le cas d'utilisation ou donner un exemple réel de l'utilisation de fonctions vides?

  3. Ou existe-t-il une tradition de langages de programmation permettant des fonctions vides?


EDIT (Ce que j'ai appris en lisant vos réponses):

  • Pour esquisser des algorithmes ou avec des fonctions abstraites
  • Pour soumettre des formulaires sans aucune action doit être effectuée
  • Espace réservé pour certaines opérations obligatoires

1
ils peuvent être utilisés comme STUBS si l'exécution du programme s'attend à les trouver / les utiliser, mais vous ne voulez rien changer à travers eux.
G.Rassovsky du

Réponses:


5

Dans les langages shell de la famille Bourne, la :commande, qui ne fait rien du tout, est généralement utilisée dans deux situations:

  • Espace réservé pour quand quelque chose attend une commande obligatoire, par exemple

    while some_condtion
    do :
    done

    car donécessite au moins une commande.

  • Ignorer les arguments, mais effectuer des effets secondaires dans la liste des arguments, par exemple

    : ${myvar=foo}

Je suis sûr qu'il existe probablement d'autres applications que les experts du shell sauraient :)

En Python (et dans d'autres langages), il est utilisé moins fréquemment. Il peut servir d'argument à une fonction d'ordre supérieur lorsque vous ne voulez rien faire. Par exemple, supposons que vous ayez une fonction qui soumet un formulaire et permette à une fonction d'être appelée de manière asynchrone une fois la soumission terminée:

def submit(callback=empty_func):
    ...

De cette façon, si le callbackn'est pas fourni, la soumission continuera tout de même mais aucune autre action ne sera effectuée. Si vous aviez utilisé Nonecomme valeur par défaut, vous devriez vérifier explicitement si le rappel était None, en ajoutant de l'encombrement au code.


1

Cela dépend de votre position dans le cycle de développement, mais parfois lorsque vous esquissez un algorithme, vous souhaitez effectuer une abstraction sur des blocs complexes sans les implémenter immédiatement.

def full_algo():
  init_stuff()
  process_stuff()
  ...

Vous savez comment ça init_stuffva marcher, c'est assez simple dans votre tête mais vous n'en avez pas vraiment besoin tout de suite, donc vous le déclarez comme une fonction vide. Il permettra à votre code de se compiler et de s'exécuter sans se soucier des détails sanglants.

Une autre utilisation des applications publiées consiste à utiliser l'héritage. Supposons que vous ayez une grande classe qui définit le comportement du code spécifique à la plate-forme. Vous pourriez vous retrouver avec une logique similaire à celle-ci:

init_filesystem();
access_files();
release_filesystem();

Ce code fonctionnera sur de nombreuses plates-formes, mais certaines plates-formes peuvent ne pas nécessiter l'initialisation du système de fichiers. Ensuite, votre héritage ressemblera à ceci (virtuel avec = 0 en C ++ signifie simplement que les classes dérivées DOIVENT implémenter ces méthodes):

class FileSystem{
  virtual void init_filesystem() = 0;
  virtual void access_files() = 0;
  virtual void release_filesystem() = 0;
};

Une implémentation particulière de cette classe (interface) pourrait alors ne rien faire pour certaines de ces méthodes. Alternativement, la classe de base pourrait déclarer des méthodes vides pour init / release au lieu de les déclarer virtuelles.

Enfin (et honteusement), vous maintenez parfois une application très ancienne. Vous craignez que la suppression de méthodes ne casse les choses. Cela se produit lorsque vous avez un héritage complexe qui n'est pas correctement compris ou lorsque vous avez beaucoup de pointeurs de fonction (rappels). Vous supprimez simplement le code à l'intérieur d'eux afin qu'ils soient appelés de toute façon sans rien casser.


0

Rufflewind a fait un bon travail en couvrant quand vous pourriez utiliser une fonction vide dans un programme terminé. D'après mon expérience, il a tendance à être utilisé plus souvent dans les programmes inachevés, vous pouvez donc planifier ce que vous allez écrire et le compiler jusqu'à ce que vous arriviez à le mettre en œuvre. En d'autres termes, il s'agit généralement d'un espace réservé.

C'est nécessaire dans le cas de python car il utilise l'indentation pour marquer les blocs, contrairement aux langages de type C qui utilisent des accolades {}. Cela signifie que si vous n'en aviez pas pass, l'analyseur ne pouvait pas dire si vous vouliez le laisser vide ou si vous avez oublié. Inclure passrend l'analyseur beaucoup plus simple et vous donne un mot pratique à rechercher lorsque vous recherchez des blocs non implémentés.


1
Pour le code inachevé, lancer NotImplementedErrorest une solution plus adéquate car "les erreurs ne doivent jamais passer silencieusement" et appeler une fonction non implémentée dans un programme en direct est une erreur.
ivan_pozdeev

Ça dépend. Pour le code que vous expédiez, oui. Mais si c'est du code que vous prévoyez d'implémenter dans une heure et que vous le laissez simplement non implémenté pendant que vous travaillez sur les tests unitaires, le simple fait de ne laisser aucune implémentation peut être une meilleure option. Souvent, mon flux de travail est 1) écrivez la méthode du talon avec pass 2) écrivez le test unitaire qui teste la valeur de retour 3) vérifiez que le test échoue (car la méthode retourne indéfinie) 4) implémentez la méthode 5) vérifiez que le test passe maintenant
Gort the Robot

0

Bien que ce ne soit pas quelque chose que vous attendez de Python, il y a des moments dans le monde des pilotes de périphériques où vous devez fournir une fonction vide, pour gérer un événement que vous (a) savez ne se produira pas ou ( b) s'en fout même si c'est le cas.

Vous voyez également cela en C avec des rappels. Parfois, vous verrez du code qui suppose simplement que vous avez fourni un rappel et essaie de l'appeler, ignorant le risque d'un pointeur nul. Dans ce cas, tout ce que vous pouvez faire est de fournir une routine de rappel vide. (Oui, je pense à un fournisseur particulier.)


J'ai passbeaucoup utilisé comme espace réservé lors de l'écriture de code, en particulier dans les classes, lorsque je veux quelque chose d'exécutable avant que tout ne soit terminé. C'est vraiment l'équivalent de {}python, ce que python ne peut pas faire car il n'utilise pas d'accolades. En ce sens, toutes les langues que je connais le permettent, c'est juste que seuls quelques-uns comme pythonnécessitent un mot-clé. Même à l'époque de l'assemblée que nous avions NOP.
Gort the Robot

@StevenBurnap, généralement quand je fais quelque chose comme ça, j'inclus l'équivalent local de printf (">>> routine XXX appelée \ n");
John R. Strohm
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.