2017-01-02 10 views
-4
class UpperAttrMetaclass(type): 

    var = "test" 

    def __new__(upperattr_metaclass, future_class_name, 
       future_class_parents, future_class_attr): 
     print("hello world") 
     uppercase_attr = {} 
     for name, val in future_class_attr.items(): 
      if not name.startswith('__'): 
       uppercase_attr[name.upper()] = val 
      else: 
       uppercase_attr[name] = val 

     # reuse the type.__new__ method 
     # this is basic OOP, nothing magic in there 
     return type.__new__(upperattr_metaclass, future_class_name, 
          future_class_parents, uppercase_attr) 


class Hello(object): 

    __metaclass__ = UpperAttrMetaclass 

    bar = "test" 

obj = Hello() 
print(obj.BAR) # obj has no attribute named BAR 

Traceback (jüngste Aufforderung zuletzt):
Datei "E: \ Python \ test.py", Zeile 32, in
print (obj.BAR)
Attribute: ' Hallo 'Objekt hat kein Attribut' BAR 'Einige Fragen zu Python3 metaclass

Warum Metaklasse UpperAttrMetaclass nicht funktioniert?

+1

Mögliche Duplikat [Python3 Singleton metaclass Methode funktioniert nicht] (http://stackoverflow.com/questions/17237857/python3-singleton-metaclass-method-not-working) – vaultah

+0

Warum diese Frage so wird downvoted ? Es hat ein perfektes Beispiel des Codes und eine gut formulierte Frage (wenn abhängig vom Titel der Frage). – jsbueno

Antwort

1

In Python3 hat sich die Methode zum Angeben einer Metaklasse von Python2 auf eine inkompatible Weise geändert.

Seit Python 3.0 besteht die Methode zum Angeben einer Metaklasse darin, den Metaklassennamen so zu verwenden, als wäre es ein benannter Parameter in der class-Anweisung.

So wird in dem obigen Beispiel shuld Sie Ihre Hallo Klasse deklarieren:

class Hello(metaclass=UpperAttrMetaclass): 
    bar = "test" 

Überprüfen Sie die Dokumentation unter: https://docs.python.org/3.0/whatsnew/3.0.html#changed-syntax

Abgesehen davon, wie Sie bemerkt haben, setzen ein __metaclass__ Attribut in ac alss body ist kein Fehler, aber es tut nichts überhaupt, aber ein Attribut mit diesem Namen zu deklarieren.

Nach ein paar Versionen von Python3.x ist dies die einzige syntaktische Änderung, die mit Python 2 nicht kompatibel ist und keine direkte Lösung darstellt, so dass der Code sowohl Python 2.x als auch Python ist 3.x kompatibel zur gleichen Zeit.

Wenn Sie die gleiche Codebasis für Python 2 und Python 3 benötigen, ruft das Paket six den Aufruf with_metaclass auf, der eine dynamische Klassenbasis mit einer Syntax erstellt, die mit beiden Versionen kompatibel ist. (https://pythonhosted.org/six/#syntax-compatibility)