Reputation: 382
I need to use variables, which are shared among instances of a class. So, class variables seemed to fit the bill. But also those class variables are shared among sub-classes, which needs to be avoided.
Here's the problem:
class Parent(object):
a=[]
class Child(Parent):
pass
print(Child.a is Parent.a) # => True # Need to avoid this
Here's how I tried to solve:
Its possible to just shadow parent's class variable by re-declaring it the Child, but its still possible to delete child's "a" variable, when Child.a again points back to Parent.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
Same as prev, but "a" added through metaclass, which is nicer.
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
But none of them solves the "possible to delete Child's class variable" problem.
Is it possible to have some sort of descriptor for class variables, which can make deletion impossible? If not, what would be a good way to solve this?
Upvotes: 2
Views: 978
Reputation: 15170
To make a class attribute private to that class, and not subclasses, prefix it with "__" (two underscores). This is called a "class-private member" or "class-private reference."
In the following __update
is in the Mapping class, but not in the subclass.
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)
From: Python Classes documentation
Here's the original code. Note that the Child class doesn't inherit the __a
attribute from the parent class.
Also note that a Child
instance object doesn't inherit the __a
attribute, either. The __a
attr is private to the Parent and its instances, it's not inherited.
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'
Upvotes: 2