en Python 3 on peut utiliser super () code> au lieu de
super (myClass, auto) code>, mais cela ne fonctionne que dans des méthodes définies à l'intérieur de la classe. Comme décrit dans Article de Michele Simionato L'exemple suivant ne fonctionne pas:
__init__.__class_cell_thingy__ = C
3 Réponses :
Peut-être, mais par voudriez-vous? Dans les deux cas, vous devez être explicite de quelle classe c'est, car la manière implicite n'a pas fonctionné. Peut-être que vous pouvez définir la cellule explicitement en quelque sorte, mais il n'y a aucune raison de le faire. Il suffit de passer les paramètres explicitement.
def __init__(self): print('calling __init__') super(C, self).__init__() class C(object): __init__ = __init__ if __name__ == '__main__': c = C()
Merci d'avoir répondu, mais ce que vous suggérez ici est très faux. Vous ne pouvez pas utiliser auto .__ classe __ code> avec
Super code>, comme cela a été récemment exclaté ici: Stackoverflow.com/Questtions/4883822/...
@nikow: Eh bien, si vous allez sous-classer, vous pouvez avoir des problèmes, oui, si cette sous-classe utilise également Super (). Donc, vous voulez utiliser le même __ init __ code> pour de nombreuses classes différentes (car sinon, vous ne l'auriez pas définis en dehors de la classe) et que vous ne savez pas quelles classes, et que vous ne savez pas si Ou comment ces classes sont sous-classées? Dans ce cas, je dirais que vous résolvez le problème de problème. Puis-je suggérer un décorateur de classe ou une architecture de composants avec des adaptateurs?
@Lennart: La fonction ajoutée est définie ailleurs après des idées d'AOP, ce qui a assez bien fonctionné dans notre projet. Dans le code réel, ces "aspects" sont activés / désactivés au moment de l'exécution, il n'est donc pas vraiment une option de décorateur. J'espérais juste que l'on pourrait activer les appels simplifiés super () code>, après tout, ils ont été ajoutés à Python 3 pour une raison.
@nikow: Bien sûr, je comprends. C'est juste que Calling Super () des méthodes ajoutées dans votre cas semble être une mauvaise idée. D'où la suggestion d'utiliser des adaptateurs (qui répondent à la même fonction de faire définir le code ailleurs) ou des décorateurs. Depuis son exécution, les décrators sont hors de questions, mais les adaptateurs ne sont pas. Vous devriez vraiment regarder l'architecture des composants Zope, qui est orienté sur l'aspect, même si cela n'aime pas se vanter. :) Mais c'est probablement trop tard pour un projet en cours, mais vous pourriez avoir des idées.
Nono, c'est un autre impôt pour "Vous n'êtes pas censé faire cela" théorie du codage. Faire ce qui fonctionne. :)
@Lennart: J'ai examiné des cadres et des mécanismes d'extension AOP avant la mise en œuvre initiale. Bien sûr comprendre zope n'est pas exactement une tâche rapide et facile :-) Ma première mise en œuvre a réellement utilisé des adaptateurs, mais globalement plus compliqué que notre solution actuelle.
@nikow: pas zope. L'architecture du composant Zope. C'est juste une petite partie de Zope. :) Muthukadan.net/docs/zca.html
Vous devriez jamais b> utiliser auto .__ classe __ code> à
super () code>, car maintenant si vous sousclasses
c code> vous obtenez une infinie boucle. Soit passer dans l'objet de classe explicite, ou i> fournir une fermeture pour
__ classe __ code>;
auto .__ classe __ code> est la mauvaise référence.
Vous pouvez utiliser le dictionnaire de la fonction.
def f(self): super(f.owner_cls, self).f() print("B") def add_to_class(cls, member, name=None): if hasattr(member, 'owner_cls'): raise ValueError("%r already added to class %r" % (member, member.owner_cls)) member.owner_cls = cls if name is None: name = member.__name__ setattr(cls, name, member) class A: def f(self): print("A") class B(A): pass add_to_class(B, f) B().f()
Cela fonctionnerait, mais je ne suis pas sûr que je préférerais cela la solution explicite avec la classe d'écriture. Après tout, je savoir i> Quelle classe la méthode appartiendra, je veux juste bénéficier du plus pratique Python 3 Super () code>.
Si vous faites quelque chose comme celui-ci en premier lieu, vous voulez probablement pouvoir attribuer la fonction à plusieurs catégories.
@Glenn: Oui, tu as raison. Bien que ce n'était pas mon cas d'utilisation principale, je me suis souvenu qu'il y avait des cas où cela serait un problème.
Sérieusement: vous ne voulez vraiment pas faire cela.
Mais, il est utile que les utilisateurs avancés de Python de comprendre cela, donc je vais l'expliquer. p>
cellules et féculents sont le Valeurs attribuées lorsqu'une fermeture est créée. Par exemple, p> ("cellules" et "freevars" sont très similaires. Frears a des noms, où les cellules ont des index. Ils sont tous deux stockés dans Une fois que vous Comprenez cela, vous pouvez voir comment super () fonctionne réellement. Toute fonction contenant un appel à f code> renvoie une fermeture basée sur
Func code>, stockant une référence à
A code>. Cette référence est stockée dans une cellule (en fait dans un freevar, mais que l'on est à la mise en œuvre). Vous pouvez examiner ceci: p>
FUNC .__ Fermeture __ Code>, avec des cellules arrivant en premier. Nous nous soucions que de
Freevars code> ici, car c'est ce que
__ classe __ p>
Super code> est en fait une fermeture, avec un fichier FreeVar nommé
__ classe __ code> (qui est également ajouté si vous vous référez à
__ class __ code> ): P>
import types
class B(object):
def __init__(self):
print("base")
class C(B):
def dummy(self): __class__
def __init__(self):
print('calling __init__')
super().__init__()
def MakeCodeObjectWithClass(c):
"""
Return a copy of the code object c, with __class__ added to the end
of co_freevars.
"""
return types.CodeType(c.co_argcount, c.co_kwonlyargcount, c.co_nlocals,
c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names,
c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno,
c.co_lnotab, c.co_freevars + ('__class__',), c.co_cellvars)
new_code = MakeCodeObjectWithClass(__init__.__code__)
old_closure = __init__.__closure__ or ()
C.__init__ = types.FunctionType(new_code, globals(), __init__.__name__,
__init__.__defaults__, old_closure + (C.dummy.__closure__[0],))
if __name__ == '__main__':
c = C()
Merci, excellente réponse. C'est bien de savoir comment ces choses fonctionnent. Je pense que je vais prendre votre conseil et coller à l'explicite Super code> appels pour le moment. Jusqu'à ce que Python 3 devienne prédominant, c'est quelque peu universitaire de toute façon.
P.s. Semble que cette réponse poussée poussée vous a poussé à 10k Rep :-)
Une autre astuce consiste à définir une fonction à l'intérieur d'une autre fonction avec un seul argument __ classe __ code>, puis renvoyez la fonction interne (ou juste sa fermeture). Ensuite, vous n'auriez pas besoin de la méthode factice pour créer la fermeture, ou vous pourriez également définir la méthode réelle en tant que cette fonction intérieure. Une autre chose est que vous puissiez utiliser un conteneur de classe (probablement avec une métaclasse auxiliaire avec des méthodes qui cachent la magie) pour stocker les fonctions, vous ne seriez pas à créer des objets de code personnalisés avec cet appel horaire.
"Est-il possible de définir cette cellule manuellement"? Quand tu as essayé ça, que s'est-il passé?
Mais comment puis-je avoir accès à cette cellule après avoir défini la fonction?
__ init __.__ classe __ code> est bien sûr autre chose. J'ai maintenant édité la question pour clarifier cela.
Pourquoi voulez-vous définir la fonction en dehors de la classe? Vous voudriez cela si vous souhaitez réutiliser une fonction ou utiliser une fonction comme méthode plusieurs fois. Vous ne pouvez pas faire ces choses et utiliser
super (...) code> correctement. Et si vous modifiez une classe au moment de l'exécution, vous pouvez simplement le calculer.
@RUSH: Évidemment, les cas d'utilisation pour cela sont un peu compliqués. Dans mon cas, il est lié à la programmation orientée forme. La fonction n'est ajoutée qu'à une classe, donc je pouvais le creuser (mais ce n'est pas ma question). Si vous pensez que ce que je demande est impossible, veuillez expliquer pourquoi, et je serai heureux d'accepter votre réponse.
@nikow: Si vous aimez la programmation orientée de l'aspect, jetez un coup d'œil à l'architecture du composant Zope, c'est-à-dire.
Si vous voulez faire un AOP, pourquoi ne pas utiliser de décorateurs?
@Lennart: Merci pour la référence. Je pense que l'AOP est utilisé dans des projets de python assez nombreux. Malheureusement, je n'ai rien trouvé directement lié à ma question.
@ S.Lott: Dans le code actuel, j'utilise des décorateurs de fonction. Mais cela ne m'aide pas avec les appels
super code> à l'intérieur de la fonction ou?
@nikow: Eh bien, il semble une meilleure idée d'appeler super () à l'intérieur du propre
__ init __ code>, puis peut-être peut-être envelopper cet init avec un décorateur.
@nikow: plutôt que d'un AOP hypothétique comme celui-ci, il est probablement préférable d'ouvrir une nouvelle question avec l'aspect spécifique qui semble faire partie de
__ init __ code>. Souvent, cela ne fait pas partie de
__ init __ code>. Il est plus facile de travailler avec des cas d'utilisation spécifiques et tangibles.
@ S.Lott: Peu importe que j'ai utilisé la méthode
__ init __ code> dans mon exemple (que j'ai pris à partir de l'article référencé). Il me semble que ma question était assez spécifique et j'ai eu une excellente réponse. Donc, je ne comprends pas vraiment pourquoi je devais tellement défendre cette question.
@nikow: "Je ne comprends pas vraiment pourquoi je devais tellement défendre cette question". Réfléchissons. Choix 1: Nous vous haïssons tous. Choix 2: La question pourrait être une amélioration. Choix 3: Nous sommes tous des idiots totaux. Choisir un.
@ S.LOTT: Vous êtes invité à modifier la question ou à faire des suggestions sur la manière de l'améliorer. Malheureusement, je ne comprends toujours pas votre commentaire précédent sur le
__ init __ init __ indien pertinent, donc je n'ai donc pas pu le considérer.
@nikow: «Je ne comprends toujours pas votre commentaire précédent sur le init b correspondant B>" Je m'excuse. C'était une demande pour une nouvelle question avec un étui concret, spécifique, tangible et détaillé pour la raison pour laquelle vous voudrez même faire cela.
@ S.Lott: Ah, je vois. Mon cas d'utilisation est un peu complexe, car il ne s'agirait que d'un peu de fonctionnalités pour un mécanisme d'extension de style AOP déjà existant dans un projet plus vaste. Je voulais juste déterminer s'il serait possible d'ajouter une prise en charge automatique pour
Super () code> une fois que la transition de Python 3 est terminée. En raison de la nature et de la complexité de la solution suggérée, je ne pense pas que cela en vaut la peine.