Метаклассы и методы
Добавление метода в метакласс отлично работает в следующем примере.
class Test(object):
def __init__(self, x):
self.x = x
def double(self):
return self.x*2
# method to add
def quadruple(self):
return self.x*4
# creating metaclass
TypeTest = type('TypeTest', (Test,), {'triple': triple,
'quadruple': quadruple})
# prints 8
TypeTest(2).quadruple()
Приведенный ниже пример не работает, и я понятия не имею, почему. Он просто не распознает себя в разобранной функции, и возникает ошибка TypeError.
class Vehicle(object):
def __init__(self, wheels, door=False):
self.wheels = wheels
self.door = door
# method to add
def check_load(self, x):
if x > self.load:
return "Load won't fit"
else:
return "Load will fit"
# creating metaclass
Truck = type('Truck', (Vehicle,), dict(wheels=4,door=True, load=100,
check_load=check_load))
# TypeError: check_load() missing 1 required positional argument: 'x'
Truck.check_load(10)
1 ответ
Прежде всего: вы не создаете метакласс, вы создаете обычные классы. type()
является (базовым) метаклассом здесь, вызов его создает новый объект класса (тот же тип объекта, что class
заявление производит).
Первый type()
вызов по сути эквивалентен:
class TypeTest(Test)
triple = triple
quadruple = quadruple
и второй пример такой же как:
class Truck(Vehicle)
wheels = 4
door = True
load = 100
check_load = check_load
Вы забыли создать экземпляр вашего Truck
учебный класс:
Truck.check_load(10)
Это оставляет check_load()
функция, с которой нечего связать, нет self
,
В первом примере вы создали экземпляр:
TypeTest(2).quadruple()
Обратите внимание на звонок, проходящий в 2
,
Создать экземпляр для self
быть привязанным к:
Truck(4, True).check_load(10)
Если вы хотите, чтобы ваш класс не нуждался в аргументах для создания экземпляра, вам нужно предоставить другой __init__
метод тоже тот, который переопределяет Vehicle.__init__
метод:
def init(self): pass
Truck = type('Truck', (Vehicle,), dict(
wheels=4,door=True, load=100,
check_load=check_load, __init__=init))
Теперь вы можете создать экземпляр без аргументов:
Truck().check_load(10)