0

I have the below Python code:

class Test:
    def __init__(self):
        pass

    def PublicFunc1(self,value):
        return self.PrivateFunc1(value)
    def PublicFunc2(self,value):
        return self.PrivateFunc2(value)

    def PrivateFunc1(self,value):
        return value * 10
    def PrivateFunc2(self,value):
        return value * 100

Now PrivateFunc1 and PrivateFunc2 are purely private functions. But they are supposed to be long functions and hence they can't be kept in the same module file.

I want to take the code of the two functions out of the main file and keep it in a separate file, but also ensure that they are private to the test class.

Can this be done in any way ?

Thanks for making me learn.

falsetru
  • 357,413
  • 63
  • 732
  • 636
Subhayan Bhattacharya
  • 5,407
  • 7
  • 42
  • 60

1 Answers1

-1

The short answer is that you cannot implement those methods in another file. You should consider whether or not those functions need to be broken down into smaller component functions if you believe the implementation code is so long that it affects readability and complexity.

If you refactor these long methods and break them down into their component behaviors you will increase readability and decrease complexity. This in turn will make your code more pythonic.

You're shouldn't try to force different language paradigms onto python -- instead, you should learn the pythonic way of handling certain problems/tasks.

Please refer to the zen of python (if you're unfamiliar):

~$ python
Python 2.7.13 (default, Dec 18 2016, 07:03:39)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>

I'm guessing you're a C or C++ programmer. Python doesn't differentiate definitions from implementations. You should not be attempting to write this type of code in Python.

Python is an interpreted language, so it doesn't go through the compilation process that allows implementations to live in different files.

Compiled programs go through the following processes:

  • Preprocessing
  • compilation
  • assembly
  • linking

Interpreted programs are interpreted line by line.


An Aside on "Private" Class Members:

Furthermore, python doesn't strictly enforce the "private", "protected", or "public" scope of class attributes/methods. There are conventions for these scopes, however this is merely a convenience and is not strictly enforced.

Public:

  • Any attribute that doesn't begin with a leading underscore.

Protected:

  • Any attribute that begins with a single leading underscore.

Private:

  • Any attribute that begins with two leading underscores.
  • These attributes are mangled, so the original attribute name is changed. The attribute is still inherited.

Here's a sample program to demonstrate:

#!/usr/bin/env python
class BaseExample(object):
    def __init__(self):
        print "In base ctor"
        self.val = 1
        print "self.val: ", self.val
        self._val = 2
        print "self._val: ", self._val
        self.__val = 3
        print "self.__val: ", self.__val
        print '-'*50

    def print_private_attr(self):
        print "Printing private attribute: "
        print '\n','+'*50, '\n'
        print self.__val


class ExampleChild(BaseExample):
    def __init__(self):
        #self = Example()
        super(ExampleChild, self).__init__()
        print "In child ctor"
        print "self.val: ", self.val
        print "self._val: ", self._val
        print "self.__val: ", self._BaseExample__val
        print '-'*50

    def change_private_inherited_attr(self, val):
        print "Printing private attribute: ",self._BaseExample__val
        print '-'*50
        self._BaseExample__val = val
        print "Printing private attribute: ", self._BaseExample__val

print 'In global scope:'
print '\n','='*50, '\n'
example = BaseExample()
print '\n','-'*50, '\n'
example2 = ExampleChild()
print '\n','='*50, '\n'
print example.__dict__
print example2.__dict__
print '\n','='*50, '\n'
print 'In global scope:'
print 'example._BaseExample__val: ', example._BaseExample__val
print 'example2._BaseExample__val: ', example2._BaseExample__val
print 'Changing value of private attr:'
example2._BaseExample__val = 10
print 'In global scope:'
print 'example2._BaseExample__val: ', example2._BaseExample__val
example2.change_private_inherited_attr(100)
print 'In global scope:'
print 'example2._BaseExample__val: ', example2._BaseExample__val

Which has the following output:

In global scope:

==================================================

In base ctor
self.val:  1
self._val:  2
self.__val:  3
--------------------------------------------------

--------------------------------------------------

In base ctor
self.val:  1
self._val:  2
self.__val:  3
--------------------------------------------------
In child ctor
self.val:  1
self._val:  2
self.__val:  3
--------------------------------------------------

==================================================

{'_val': 2, '_BaseExample__val': 3, 'val': 1}
{'_val': 2, '_BaseExample__val': 3, 'val': 1}

==================================================

In global scope:
example._BaseExample__val:  3
example2._BaseExample__val:  3
Changing value of private attr:
In global scope:
example2._BaseExample__val:  10
Printing private attribute:  10
--------------------------------------------------
Printing private attribute:  100
In global scope:
example2._BaseExample__val:  100
Community
  • 1
  • 1
Charles D Pantoga
  • 4,307
  • 1
  • 15
  • 14
  • I can make the functions begin with two leading __ , but can i put them in a separate file and use them inside this module ? – Subhayan Bhattacharya Jan 18 '17 at 05:34
  • Well, it _is_ enforced at the lexical level: http://stackoverflow.com/questions/70528/why-are-pythons-private-methods-not-actually-private – DYZ Jan 18 '17 at 05:35
  • @DYZ I was working on editing my answer when you wrote that, yes obviously they are not inherited. But you can still access them if you understand how names are mangled in python. – Charles D Pantoga Jan 18 '17 at 05:43
  • @CharlesAddis That's why I say they are enforced at the lexical level - but not at the semantic one. – DYZ Jan 18 '17 at 05:44
  • @DYZ yes, I was confirming what you said, not questioning it. – Charles D Pantoga Jan 18 '17 at 05:57