9
votes

Quels sont les avantages et les inconvénients des méthodes requises contre l'importation de code de chargement?

Ruby utilise Exiger , Python utilise importer . Ce sont des modèles sensiblement différents, et pendant que je suis plus habitué au modèle exiger , je peux voir quelques endroits où je pense que j'aime importer plus. Je suis curieux de savoir ce que les gens trouvent particulièrement faciles - ou plus intéressant, plus difficiles qu'ils ne devraient être - avec chacun de ces modèles.

En particulier, si vous écrivez un nouveau langage de programmation, comment concevriez-vous un mécanisme de chargement de code? Quels "avantages" et "contre" pèseraient le plus lourdement sur votre choix de conception?


5 commentaires

Pourquoi cela devrait-il être un wiki communautaire? C'est une question claire et responsable!


Parce que je pose une question pour laquelle les réponses peuvent être subjectives. Il existe une possibilité définitive que les gens d'avoir une préférence personnelle pour l'une ou l'autre méthode. Je suis intéressé par des préférences subjectives s'il y a une raison légitime derrière eux au-delà de "je préfère celui-ci."


J'aimerais connaître le contexte de la question, allez-vous choisir une langue sur l'autre sur la base de l'importation vs besoin?


Non, le contexte de cette question est la conception de la langue: je travaille sur une langue de programmation expérimentale (écrite dans OCAML) pour le plaisir. J'utilise régulièrement Python et Ruby à ce stade, bien que je suis assez nouveau à Python.


Être votre drapeau de modérateur; ne peut faire. Si vous vouliez accepter la réponse «KAIZER.SE», vous auriez dû le faire. Notez également que Auto-Accepter ne donne que demi-points.


4 Réponses :


17
votes

Le python Import a une fonctionnalité majeure en ce qu'elle lie deux choses ensemble - comment trouver l'importation et sous quel espace de noms l'inclure .

Ceci crée un code très explicite:

Importer xml.sax

Ceci spécifie où trouver le code que nous voulons utiliser, par Les règles du chemin de recherche Python.

En même temps, tous les objets que nous souhaitons accéder à Live sous cet espace de noms exact, par exemple xml.sax.contenthandler .

Je considère cela comme un avantage à l'exigence de Ruby. nécessite 'xml' pourrait en fait rendre des objets dans l'espace de noms xml ou tout autre espace de nom disponible dans le module, sans que cela soit directement évident de la ligne requise.

si xml.sax.contenthandler est trop long, vous pouvez spécifier un nom différent lors de l'importation: xxx

et il est maintenant disponible sous x.conthandler .

De cette façon, Python vous oblige à construire explicitement l'espace de noms de chaque module. Les espaces de noms Python sont donc très «physiques», et je vais expliquer ce que je veux dire:

  • Par défaut, seuls les noms directement définis dans le module sont disponibles dans son espace de noms: fonctions, classes et ainsi.
  • Pour ajouter à un espace de noms d'un module, vous importez explicitement les noms que vous souhaitez ajouter, les placer (par référence) "physiquement" dans le module actuel.

    Par exemple, si nous avons le petit package Python "processus" avec des sous-modules internes machine et interface , et nous souhaitons présenter ceci comme un poste pratique Espace de noms directement sous le nom du package, c'est ainsi que l'exemple de ce que nous pouvions écrire dans le fichier "de définition de package" processus / __ init __. py : xxx

    Ainsi, nous soulevons ce qui serait normalement accessible comme processus.machine.machine jusqu'à processus.machine . Et nous ajoutons tous les noms de process.interface à processus Espace de noms, de manière très explicite.

    Les avantages de l'importation de Python que j'ai écrit Simplement deux:

    • clair ce que vous incluez lorsque vous utilisez importer
    • explicite comment vous modifiez l'espace de noms de votre propre module (pour le programme ou pour d'autres personnes à importer)

6 commentaires

Je conviens que c'est une fonctionnalité bonne et utile, mais j'ai constaté qu'il y avait une courbe d'apprentissage plus raide avec des choses comme __ init __. Py et si vous n'avez pas eu de structure de répertoire flexible pour une raison quelconque, cette fait des noms de noms exactement comme vous voulez un peu difficile.


Je me demande pour quelle raison vous n'auriez pas une "structure de répertoire flexible"?


@Bob: Bien sûr, c'est l'inconvénient. La façon dont je le vois, vous négociez une courbe d'apprentissage plus raide pour l'avantage @ kaizer.se mentionné. Si vous me demandez, ça vaut le coup.


@Luper: Voir le commentaire ci-dessous concernant les plugins; Je devais être beaucoup plus délibérément délibéré de nommer des choses que je n'attendais avec Python. Avec Ruby, j'aurais pu choisir les noms de fichiers que je voulais avec un effet pratiquement zéro sur l'API publique.


@Bob: et choisir des chemins et des noms de fichiers arbitraires et déroutants avec zéro connexion à des noms vus du niveau de langue est une excellente caractéristique car ... ??? Je ne comprends tout simplement pas. Après des années de travail avec C ++ et son # Inclure / Espace de noms / Modèle d'unité de compilation Je trouve Python Way ... Je ne sais pas ... sympa ... sympathique ... libérer ...


@tomekszpakowicz: Ouais, les sentiers ne sont pas arbitraires ou déroutants, c'est juste que le projet est techniquement toujours confidentiel, alors j'ai légèrement muni les chemins.



1
votes

Disclaimer, Je ne suis en aucun cas un expert en Python. em>

Le plus grand avantage que je vois à nécessite code> sur import code> est simplement que Vous n'avez pas à vous soucier de comprendre le mappage entre les espaces de noms et les chemins de fichiers. C'est évident: c'est juste un chemin de fichier standard. P>

J'aime vraiment l'accent mis sur la liste de noms que Import code> a, mais ne peut s'empêcher de me demander si cette approche particulière n'est pas trop inflexible. Autant que je puisse dire, le seul moyen de contrôler la nommage d'un module en Python consiste à modifier le nom de fichier du module importé ou en utilisant un comme code> renommer. En outre, avec des noms de noms explicites, vous avez un moyen par lequel vous pouvez vous référer à quelque chose par son identifiant parfaitement qualifié, mais avec un nom de noms implicite, vous n'avez aucun moyen de le faire à l'intérieur du module lui-même, ce qui peut conduire à des ambiguïtés potentielles qui sont Difficile à résoudre sans renommer. p>

IE, dans foo.py code>: p> xxx pré>

Ceci échoue avec: P>

Traceback (most recent call last):
  File "", line 1, in ?
  File "foo.py", line 3, in myself
    return foo.Bar
NameError: global name 'foo' is not defined


6 commentaires

En fait, vous pouvez revenir 'foo.bar', si vous «importez-vous FOO» juste au-dessus de la méthode «moi-même». Mais pourquoi voudriez-vous faire cela quand vous pourrez simplement retourner «bar»?


Dans cet exemple, évidemment, oui, la barre de retour est exactement ce que vous voudriez faire. Cependant, j'ai une situation dans certains codes, j'écris actuellement où sont des plugins écrites par d'autres auteurs. Je dois être particulièrement prudent des espaces de noms ambigus. Heureusement, je viens de découvrir de __future__ importer absolute_import , et cela atténue presque complètement ce problème.


Pourquoi ne pas mettre vos plugins dans un répertoire le long de votre application, comme 'plugins', chacun avec son propre sous-répertoire? De cette façon, il ne peut y avoir aucun conflit entre les plugins, vous pouvez importer sans faire de la magie noire et trouver des implémentations avec sous-classes . Si les auteurs de plug-in font des importations contradictoires telles que "Strings d'importation", ce n'est pas votre problème, ou si c'est ce n'est plus vraiment plugins;)


C'est exactement ce que je fais réellement. Le problème est que j'ai un module nommé myProject.conents et les plugins sont nommés composants.MyComponent . Toute tentative d'autres modules dans le module MyProject à charger composants.MYComponent échoue, car ils recherchent le mauvais module pour myComponent . de __future__ importer absolute_import corrige cela.


Oh je vois, les importations relatives de style anciennes sont diaboliques (j'ai arrêté de les utiliser il y a longtemps), je suis content qu'ils l'enlèvent à Python 2.7.


Exactement! Ce que j'ai essayé d'expliquer ... malgré mal.



3
votes

Une belle propriété de nécessite est-ce qu'il est en fait une méthode définie dans noyau . Ainsi, vous pouvez le remplacer et mettre en œuvre votre propre système d'emballage pour RUBY, ce que par exemple. Les rubygems font!

PS: Je ne vends pas de singe patching ici, mais le fait que le système de paquet de Ruby puisse être réécrit par l'utilisateur (même pour fonctionner comme le système de Python). Lorsque vous écrivez un nouveau langage de programmation, vous ne pouvez pas tout comprendre. Ainsi, si votre mécanisme d'importation est totalement extensible (dans totalement toutes les directions) de la langue, vous effectuez vos futurs utilisateurs le meilleur service. Une langue qui n'est pas entièrement extensible de l'intérieur en elle-même est une impasse évolutive. Je dirais que c'est l'une des choses que Matz a eu raison avec Ruby.


6 commentaires

Je ne vais pas aller à -1 cela, mais le singe-patching tel qu'il existe dans Ruby est problématique, et pas quelque chose que je veux encourager. Un bon système d'emballage modifierait simplement le chemin de recherche et laisserait le code de chargement du code seul.


Eh bien ... je suis assez sûr que vous ne pouvez pas imiter le système d'importation de Python à Ruby. Vous pourriez avoir quelque chose de vaguement similaire, mais ce serait un piratage total, il serait probablement de briser toutes sortes de code, et vous feriez pisser beaucoup de personnes si vous l'utilisiez dans un environnement de production.


-1 Pour prétendre ne pas vendre de patchs de singe pendant que ... Vendre des patchs de singe. Aussi, pour une inclusion totale sur le mécanisme d'importation de Python (et la volonté de le dur de toute façon). Première réponse que j'ai jamais vue pour que je puisse évoquer plus d'une fois si je pouvais.


Ugh, cela n'aurait pas dû être la réponse acceptée, et parce que c'est une prime, je ne peux pas le changer. Alors est sorti et a choisi la meilleure réponse écrite après que la généraliste ait été démarrée au lieu de la réponse la plus élue, il semble.


Vous avez déjà pensé alors :) Vous demandez au mieux Jeff ou l'un des modérateurs de site de le réparer.


Yay! Ils ont finalement cessé de verrouiller des réponses prenantes comme acceptées.



1
votes

L'importation de Python fournit un type d'espace de noms très explicite: l'espace de noms est le chemin, vous n'avez pas à examiner les fichiers pour connaître quel espace de noms ils effectuent leurs définitions et que votre fichier n'est pas encombré de définitions d'espace de noms. Cela rend le schéma d'espace de noms d'une application simple et rapide à comprendre (il suffit de regarder l'arborescence source) et d'éviter des erreurs simples telles que Misping, une déclaration d'espace de noms.

Un bel effet secondaire est que chaque fichier a son propre espace de nom privé. Vous n'avez donc pas à vous soucier des conflits lorsque vous nommez des choses.

Parfois, des espaces de noms peuvent aussi devenir ennuyeux, ayant des choses comme quelque.module.far.far.away.theclass () partout peut rapidement rendre votre code très long et ennuyeux. Dans ces cas, vous pouvez Import ... de ... et injecter des bits d'un autre espace de noms dans l'actuel. Si l'injection provoque un conflit avec le module que vous importeriez, vous pouvez simplement renommer la chose que vous avez importée: à partir de certains.auther.Module d'importation comme barfromothermodule . .

Python est toujours vulnérable aux problèmes tels que les importations circulaires, mais c'est la conception de l'application plus que la langue qui doit être blâmée dans ces cas.

SO Python a pris C ++ Nomspace et #include et largement étendu dessus. D'autre part, je ne vois pas de quelle manière le module de Ruby et nécessite ajouter quelque chose de nouveau à celles-ci et que vous avez exactement les mêmes problèmes horribles tels que l'encombrement des espaces de noms globaux. < / p>


2 commentaires

L'exigence de Ruby est entièrement extensible de la langue. Si vous n'aimez pas sa sémantique d'importation, vous pouvez aller les changer! Cela ne peut être fait en C ++ ou Python, donc au moins à ce respect Ruby ajoute une grande nouvelle à la manière dont les œuvres d'importation.


Vous pouvez personnaliser exactement le mécanisme d'importation Python comme dans Ruby. Mais dans les deux cas, cela ressemble à une idée terriblement mauvaise. Que se passe-t-il lorsque deux modules tiers personnalisent le mécanisme d'importation? Ce genre de choses doit être standard et le mécanisme standard de Ruby ne suffit pas pour moi.