Reputation: 124
I have a class named SocialPlatform
:
class SocialPlatform:
nb_post = 0
def __init__(self, data):
self.data = data
self._init_type()
self.id_post = self._init_id_post()
@classmethod
def _init_id_post(cls):
cls.nb_post += 1
return cls.nb_post
and threee other classes that inherit from SocialPlatform
:
class Facebook(SocialPlatform):
_NAME = 'facebook'
@classmethod
def get_class_name(cls):
return cls._NAME
# code here
class Twitter(SocialPlatform):
_NAME = 'twitter'
@classmethod
def get_class_name(cls):
return cls._NAME
# code here
class Instagram(SocialPlatform):
_NAME = 'instagram'
@classmethod
def get_class_name(cls):
return cls._NAME
# code here
My idea was to increment nb_post
each time an instance of SocialPlatform
was created. I tought this variable was shared between all the classes that inherit from SocialPlatform
So I tested that in my main function :
def main():
post = Post() # an other class with stuff in it, it doesn't matter here
social_platform = {
'facebook': Facebook,
'twitter': Twitter,
'instagram': Instagram
}
while True:
try:
platform = social_platform[post.actual_post['header']['platform']](post.actual_post['data'])
except KeyError:
print 'Platform (%s) not implemented yet' % post.actual_post['header']['platform']
sys.exit(84)
print 'platform name : ' + platform.get_class_name()
print 'post id : ' + str(platform.id_post)
# platform.aff_content()
post.pop()
if not len(post.post):
break
print 'enter return to display next post'
while raw_input() != "": pass
but when I use this code I get this output :
platform name : twitter
post id : 1
enter return to display next post
platform name : facebook
post id : 1
enter return to display next post
platform name : twitter
post id : 2
With this method nb_post
is shared between Twitter, Facebook or Instagram instance, not all of them.
So my question is : is there any way to do this in python ?
Upvotes: 1
Views: 111
Reputation: 8254
This works for me:
class SocialPlatform(object):
nb_post = 0
def __init__(self):
self.id_post = A.nb_post
A.increment()
@classmethod
def increment(cls):
cls.nb_post += 1
class Facebook(SocialPlatform):
pass
class Twitter(SocialPlatform):
pass
And then:
>>> a = Facebook()
>>> b = Twitter()
>>> c = Twitter()
>>>
>>> a.id_post
0
>>> b.id_post
1
>>> c.id_post
2
Upvotes: 0
Reputation: 238
class A():
n = 0
def __init__(self):
A.n += 1
class B(A):
def __init__(self):
super(B, self).__init__()
class C(A):
def __init__(self):
super(C, self).__init__()
a = A()
print(a.n) #prints 1
b = B()
print(a.n) #prints 2
c = C()
print(a.n) #prints 3
I think you can figure out the rest by yourself. Good luck!
Upvotes: 1
Reputation: 1001
When an attribute is not found, it will be looked up on a higher level. When assigning, the most local level is used though.
For example:
class Foo:
v = 1
a = Foo()
b = Foo()
print(a.v) # 1: v is not found in "a" instance, but found in "Foo" class
Foo.v = 2 # modifies Foo class's "v"
print(a.v) # 2: not found in "a" instance but found in class
a.v = 3 # creates an attribute on "a" instance, does not modify class "v"
print(Foo.v) # 2
print(b.v) # 2: not found in "b" instance but found in "Foo" class
Here _init_id_post
was declared a classmethod
, and you're doing cls.nb_post = cls.nb_post + 1
.
In this expression, the second cls.nb_post
occurence will refer to SocialPlatform
the first time, then you assign on the cls
object which is refering to the Twitter
or Instagram
class, not SocialPlatform
.
When you call it again on the same class, the second cls.nb_post
occurence will not refer to SocialPlatform
since you created the attribute at the level of the Twitter
class (for example).
The solution is not to use cls
but use SocialPlatform.nb_post += 1
(and make it a @staticmethod
)
Upvotes: 1
Reputation: 1289
You have to explicitly reference the base class in the increment expression:
def _init_id_post(cls):
cls.nb_post += 1
return cls.nb_post
Should be:
def _init_id_post(cls):
SocialPlatform.nb_post += 1
return SocialPlatform.nb_post
As per:
How to count the number of instance of a custom class?
Upvotes: 1