【问题标题】:Python static variablesPython 静态变量
【发布时间】:2021-11-17 03:03:45
【问题描述】:

我试图为这个父类的所有子实例设置一个静态变量作为“id”。我遇到的问题是重复计算此 ID,可能是因为父母的 __init__ 被调用了两次。但是如果我删除显式的Parent().__init__() 调用,那么计数器根本不会增加。如何让 id 只增加一个?这是我的代码 sn-p:

#!/usr/bin/python3
class Parent:
    cls_id = 0

    def __init__ (cls):
        cls.cls_inc_id()

    @classmethod
    def cls_inc_id (cls):
        cls.cls_id += 1

    @classmethod
    def child_inc_id (self):
        self.id += 1


class Child1 (Parent):

    def __init__ (self):
        Parent().__init__()
        self.id = super().cls_id
        print ("Child1 id: ", self.id)

class Child2 (Parent):

    def __init__ (self):
        Parent().__init__()
        self.id = super().cls_id
        print ("Child2 id: ", self.id)


child1 = Child1()
child2 = Child1()

child3 = Child2()
child4 = Child2()

我的输出是: %> ./static_vars.py

Child1 id:  2
Child1 id:  4
Child2 id:  6
Child2 id:  8

提前致谢

【问题讨论】:

  • 对不起,您到底想完成什么? 您期望的输出是什么?
  • 顺便说一句,不要使用cls 作为__init__ 的第一个参数的名称。按照惯例,它应该是__init__ (self),因为它是一个实例方法

标签: python static-variables


【解决方案1】:

由于Parent().__init(),它增加了两次。这会创建一个全新的对象,对其进行初始化,然后将其丢弃。你应该使用super().__init__(),并在你的__init__ method refer to Parent.cls_inc_id`中。然后就可以了。

顺便说一句,在Parent.__init__ 中,您调用参数“cls”,但它实际上是“self”——这是一个对象方法,而不是类方法。

新代码:

#!/usr/bin/python3
class Parent:
    cls_id = 0

    def __init__ (self):
        print("Parent.__init__")
        Parent.cls_inc_id()

    @classmethod
    def cls_inc_id (cls):
        print("Parent.cls_inc_id")
        cls.cls_id += 1

    @classmethod
    def child_inc_id (cls):
        print("child_inc_id")
        cls.id += 1


class Child1 (Parent):

    def __init__ (self):
        print("Child1.__init__")
        super().__init__()
        self.id = super().cls_id
        print ("Child1 id: ", self.id)

class Child2 (Parent):

    def __init__ (self):
        print("Child2.__init__")
        super().__init__()
        self.id = super().cls_id
        print ("Child2 id: ", self.id)


child1 = Child1()
child2 = Child1()

child3 = Child2()
child4 = Child2()

输出:

Child1.__init__
Parent.__init__
Parent.cls_inc_id
1
Child1 id:  1
Child1.__init__
Parent.__init__
Parent.cls_inc_id
1
Child1 id:  2
Child2.__init__
Parent.__init__
Parent.cls_inc_id
1
Child2 id:  3
Child2.__init__
Parent.__init__
Parent.cls_inc_id
1
Child2 id:  4

【讨论】:

  • 另外cls.cls_inc_id() 必须是Parent.cls_inc_id()。否则它会创建一个实例属性而不是更新类属性。
  • 哈!很好的眼睛!
  • @Barmar 不,它没有,因为cls_inc_idclassmethod
  • 是的,因为他将它作为对象方法调用。试试看。
  • 我不确定你的意思。它将始终将类对象作为第一个参数提供。不管你怎么称呼它,它都不会创建实例属性。但是,它会根据您的调用方式创建单独的类变量。即,如果您使用self.cls_inc_id(),则Parent.cls_inc_id 方法将通过Child1Child2,具体取决于self 的类型
【解决方案2】:

正如其他人所提到的,您没有正确使用 super 构造函数,但我也会引用父类中的实际类,而不是您错误命名为 cls 的实例 self

class Parent:
    cls_id = 0

    def __init__(self):
        self.id = Parent.cls_id
        Parent.cls_id += 1


class Child1(Parent):
    def __init__(self):
        super().__init__()
        print ("Child1 id: ", self.id)


class Child2(Parent):
    def __init__(self):
        super().__init__()
        print ("Child2 id: ", self.id)


child1 = Child1()
child2 = Child1()

child3 = Child2()
child4 = Child2()
Child1 id:  0
Child1 id:  1
Child2 id:  2
Child2 id:  3

如果您想为每种类型的类设置一个单独的 ID,您可以使用字典映射类到 id:

from collections import defaultdict


class Parent:
    cls_ids = defaultdict(int)

    def __init__(self):
        self.id = Parent.cls_ids[type(self)]
        Parent.cls_ids[type(self)] += 1
Child1 id:  0
Child1 id:  1
Child2 id:  0
Child2 id:  1

【讨论】:

  • 感谢您提供有关使用 collections 包的提示。我会试一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2014-12-25
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 2023-03-23
相关资源
最近更新 更多