【问题标题】:can python classes share variable with parent classepython类可以与父类共享变量吗
【发布时间】:2016-09-29 14:07:43
【问题描述】:

我有一个名为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

还有其他三个继承自 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

我的想法是每次创建SocialPlatform 的实例时增加nb_post。我认为这个变量在所有继承自SocialPlatform的类之间共享

所以我在我的主要功能中进行了测试:

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

但是当我使用这段代码时,我得到了这个输出:

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

使用此方法nb_post 在 Twitter、Facebook 或 Instagram 实例之间共享,而不是在所有实例之间共享。

所以我的问题是:有没有办法在 python 中做到这一点?

【问题讨论】:

    标签: python inheritance


    【解决方案1】:

    当没有找到一个属性时,它会在更高的级别上查找。分配时,虽然使用了最本地的级别。

    例如:

    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
    

    这里_init_id_post 被声明为classmethod,而你正在做cls.nb_post = cls.nb_post + 1。 在此表达式中,第二次出现 cls.nb_post 将第一次引用 SocialPlatform,然后您分配 cls 对象,该对象引用 TwitterInstagram 类,而不是 SocialPlatform。 当您在同一个类上再次调用它时,第二个 cls.nb_post 出现将不会引用 SocialPlatform,因为您在 Twitter 类的级别创建了属性(例如)。

    解决方案不是使用cls,而是使用SocialPlatform.nb_post += 1(并将其设为@staticmethod

    【讨论】:

      【解决方案2】:

      你必须在增量表达式中显式引用基类:

      def _init_id_post(cls):
          cls.nb_post += 1
          return cls.nb_post
      

      应该是:

      def _init_id_post(cls):
          SocialPlatform.nb_post += 1
          return SocialPlatform.nb_post
      

      根据:

      How to count the number of instance of a custom class?

      【讨论】:

        【解决方案3】:
           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
        

        我想你可以自己解决剩下的问题。祝你好运!

        【讨论】:

          【解决方案4】:

          这对我有用:

          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
          

          然后:

          >>> a = Facebook()
          >>> b = Twitter()
          >>> c = Twitter()
          >>>
          >>> a.id_post
          0
          >>> b.id_post
          1
          >>> c.id_post
          2
          

          【讨论】:

            猜你喜欢
            • 2017-10-28
            • 2018-11-11
            • 2020-10-14
            • 1970-01-01
            • 1970-01-01
            • 2021-07-04
            • 1970-01-01
            • 1970-01-01
            • 2015-05-11
            相关资源
            最近更新 更多