我有几个类(class)。实例创建的期望行为是为实例分配一个 ID。为简单起见,让我们假设 ID 应从 0 开始,并在每次创建实例时增加 1。对于这几个类中的每一个,ID 都应该独立递增。
我知道如何在 C++ 中执行此操作。我实际上也用 Python 做过,但我不像 C++ 解决方案那样喜欢它,我想知道这是否是由于我对 Python 的了解有限(仅 6 周多一点),或者是否有更好的,更 Pythonic 的方式。
在 C++ 中,我使用继承和组合实现了这一点。两种实现都使用 Curiously Recurring Template Pattern (CRPT) 习惯用法。我稍微更喜欢继承方式:
#include <iostream>
template<class T>
class Countable{
static int counter;
public:
int id;
Countable() : id(counter++){}
};
template<class T>
int Countable<T>::counter = 0;
class Counted : public Countable<Counted>{};
class AnotherCounted: public Countable<AnotherCounted>{};
int main(){
Counted element0;
Counted element1;
Counted element2;
AnotherCounted another_element0;
std::cout << "This should be 2, and actually is: " << element2.id << std::endl;
std::cout << "This should be 0, and actually is: " << another_element0.id << std::endl;
}
对组合方式:
#include <iostream>
template<class T>
class Countable{
static int counter;
public:
int id;
Countable() : id(counter++){}
};
template<class T>
int Countable<T>::counter = 0;
class Counted{
public:
Countable<Counted> counterObject;
};
class AnotherCounted{
public:
Countable<AnotherCounted> counterObject;
};
int main(){
Counted element0;
Counted element1;
Counted element2;
AnotherCounted another_element0;
std::cout << "This should be 2, and actually is: " << element2.counterObject.id << std::endl;
std::cout << "This should be 0, and actually is: " << another_element0.counterObject.id << std::endl;
}
现在,在 python 中,没有模板可以为每个类提供不同的计数器。于是,我将可数类包装成一个函数,得到了如下实现:(继承方式)
def Countable():
class _Countable:
counter = 0
def __init__(self):
self.id = _Countable.counter
_Countable.counter += 1
return _Countable
class Counted ( Countable() ) :
pass
class AnotherCounted( Countable() ):
pass
element0 = Counted()
element1 = Counted()
element2 = Counted()
another_element0 = AnotherCounted()
print "This should be 2, and actually is:", element2.id
print "This should be 0, and actually is:", another_element0.id
及组成方式:
def Countable():
class _Countable:
counter = 0
def __init__(self):
self.id = _Countable.counter
_Countable.counter += 1
return _Countable
class Counted ( Countable() ) :
counterClass = Countable()
def __init__(self):
self.counterObject = Counted.counterClass()
class AnotherCounted( Countable() ):
counterClass = Countable()
def __init__(self):
self.counterObject = self.counterClass()
element0 = Counted()
element1 = Counted()
element2 = Counted()
another_element0 = AnotherCounted()
print "This should be 2, and actually is:", element2.counterObject.id
print "This should be 0, and actually is:", another_element0.counterObject.id
让我烦恼的是这个。在 C++ 中,我很清楚自己在做什么,例如即使我的类实际上继承了 multiply(不仅仅是从 Countable<> 模板化类),我也没有看到任何问题——一切都非常简单。
现在,在 Python 中,我看到以下问题:
1) 当我使用组合时,我像这样实例化计数类:
counterClass = Countable()
我必须为每个类都这样做,这可能容易出错。
2) 当我使用继承时,当我想要继承乘法时,我会遇到更多的麻烦。请注意,在上面,我没有定义 Counted 和 AnotherCounted 的 __init__
,但是如果我继承 multiply,我将不得不显式调用基类构造函数,或者使用 super()。我不喜欢这个(还是?)我也可以使用元类,但我的知识有限,而且它似乎增加了复杂性而不是简单性。
总而言之,我认为组合方式可能更适合 Python 实现,尽管存在必须使用 Countable() 显式定义 counterClass 类属性的问题。
如果您对我的结论的有效性提出意见,我将不胜感激。
我也希望能提供比我更好的解决方案的提示。
谢谢。
最佳答案
我会使用 __new__
,这样你就不必记住在 __init__
中做任何事情:
class Countable(object):
counter = 0
def __new__(cls, *a, **kw):
instance = super(Countable, cls).__new__(cls, *a, **kw)
instance.id = cls.counter + 1
cls.counter = instance.id
return instance
class A(Countable):
pass
class B(Countable):
pass
print A().id, A().id # 1 2
print B().id # 1
关于c++ - 实现具有自动递增实例属性的类的最 Pythonic 方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17173149/