简体   繁体   English

python metaclass不记得新值

[英]python metaclass doesn't remember the new value

I wrote a class Person with a metaclass Spell. 我写了一个具有Metaclass Spell的Person类。 In the metaclass I change an attribute and it is ok, but if i want to use this new value for another operation, it doesn't work and it use the previous value. 在元类中,我可以更改属性,并且可以,但是如果我想将此新值用于其他操作,则该行将不起作用,并且将使用先前的值。 How can i fix this? 我怎样才能解决这个问题?

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())

The output is 输出是

12
96
15
96

but 96 is 12*8 not 15*8, why? 但是96是12 * 8而不是15 * 8,为什么? where is the error? 错误在哪里?

The lambda you created refers to the dictionary filled during class construction. 您创建的lambda指的是在类构建期间填充的字典。 Later (after class creation) changes to class variables are not reflected in it, but even if that was the case, the line persona4.pay_per_hour = 15 assigns a new instance attribute instead of changing the class attribute. 稍后(在创建类之后)对类变量的更改不会反映在其中,但是即使是这种情况, persona4.pay_per_hour = 15persona4.pay_per_hour = 15分配一个新的实例属性,而不是更改类属性。 Use self.pay_per_hour in the functions produced by pph to get the value the instance in question uses at the moment. pph产生的函数中使用self.pay_per_hour获取有关实例当前使用的值。

Or, even better, do away with the metaclass. 或者,甚至更好的是,不要使用元类。 There's no reason to use them here, and as you saw, it's easy to make things less extensible than needed. 没有理由在这里使用它们,正如您所看到的,很容易使事情的扩展性超出所需。

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):
    ...

This handles changes to pay_per_hour and hours_per_day transparently and at instance level. 这将透明地在实例级别处理pay_per_hour和hours_per_day的更改。

The problem is that your function pph only look up the value of pay_per_hour in the class dictionary, while you only override the value of pay_per_hour in the instance. 问题是,你的函数pph只能仰望的价值pay_per_hour在类字典,当你只覆盖的值pay_per_hour的实例。 In Python, when you lookup a value of a field of an object, it first check in the instance dictionary, then in the class dictionary (and all the super class in the mro order). 在Python中,当您查找对象字段的值时,它将首先检入实例字典,然后检入类字典(以及所有按mro顺序排列的超类)。

You need to change your metaclass to: 您需要将元类更改为:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM