override class variable in python?

后端 未结 3 1023
灰色年华
灰色年华 2021-01-04 05:10

Below, base_id and _id is a class variable and shared among all child classes.
Is there a way to separate them into each class?



        
相关标签:
3条回答
  • 2021-01-04 05:22

    If you don't want to violate the DRY principle like falsetru suggests, you'll need to use metaclasses. I was thinking of writing something up, but there's already a good long description of metaclasses on SO, so check it out.

    Metaclasses, in short, let you control subclass creation.

    Basically, what you need to do is, upon the creation of a subclass of Parent, add the _id member to the newly-created subclass.

    0 讨论(0)
  • 2021-01-04 05:29

    As you said in the question, _id is shared by parent and all children classes. Define _id for every children classes.

    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
    

    UPDATE

    Using metaclass:

    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)
    
    0 讨论(0)
  • 2021-01-04 05:33

    If you really need to use the ID this way, use parameters:

    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
    

    etc.

    This assumes you won't be constructing instances of Parent directly, but that looks reasonable with your example code.

    0 讨论(0)
提交回复
热议问题