如何创建子类之间不共享的类变量?

时间:2014-06-03 16:08:01

标签: python python-2.7

我需要使用在类的实例之间共享的变量。所以,类变量似乎符合要求。但是这些类变量也是在子类之间共享的,这需要避免。

问题在于:

class Parent(object):
    a=[]

class Child(Parent):
    pass

print(Child.a is Parent.a) # => True # Need to avoid this

以下是我试图解决的问题:

  1. 可以通过重新声明它的Child来遮蔽父类的变量,但是当Child.a再次指向Parent.a时,它仍然可以删除子的“a”变量。

    class Parent(object):
        a=[]
    
    class Child(Parent):
        a=[] # Works, but delete-able.
    
    print(Child.a is Parent.a) # => False # Works
    del Child.a
    print(Child.a is Parent.a) # => True # Breaks again
    
  2. 与prev相同,但通过元类添加“a”,这更好。

    class meta(type):
        def __new__(cls, name, base, clsdict):
                temp_class = type.__new__(cls, name, base, clsdict)
                temp_class.a=[]
                return temp_class
    class Parent(object):
        __metaclass__=meta
    
    class Child(Parent):
        pass
    
    print(Child.a is Parent.a) # => False # Works
    del Child.a
    print(Child.a is Parent.a) # => True # Breaks again
    
  3. 但它们都没有解决“可能删除Child的类变量”的问题。

    是否有可能为类变量设置某种描述符,这会导致删除不可能?如果没有,那么解决这个问题的好方法是什么?

1 个答案:

答案 0 :(得分:2)

要使类属性对该类是私有的,而不是子类,请在其前面加上" __" (两个下划线)。这被称为"类 - 私人会员"或"类 - 私人参考。"

以下__update位于Mapping类中,但不在子类中。

class Mapping:
    def __init__(self, iterable):
        self.items_list = []
        self.__update(iterable)

    def update(self, iterable):
        for item in iterable:
            self.items_list.append(item)

    __update = update   # private copy of original update() method

class MappingSubclass(Mapping):

    def update(self, keys, values):
        # provides new signature for update()
        # but does not break __init__()
        for item in zip(keys, values):
            self.items_list.append(item)

来自:Python Classes documentation

这是原始代码。请注意,Child类不会从父类继承__a属性。

另请注意,Child 实例对象也不会继承__a属性。 __a attr对Parent及其实例是私有的,它不会被继承。

class Parent(object):
    __a = []

class Child(Parent):
    def check(self):
        print self.__a  # raises exception, __a is in Parent only, not in self

try:
    print(Child.__a is Parent.__a)
except AttributeError as exc:
    print exc
print
try:
    Child().check()
except AttributeError as exc:
    print exc

输出

type object 'Child' has no attribute '__a'

'Child' object has no attribute '_Child__a'