метакласс python не помнит новое значение

1

Я написал класс Person с метаклассовым заклинанием. В метаклассе я изменяю атрибут, и это нормально, но если я хочу использовать это новое значение для другой операции, он не работает и использует предыдущее значение. Как я могу это исправить?

class Spell(type):
    def __new__(cls,classname,super,classdict):
        def pph( hours ): return lambda self : classdict['pay_per_hour'] * hours

        classdict['pay_per_hour'] = 12
        classdict['day_salary'] = pph(8)
    return type.__new__(cls, classname, super, classdict )

class Person(metaclass=Spell):
    def __init__(self,name,lastname,bday):
        self.name = name
        self.lastname = lastname
        self.bday = bday

    def get_name(self):
        return self._name
    def get_lastname(self):
        return self._lastname
    def get_bday(self):
        return self._bday
    def __repr__(self):
        return "name: {0}, lastname: {1}, bday: {2}".format(self.name,self.lastname,self.bday)

if __name__ == "__main__":
    persona4 = Person("lugdfgca","djfosd","16 febbraio 85")
    print(persona4.pay_per_hour)
    print(persona4.day_salary())
    persona4.pay_per_hour=15
    print(persona4.pay_per_hour)
    print(persona4.day_salary())

Выход

12
96
15
96

но 96 12 * 8 не 15 * 8, почему? где ошибка?

  • 0
    Вы должны исправить свой отступ
  • 1
    По какой причине вы пытаетесь использовать метакласс? В вашем примере нет ничего, что было бы проще с обычным базовым классом.
Показать ещё 1 комментарий
Теги:
metaclass

2 ответа

2

Лямбда, которую вы создали, относится к словарю, заполненному во время построения класса. Позже (после создания класса) изменения в переменных класса не отражаются в нем, но даже если это было так, строка persona4.pay_per_hour = 15 назначает новый атрибут экземпляра вместо изменения атрибута класса. Используйте self.pay_per_hour в функциях, созданных pph чтобы получить значение, которое использует данный экземпляр в данный момент.

Или, что еще лучше, покончить с метаклассом. Там нет причин использовать их здесь, и, как вы видели, легко сделать вещи менее доступными, чем необходимо.

class Spell:
    pay_per_hour = 12
    hours_per_day = 8

    # @property # allows nicer syntax, look it up if you don't know it
    def day_salary(self):
        return hours_per_day * pay_per_hour

class Person(Spell):
    ...

Это обрабатывает изменения в pay_per_hour и hours_per_day прозрачно и на уровне экземпляра.

  • 0
    Этот. Я не уверен, какая польза от использования метакласса в этом случае. Кажется, что хорошее, старомодное наследование классов должно быть более чем достаточно.
1

Проблема в том, что ваша функция pph только ищет значение pay_per_hour в словаре классов, в то время как вы только переопределяете значение pay_per_hour в экземпляре. В Python, когда вы просматриваете значение поля объекта, он сначала проверяет словарь экземпляра, затем в словаре классов (и весь суперкласс в порядке mro).

Вам необходимо изменить свой метакласс для:

def __new__(cls,classname,super,classdict):
    def pph( hours ): return lambda self : self.pay_per_hour * hours

    classdict['pay_per_hour'] = 12
    classdict['day_salary'] = pph(8)
  • 0
    отлично, спасибо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню