I am trying to access a function from within a class that is within a different file.
My layout is:
Directory
-> ClassFile.py
-> _AFile.py
in ClassFile:
class TestClass:
from ._AFile import test_1, test_2, test_3
def __init__(self):
def RunAllTests(self):
self.test_1()
self.test_2()
self.test_3()
@staticmethod
def __DoSomething(a, b):
return a + b
in _AFile:
def test_1(self):
self.__DoSomething
def test_2(self):
self.__DoSomething
def test_3(self):
self.__DoSomething
This is what I want to do but cannot as I get: AttributeError: 'TestClass' object has no attribute '__DoSomething'
How can I access the static method from TestClass within AFile?
2 Answers 2
Methods which start with __ are class-private and they are mangled and so you cant access them when importing form a different file.
Official Docs:
__*
Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between "private" attributes of base and derived classes. See section Identifiers (Names).
Fix
Change __DoSomething to _DoSomething
You are spreading the implementation of class TestClass into two files ClassFile.py and _AFile.py. In such a case you need to put __init__.py (empty file) inside the module.
Fix
Your directory structure should look like below
mymodule
--> __init__.py
--> ClassFile.py
--> _AFile.py
ClassFile.py
class TestClass:
from ._AFile import test_1, test_2, test_3
def __init__(self):
pass
def RunAllTests(self):
self.test_1()
self.test_2()
self.test_3()
@staticmethod
def _DoSomething(a, b):
result = a+b
print (result)
return result
_AFile.py
def test_1(self):
self._DoSomething(1,2)
def test_2(self):
self._DoSomething(2,3)
def test_3(self):
self._DoSomething(4,5)
Testing:
from mymodule.ClassFile import TestClass
test = TestClass()
test.RunAllTests()
Output:
3
5
9
Comments
You are calling a private method from outside its class declaration, and it happens that python is doing some transformations under the hood.
As explained in the link above, the private attributes and methods of a python class are modified under the form _ClassName__attributename. This is a protection to avoid collision with subclasses defining potentially the same attributes or methods.
As a result, to make your import work as you want, you have two possibilities:
- keep the method private, but use the generated method name from python
- Use protected methods to use in your secondary file.
The following files will show you both possibilities:
_AFile.py
def test_1(self):
# Express which private method you want to use
self._TestClass__DoSomething()
def test_2(self):
# Use a protected attribute only
self._do_another_thing()
ClassFile.py
class TestClass:
from _AFile import test_1, test_2
def __init__(self):
pass
def RunAllTests(self):
self.test_1()
self.test_2()
@staticmethod
def __DoSomething():
print("done something")
@staticmethod
def _do_another_thing():
print("done another thing")
Execution:
>>> from ClassFile import TestClass
>>> TestClass().RunAllTests()
done something
done another thing
_AFile, atleast the member listing?test_1exists in_AFile, there is no__DoSomethingin_AFile. You'll have to importTestClassin_AFile. Also you'll have to call it asTestClass.__DoSomethingas it is static.