2009-05-04 12 views
6

J'ai essayé d'en apprendre davantage sur les métaclasses en Python. J'ai l'idée principale, mais je n'arrive pas à activer le mécanisme. Si je comprends bien, vous pouvez spécifier M comme étant la métaclasse lors de la construction d'une classe K en mettant __metaclass__ à M au niveau global ou de la classe. Pour tester cela, je l'ai écrit le programme suivant:__metaclass__ ne devrait-il pas forcer l'utilisation d'une métaclasse en Python?

p = print 

class M(type): 
    def __init__(*args): 
     type.__init__(*args) 
     print("The rain in Spain") 

p(1) 
class ClassMeta: 
    __metaclass__ = M 

p(2) 
__metaclass__ = M 
class GlobalMeta: pass 

p(3) 
M('NotMeta2',(), {}) 

p(4) 

Cependant, quand je le lance, je reçois la sortie suivante:

 
C:\Documents and Settings\Daniel Wong\Desktop>python --version 
Python 3.0.1 

C:\Documents and Settings\Daniel Wong\Desktop>python meta.py 
1 
2 
3 
The rain in Spain 
4 

Si je ne vois pas « La pluie en Espagne » après 1 et 2? Que se passe t-il ici?

+1

Le double négatif "ne force pas" est difficile à analyser. Pourriez-vous résoudre la question, s'il vous plaît? –

+0

Merci pour les commentaires. Je pense que cela devrait être plus facile à comprendre maintenant. – allyourcode

Répondre

13

En Python 3 (que vous utilisez) métaclasses sont spécifiés par un paramètre de mot-clé dans la définition de la classe:

class ClassMeta(metaclass=M): 
    pass 

Spécification d'une variable globale ou la propriété de classe __metaclass__ est ancienne syntaxe de Python 2.x et non plus soutenu. Voir également "What's new in Python 3" et PEP 2115.

2

Cela fonctionne comme prévu en Python 2.6 (et versions antérieures), mais dans la version 3.0 sont spécifiées différemment métaclasses:

class ArgMeta(metaclass=M): ... 
2

La syntaxe de métaclasses a changed en Python 3.0. L'attribut __metaclass__ n'est plus spécial ni au niveau de la classe ni au niveau du module. Pour faire ce que vous essayez de faire, vous devez spécifier metaclass comme argument mot-clé à la déclaration class:

p = print 

class M(type): 
    def __init__(*args): 
     type.__init__(*args) 
     print("The rain in Spain") 

p(1) 
class ClassMeta(metaclass=M): pass 

Rendement:

1 
The rain in Spain 

Comme on pouvait s'y attendre.