python 元类不记得新值

发布于 2024-12-02 01:19:15 字数 1188 浏览 0 评论 0原文

我用元类 Spell 编写了一个 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,为什么?错误在哪里?

I wrote a class Person with a metaclass Spell. 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? where is the error?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

行至春深 2024-12-09 01:19:15

您创建的 lambda 指的是在类构造期间填充的字典。稍后(在类创建之后)对类变量的更改不会反映在其中,但即使是这种情况,行 persona4.pay_per_hour = 15 也会分配一个新的实例属性,而不是更改类属性。在 pph 生成的函数中使用 self.pay_per_hour 来获取相关实例当前使用的值。

或者,更好的是,取消元类。没有理由在这里使用它们,正如您所看到的,很容易使事情的可扩展性低于所需的程度。

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 的更改。

The lambda you created refers to the dictionary filled during class construction. 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. Use self.pay_per_hour in the functions produced by pph to get the value the instance in question uses at the moment.

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.

披肩女神 2024-12-09 01:19:15

问题在于,您的函数 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)

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

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文