在python中覆盖类变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19719767/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
override class variable in python?
提问by eugene
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?
下面,base_id
and_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
采纳答案by Mike DeSimone
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.
如果您不想像 falsetru 建议的那样违反 DRY 原则,则需要使用元类。我正在考虑写一些东西,但是在 SO 上已经有很长的元类描述,所以检查一下。
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.
基本上,您需要做的是,在创建 的子类时Parent
,将该_id
成员添加到新创建的子类中。
回答by falsetru
As you said in the question, _id
is shared by parent and all children classes. Define _id
for every children classes.
正如您在问题中所说,_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
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)
回答by jpmc26
If you really need to use the ID this way, use parameters:
如果确实需要这样使用 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
etc.
等等。
This assumes you won't be constructing instances of Parent
directly, but that looks reasonable with your example code.
这假设您不会直接构造 的实例Parent
,但是您的示例代码看起来很合理。