L'intention était de mettre en œuvre une sorte de cadre de plug-in, où les plugins sont des sous-classes (c'est-à-dire B) de la même classe de base (c'est-à-dire). La classe de base est chargée d'importation standard, tandis que les sous-classes sont chargées avec imp.load_module () du trajet d'un emballage bien connu (c.-à-d. PKG).
# test_2.py
import pkg
from pkg import mod1
import imp
tup = imp.find_module('mod1', pkg.__path__)
mod0 = imp.load_module('mod1', tup[0], tup[1], tup[2])
print(issubclass(mod0.A, mod1.A)) # False
3 Réponses :
Ils ne sont pas em> la même classe. Ils ont été créés avec le même code, mais comme vous avez exécuté ce code deux fois (une fois dans l'importation et une fois dans load_module), vous obtenez deux objets de classe différents. Edit: puisque vous ne pouvez pas compter sur issubclass code> comparaisse l'identité des objets de classe et ils sont différents. issubclass code>, une alternative possible consiste à créer un Attribut unique sur la classe de base qui sera hérité par les classes dérivées. Cet attribut existe également sur des copies de la classe. Vous pouvez ensuite tester pour l'attribut. P> class A:
isA = True
class B(A):
pass
class C:
pass
def isA(aclass):
try:
return aclass.isA
except AttributeError:
return False
print isA(A)
True
print isA(B)
True
print isA(C)
False
"Doc, ça fait mal quand je fais ça!" "Ne fais pas ça."
@liuyu, je n'ai pas été en mesure de tester cela, mais vous pourrez peut-être vérifier si les classes sont égales par correspondance: issubclass (mod0.a, mod1.a) ou mod0.a == mod1.a code >
@MarkRansom (mod0.a == mod1.a) est évalué à FALSE. Et vous avez raison, ce sont des classes différentes résultant du même code exécuté deux fois, c'est-à-dire ID (MOD0.A) et ID (MOD1.A) diffèrent.
@liuyu, a ajouté une solution de contournement pour vous. Désolé je ne pouvais pas y arriver plus tôt.
J'ai un cas similaire. Dans File-A, je définis une classe de base, qu'une classe dans les sous-classes de fichier B. Dans File, a, j'utilise ensuite impossible_source code> pour charger la classe dans File-b. Votre réponse s'applique-t-elle, plus particulièrement "Ils ne sont pas la même classe" i>?
@Jeppe C'est ce que j'ai trouvé à travers un débogage. Si j'avais pris la classe partagée et que je l'ai déplacée dans un sous-répertoire des classes qui en avait besoin, je n'avais pas à utiliser load_module code> ou une variante, ce qui signifiait qu'il n'a été chargé qu'une fois sur le principal / sous Cours de répertoire. A définitivement appris une leçon intéressante ici.
#!/usr/bin/env python
import os
import sys
import pkg
from pkg import mod1
import imp
def smart_load_module(name, path):
# get full module path
full_path = os.path.abspath(os.path.join(path[0], name))
for module_name, module in sys.modules.items():
# skip empty modules and ones without actual file
if not module or not hasattr(module, '__file__'):
continue
# remove extension and normalize path
module_path = os.path.abspath(os.path.splitext(module.__file__)[0])
if full_path == module_path:
return module
# if not found, load standard way
tup = imp.find_module(name, path)
return imp.load_module(name, tup[0], tup[1], tup[2])
if __name__ == '__main__':
mod00 = smart_load_module('mod1', pkg.__path__)
print(issubclass(mod00.A, mod1.A)) # True
tup = imp.find_module('mod1', pkg.__path__)
mod0 = imp.load_module('mod1', tup[0], tup[1], tup[2])
print(issubclass(mod0.A, mod1.A)) # False
This works for me. I search class by full path in sys.modules and return loaded instance if any found.
Depuis que j'ai passé du temps avec ceci, je pensais partager ma solution:
import inspect
...
def inherits_from(child, parent_name):
if inspect.isclass(child):
if parent_name in [c.__name__ for c in inspect.getmro(child)[1:]]:
return True
return False
print inherits_from(possible_child_class, 'parent_class')
#True
Juste curieux, pourquoi tranchez-vous du nom de première classe? Cela ne semble pas nécessaire.
Pourquoi n'utilisez-vous pas simple
importer code> déclarations? Cela éviterait ce genre de problème.Veuillez afficher l'instruction
importer code> dansmod2 code> que les importationsmod1 code>. Il importe si cette instruction estimporter mod1 code> oude pkg importer mod1 code> ouà partir de. Importer mod1 code>.Vous avez importé le module contenant votre classe de base deux fois et tous les objets du module ont également été dupliqués. Essayez
imprimer mod0.a est mod1.a code> et voir si ce n'est pasfalse code>. Ou mêmemod0 est mod1 code>.@Sevenmarnach Je mettez en place un cadre de plug-in, où les noms des sous-classes ne sont disponibles que dans l'exécution et ne peuvent pas être codés en dur.
@liuyu: Il y a des cadres de plug-in Python. Si vous n'avez pas la connaissance intime du mécanisme d'importation Python, je suggère d'utiliser l'un de ces cadres plutôt que de rouler votre propre. Quoi qu'il en soit, le fait que les "noms des sous-classes ne soient disponibles que dans l'exécution" ne devraient pas vous empêcher de coder une déclaration d'importation, non?
@kindall tous les deux (mod0.a est mod1.a) et (mod0 est MOD1) dans Test_2 sont faux. Deux Instances i> du même module importées à partir de différents chemins sont considérés comme différents modules (au moins vrai pour Python 2.7 et Python 3.2). Sinon, il n'y aurait pas du tout le problème.