在python中重写类变量?

2024-09-30 02:36:40 发布

您现在位置:Python中文网/ 问答频道 /正文

下面,base_id_id是一个类变量,在所有子类之间共享。
有没有办法把他们分成每一个班?

from itertools import count

class Parent(object):
    base_id = 0
    _id = count(0)

    def __init__(self):
        self.id = self.base_id + self._id.next()


class Child1(Parent):
    base_id = 100
    def __init__(self):
        Parent.__init__(self)
        print 'Child1:', self.id

class Child2(Parent):
    base_id = 200
    def __init__(self):
        Parent.__init__(self)
        print 'Child2:', self.id

c1 = Child1()                   # 100
c2 = Child2()                   # 201 <- want this to be 200
c1 = Child1()                   # 102 <- want this to be 101
c2 = Child2()                   # 203 <- want this to be 201

Tags: toselfidbaseinitdefcountbe
3条回答

正如您在问题中所说,_id由父类和所有子类共享。为每个子类定义_id

from itertools import count

class Parent(object):
    base_id = 0
    _id = count(0)

    def __init__(self):
        self.id = self.base_id + self._id.next()


class Child1(Parent):
    base_id = 100
    _id = count(0) # <-------
    def __init__(self):
        Parent.__init__(self)
        print 'Child1:', self.id

class Child2(Parent):
    base_id = 200
    _id = count(0) # <-------
    def __init__(self):
        Parent.__init__(self)
        print 'Child2:', self.id

c1 = Child1()                   # 100
c2 = Child2()                   # 200
c1 = Child1()                   # 101
c2 = Child2()                   # 201

更新

使用元类:

class IdGenerator(type):
    def __new__(mcs, name, bases, attrs):
        attrs['_id'] = count(0)
        return type.__new__(mcs, name, bases, attrs)

class Parent(object):
    __metaclass__ = IdGenerator
    base_id = 0
    def __init__(self):
        self.id = self.base_id + next(self._id)

如果你不想像falsetru建议的那样违反DRY原则,你需要使用元类。我想写点东西,但是there's already a good long description of metaclasses on SO,所以去看看。

简而言之,元类允许您控制子类的创建。

基本上,您需要做的是,在创建Parent的子类时,将_id成员添加到新创建的子类中。

如果确实需要这样使用ID,请使用参数:

class Parent(object):
    def __init__(self, id):
        self.id = id

class Child1(Parent):
    _id_counter = count(0)
    def __init__(self):
        Parent.__init__(self, 100 + self._id_counter.next())
        print 'Child1:', self.id

等等

这假设您不会直接构造Parent的实例,但这在示例代码中看起来是合理的。

相关问题 更多 >

    热门问题