I wish to use a meta class in order to add helper methods based on the original class. If the method I wish to add uses self.__attributeName
I get an AttributeError
(because of name mangling) but for an existing identical method this isn't a problem.
Here is a simplified example
# Function to be added as a method of Test
def newfunction2(self):
"""Function identical to newfunction"""
print self.mouse
print self._dog
print self.__cat
class MetaTest(type):
"""Metaclass to process the original class and
add new methods based on the original class
"""
def __new__(meta, name, base, dct):
newclass = super(MetaTest, meta).__new__(
meta, name, base, dct
)
# Condition for adding newfunction2
if "newfunction" in dct:
print "Found newfunction!"
print "Add newfunction2!"
setattr(newclass, "newfunction2", newfunction2)
return newclass
# Class to be modified by MetaTest
class Test(object):
__metaclass__ = MetaTest
def __init__(self):
self.__cat = "cat"
self._dog = "dog"
self.mouse = "mouse"
def newfunction(self):
"""Function identical to newfunction2"""
print self.mouse
print self._dog
print self.__cat
T = Test()
T.newfunction()
T.newfunction2() # AttributeError: 'Test' object has no attribute '__cat'
Is there a way of adding newfunction2
that could use self.__cat
?
(Without renaming self.__cat
to self._cat
.)
And maybe something more fundamental, why isn't self.__cat
being treated in the same way for both cases since newfunction2
is now part of Test
?
Name mangling happens when the methods in a class are compiled. Attribute names like __foo
are turned in to _ClassName__foo
, where ClassName
is the name of the class the method is defined in. Note that you can use name mangling for attributes of other objects!
In your code, the name mangling in newfunction2
doesn't work because when the function is compiled, it's not part of the class. Thus the lookups of __cat
don't get turned into __Test_cat
the way they did in Test.__init__
. You could explicitly look up the mangled version of the attribute name if you want, but it sounds like you want newfunction2
to be generic, and able to be added to multiple classes. Unfortunately, that doesn't work with name mangling.
Indeed, preventing code not defined in your class from accessing your attributes is the whole reason to use name mangling. Usually it's only worth bothering with if you're writing a proxy or mixin type and you don't want your internal-use attributes to collide with the attributes of the class you're proxying or mixing in with (which you won't know in advance).