![](/img/trans.png)
[英]What is the most efficient way to recalculate attributes of a Boost Spirit parse with a different symbol table?
[英]What is the most Pythonic way of implementing classes with auto-incrementing instance attributes?
我有几节课。 创建实例时,期望的行为是为实例分配了ID。 为简单起见,让我们假设ID应该从0开始,并在每次创建实例时增加1。 对于这几种类别中的每一种,ID应该独立增加。
我知道如何用C ++做到这一点。 我实际上也在Python中做到了这一点,但是我不喜欢C ++解决方案,并且我想知道这是由于我对Python的了解有限(不到6周)还是有更好的解决方案? ,更Python化的方式。
在C ++中,我既使用继承又使用合成来实现此目的。 两种实现都使用“好奇重复模板模式”(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 ++中,我有一个很好的主意,我在做什么,例如,即使我的类实际上继承了乘法(不仅仅来自Countable <>模板化类),我也看不到任何问题-一切都很简单。
现在,在Python中,我看到了以下问题:
1)当我使用组合时,我实例化了计数类:
counterClass = Countable()
我必须为每个课程都这样做,这可能容易出错。
2)当我使用继承时,当我想要繁衍时会遇到更多麻烦。 请注意,上面我没有定义Counted或AnotherCounted的__init__
,但是如果我继承了乘法,则必须显式调用基类构造函数,或者使用super()。 我不喜欢这样(还可以吗?)我也可以使用元类,但是我的知识在那里受到限制,而且似乎增加了复杂性而不是简单性。
总而言之,尽管必须使用Countable()显式定义counterClass类属性,但我认为这种组合方式可能更适合Python实现。
感谢您对我的结论的有效性的意见。
我也希望有比我更好的解决方案的提示。
谢谢。
我会使用__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
我可能会使用一个简单的类装饰器...
import itertools
def countable(cls):
cls.counter = itertools.count()
return cls
@countable
class Foo(object):
def __init__(self):
self.ID = next(self.__class__.counter)
@countable
class Bar(Foo):
pass
f = Foo()
print f.ID
b = Bar()
print b.ID
如果您真的想以“幻想”的方式进行此操作,则可以使用元类:
import itertools
class Countable(type):
def __new__(cls,name,bases,dct):
dct['counter'] = itertools.count()
return super(Countable,cls).__new__(cls,name,bases,dct)
class Foo(object):
__metaclass__ = Countable
def __init__(self):
self.ID = next(self.__class__.counter)
class Bar(Foo):
pass
f = Foo()
print f.ID
b = Bar()
print b.ID
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.