我有两个类:继承Ancestor类的Child类。我的目标是在不覆盖的情况下为每个实例添加id属性
代码示例:
class Ancestor(tensorflow.Module):
_id = 0
def __init__(self, some_list=):
super(Ancestor, self).__init__()
self.id = Ancestor._id + 1
Ancestor._id += 1
class Child(Ancestor):
_id = 0
def __init__(self):
self.id = Child._id + 1
Child._id += 1
some_list = [char + self.id for char in ["a", "b", "c"] ]
super(Child, self).__init__(some_list)
a1 = Ancestor()
a2 = Ancestor()
c1 = Child()
c2 = Child()
print(a1.id, a2.id, c1.id, c2.id)
>>> 1 2 3 4
我希望打印此设置:1 2 1 2
如何做到这一点?
在Child构造函数中编辑"some_list"只是为了强调Child在调用Ancestor的超级方法之前必须接收其id
Python3用户:请参阅底部,了解使用__init_subclass__
的更好解决方案。
不要硬编码类名。使用type(self)
可以访问每个实例的相应类。
class Ancestor(object):
_id = 0
def __init__(self):
type(self)._id += 1
self.id = self._id
class Child(Ancestor):
_id = 0
def __init__(self):
super(Child, self).__init__()
# Actual class-specific stuff here.
# If there is none, you don't even need to override __init__
a1 = Ancestor()
a2 = Ancestor()
c1 = Child()
c2 = Child()
assert (a1.id, a2.id, c1.id, c2.id) == (1,2,1,2)
或者更干净,使属性成为生成器,而不是要更新的值。请注意,由于count
实例保持其自己的状态,因此不需要将back的任何内容分配给class属性,因此您可以通过实例而不是其类型访问_id
。
from itertools import count
class Ancestor(object):
_id = count(1)
def __init__(self, **kwargs):
super(Ancestor, self).__init__(**kwargs)
self.id = next(self._id)
class Child(Ancestor):
_id = count(1)
Python 3
您可以使用__init_subclass__
来确保Ancestor
的每个子代都有自己的ID生成器,而不必在类定义中显式添加它。
from itertools import count
class CountedInstance:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls._id = count(1)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.id = next(self._id)
class Ancestor(CountedInstance):
pass
class Child(Ancestor):
pass
使用type(self)
而不是类名。
class Ancestor(object):
_id = 0
def __init__(self):
type(self)._id += 1
self.id = self._id
class Child(Ancestor):
_id = 0
a1 = Ancestor()
a2 = Ancestor()
c1 = Child()
c2 = Child()
print(a1.id, a2.id, c1.id, c2.id) # -> 1 2 1 2
注意,您可以使用self.__class__
来完成同样的事情,但它可以被覆盖,所以type(self)
更好。