Metaklasy

  • Wszystko jest obiektem, klasa też
  • Klasę można kopiować, modyfikować, mieć wiele referencji do niej
  • słowo class tworzy obiekt
  • obiekty "klasy", potrafią tworzyć obiekty opisane na podstawie swojej definicji
  • type jest klasą
  • type(name, bases, dict)
    • name - nazwa klasy
    • bases - klasy nadrzędne
    • dict - słownik z atrybutami klasy
  • metaklasa to klasa dla klasy
  • type jest metaklasą zdefiniowaną przez Python'a
  • __metaclass__ atrybut metaklasy dla klasy w Python2
  • class A(metaclass=metaklasa) Python3

In [ ]:
class Punkt():
    x = 1
    y = 2
    def dodaj(self):
        return self.x + self.y
    
p = Punkt()    
print(p)
print(p.x)
print(p.y)
print(p.dodaj())

In [ ]:
def dodaj(self):
    return self.x + self.y

KlasaPunkt = type("Punkt", (), {
    "x": 1,
    "y": 2,
    "dodaj": dodaj
})

p = KlasaPunkt()
print(p)
print(p.x)
print(p.y)
print(p.dodaj())

In [ ]:
def capitalize_metaclass_as_function(name, bases, classdict):
        d = {}
        for attr_key, attr in classdict.items():
            print(attr_key, attr)
            if callable(attr) and not attr_key.startswith("__".format(name)):
                d[attr_key.capitalize()] = attr
            else:
                d[attr_key] = attr
        return type(name, bases, d)

class Punkt(metaclass=capitalize_metaclass_as_function):

    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def dodaj(self):
        return self.x + self.y
    
p = Punkt(1, 2)
print(p.Dodaj)
print(p.Dodaj())

In [ ]:
class CapitalizeMetaclass(type):
    
    def __new__(cls, name, bases, classdict):
        print(cls)
        print(name)
        print(bases)
        print(classdict)
        d = {}
        for attr_key, attr in classdict.items():
            if callable(attr) and not attr_key.startswith("__".format(name)):
                d[attr_key.capitalize()] = attr
            else:
                d[attr_key] = attr
        return super().__new__(cls, name, bases, d)

class Punkt(metaclass=CapitalizeMetaclass):

    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def dodaj(self):
        return self.x + self.y
    
p = Punkt(1, 2)
print(p.Dodaj)
print(p.Dodaj())