plean
plean

Reputation: 124

can python classes share variable with parent classe

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

Answers (4)

brianpck
brianpck

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

farshed-
farshed-

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

λuser
λuser

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

Aidenhjj
Aidenhjj

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

Related Questions