Reputation: 766
I have defined a base class that handles generic content, and children classes that are more specific in which content (object type) they accept. However, when calling the function defined in the parent class, the parent variables are used instead of the child variables. How do I get Python to use the child variable inside the parent functions ?
Example code :
class BaseField(object):
__accepted_types = (object,)
def __init__(self, description=""):
self.content = None
self.description = description
def set(self, content):
if isinstance(content, self.__accepted_types):
print(type(content), self.__accepted_types)
print(type(self))
self.__set(content)
else:
raise ValueError("wrong type")
def __set(self, content):
pass
class StringField(BaseField):
__accepted_types = (basestring,)
def __init__(self, description=""):
super().__init__(description)
print(self.__accepted_types)
if __name__ == '__main__':
x = StringField("a test field")
x.set(3)
I expect this code to raise a ValueError
(I'm trying to pass an int
to a class that only accepts str
), however I get the following result:
(<class 'str'>,)
<class 'int'> (<class 'object'>,) <class '__main__.StringField'>
Note that the function correctly returns that it's within "StringField"
but uses the "BaseField"
value for __accepted_types
. The behavior is the same if I declare __accepted_types
as an instance variable.
Upvotes: 2
Views: 228
Reputation: 45231
As a followup to the other answer, I highly recommend watching this talk from PyCon 2013, in which the purpose and use of the Python name-mangling paradigm is discussed.
To summarize, using double underscore for your object variables it not a way to keep them "private". In fact, private variables in Python are not "a thing"; when coming from other languages, using Python effectively requires a shift in thinking on this and other topics.
The purpose of name-mangling it to prevent parent and child classes from falling into the trap of namespace wars, in which, for example, some child class is using an attribute name for a different purpose than the parent class.
For further reading, see these other questions and answers:
Underscore vs Double underscore with variables and methods
What is the meaning of a single- and a double-underscore before an object name?
Upvotes: 1
Reputation: 160397
You're falling victim to name mangling; the names are getting mangled inside the class body and self.__accepted_types
get's transformed to _BaseField__accepted_types
inside set
.
Change all occurrences of __accepted_types
to accepted_types
and it'll work just fine.
p.s If you're indeed using Python 3, basestring
doesn't exist, use str
.
Upvotes: 2