3 Réponses :
Eh bien, le type Il arrive que l'appelant code> imprimer cod> puis appelez Oui, il est seulement initialement invoqué, puis les mains contrôlent à Les classes dérivées n'utilisent pas (autant que je puisse dire) Nope, si aucun Quant à la question code> est bien sûr
mymetaclass code>.
METACLASS_CALLABLE CODE> est initialement "sélectionné" comme métaclass depuis Il a été spécifié dans la métaclass code> kwarg et comme tel, c'est
__ appel __ code> (un appel de fonction simple) va être effectué. p>
mymetaclass .__ appel __ code> (quel type
__ code> depuis
__ call code> n'a pas été remplacé par
mymetaclass code>). là em> l'affectation de
CLS .__ classe __ code> est faite
à myMetaclass code>. p>
métaclass_callable code> est appelé une fois, puis semble être irrécupérable p>
blockQuote>
mymetaclass code>. Je ne suis au courant d'aucun attribut de classe qui conserve cette information. p>
métaclass_callable code> de quelque manière que ce soit. p>
blockQuote>
métaclass code> est explicitement défini, La meilleure correspondance des métaclasses de
bases code>
(ICI myClass code>) sera utilisé (résultant dans
mymetaclass code>). p>
2 code>, tout ce que vous pouvez faire avec une appelable est également possible en utilisant une instance de type avec
__ appel __ code> remplacé en conséquence. Quant à pourquoi em>, vous ne voudrez peut-être pas aller à la pleine création de classe soufflée si vous souhaitez simplement apporter des modifications mineures lors de la création d'une classe. P>
Des deux choix que j'ai donnés, quelle est votre réponse à la questionner une? Quant à votre réponse à la question 2, pouvez-vous donner un exemple dans lequel l'utilisation d'une appelable est en quelque sorte "moins pleine soufflée" que de dériver de type code>?
En ce qui concerne votre première question, la métaclasse doit être MyMetaclass Code> (ce que c'est ainsi):
# Provide a PEP 3115 compliant mechanism for class creation
def new_class(name, bases=(), kwds=None, exec_body=None):
"""Create a class object dynamically using the appropriate metaclass."""
meta, ns, kwds = prepare_class(name, bases, kwds)
if exec_body is not None:
exec_body(ns)
return meta(name, bases, ns, **kwds)
def prepare_class(name, bases=(), kwds=None):
"""Call the __prepare__ method of the appropriate metaclass.
Returns (metaclass, namespace, kwds) as a 3-tuple
*metaclass* is the appropriate metaclass
*namespace* is the prepared class namespace
*kwds* is an updated copy of the passed in kwds argument with any
'metaclass' entry removed. If no kwds argument is passed in, this will
be an empty dict.
"""
if kwds is None:
kwds = {}
else:
kwds = dict(kwds) # Don't alter the provided mapping
if 'metaclass' in kwds:
meta = kwds.pop('metaclass')
else:
if bases:
meta = type(bases[0])
else:
meta = type
if isinstance(meta, type):
# when meta is a type, we first determine the most-derived metaclass
# instead of invoking the initial candidate directly
meta = _calculate_meta(meta, bases)
if hasattr(meta, '__prepare__'):
ns = meta.__prepare__(name, bases, **kwds)
else:
ns = {}
return meta, ns, kwds
def _calculate_meta(meta, bases):
"""Calculate the most derived metaclass."""
winner = meta
for base in bases:
base_meta = type(base)
if issubclass(winner, base_meta):
continue
if issubclass(base_meta, winner):
winner = base_meta
continue
# else:
raise TypeError("metaclass conflict: "
"the metaclass of a derived class "
"must be a (non-strict) subclass "
"of the metaclasses of all its bases")
return winner
Pour la question 2, je ne comprends pas comment vous répondez à ma question: "Y a-t-il quelque chose que vous puissiez faire avec un appelable que vous ne pouvez pas faire avec une instance de type type code>? Quel est le but d'accepter une appelable arbitraire? "
@Neilg Comme je l'ai mis à jour, il n'y a pas de but particulier, c'est juste la nature des Maclasses.
Cela semble suggérer que vous pouvez contourner _calculate_meta code>, mais je n'ai pas pu faire cela.
@Neilg Yase c'est pour Python 3. Si vous contournez que vous n'obtiendrez pas de méta appropriée car il est dit dans Doc.
Je veux dire, je n'ai pas pu le contourner en spécifiant une métaclasse sans type. (Je déclenche toujours l'erreur appropriée).
Utilisation d'un appelable: Classe autretreuse (myClass, métaclass = autre_metaclass_callable): Pass code>
@Neilg C'est une chose différente, je pense que vous avez terminé avec un METACLASS Confit CODE>, c'est à ce sujet, la métaclasse de votre classe dérivée n'est pas une sous-classe des métaclasses de toutes ses bases. Comme le dernier trace de la trace.
Mais qui est coché _calculate_meta code>, qui doit être ignoré lorsque
méta code> n'est pas une instance de
type code> (une fonction régulière n'est pas une instance de
Tapez code>).
Je l'ai compris. C'est parce que quelque chose s'est passé en cours de route et d'objets / typeObject.c: Type_new ne coïncide plus avec lib / type.py: new_class. La version Python appelle conditionnellement _Calculate_meta alors que la version C appelle cela inconditionnellement. Je considère que la mise en œuvre C est la "version correcte".
@Neilg Dans ce cas, il exécutera la fonction et que vous appelez une classe à l'intérieur de cette fonction (avec la même métaclasse que l'une des classes de base), il augmentera un conflit code>.
@Neilg Je ne sais pas si cela exécute le code C avant le code Python ici. Comme je l'ai dit, cela pourrait être parce que après avoir appelé la classe dans la fonction.
Il ne gère pas du tout le code Python. Cela appelle simplement la mise en œuvre C, qui est incompatible.
Concernant la question 1, je pense que la "métaclasse" d'une classe CLS code> doit être comprise comme
type (CLS) code>. Ce mode de compréhension est compatible avec le message d'erreur de Python dans l'exemple suivant:
>>> class MetaMeta(type):
... def __call__(mcls, name, bases, methods):
... metabases = set(type(X) for X in bases)
... metabases.add(mcls)
... if len(metabases) > 1:
... mcls = type(''.join([X.__name__ for X in metabases]), tuple(metabases), {})
... return mcls.__new__(mcls, name, bases, methods)
...
>>> class Meta1(type):
... __metaclass__ = MetaMeta
...
>>> class Meta2(type):
... __metaclass__ = MetaMeta
...
>>> class C1:
... __metaclass__ = Meta1
...
>>> class C2:
... __metaclass__ = Meta2
...
>>> type(C1)
<class '__main__.Meta1'>
>>> type(C2)
<class '__main__.Meta2'>
>>> class C3(C1,C2): pass
...
>>> type(C3)
<class '__main__.Meta1Meta2'>