1

Is there a way to share member variables between a class and a nested class ?

for example

class Base(object):
  class __Internal(object):
    def __init__(self, parent):
        self.__parent = parent
        self.__parent.__private_method()


#
def __init__(self):
    self.__internal = Base.__Internal(self)
    return

def __private_method(self):
    print "hurray"
    return

if name == "main": b = Base()`

is there a way for the __Internal class to access members of the parent class ?

iam looking for private members like parent.__vars/__methods .

I have edited the code to better explain this. running this code throws

AttributeError: 'Base' object has no attribute '_Internal__private_method'
user3279954
  • 556
  • 2
  • 7
  • 22
  • The Base object is a singleton btw. – user3279954 Mar 26 '15 at 04:04
  • 2
    Internal class has reference to its parent `self.__parent`. So you can use this to access parent's class members. – Marcin Mar 26 '15 at 04:07
  • Iam specifically looking for private methods, so classes outside Base cannot invoke except the internal class ex the __private_method() above – user3279954 Mar 26 '15 at 06:10
  • There are no private variables or methods in python. What you have is something that only appears as private with double underscore. You can access it if want anytime. – Marcin Mar 26 '15 at 06:12
  • I have pasted the code in pastebin for better formating. http://pastebin.com/0rr1FLik. If you run the code the error will be obvious. – user3279954 Mar 26 '15 at 06:16
  • I modified your example code. Please check my answer. – Marcin Mar 26 '15 at 06:28

2 Answers2

0

You must use BaseClassName.methodname(self, arguments) or BaseClassName.field

Example (very ugly code):

class Base(object):
    some_field = "OK"

    class Internal(object):
        def __init__(self, parent):
            self.__parent = parent

        def change_some_field(self):
            Base.some_field = "NOP"

    def __init__(self):
        self.__private = "val"
        self.__internal = Base.Internal(self)

    def show_field(self):
        print self.some_field

    def change_some_field(self):
        self.__internal.change_some_field()


def main():
    a = Base()
    a.show_field()
    a.change_some_field()
    a.show_field()
    return 0

if __name__ == '__main__':
    main()

You can find a very useful resources at Why are Python's 'private' methods not actually private?

Community
  • 1
  • 1
Jose Raul Barreras
  • 849
  • 1
  • 13
  • 19
  • if Base version of change_some_field is changed to __change_some_field this will become no callable from the Internal class. – user3279954 Mar 26 '15 at 06:09
  • From https://docs.python.org/2/tutorial/classes.html: “Private” instance variables that cannot be accessed except from inside an object don’t exist in Python.(....)Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class. btw, I still can't found how access to __some_field from Internal. :( – Jose Raul Barreras Mar 26 '15 at 18:07
0

To access privete method, instead of this:

self.__parent.__private_method()

use this:

self.__parent._Base__private_method()

Modified your example:

class Base(object):
        class __Internal(object):
                def __init__(self, parent):
                        self.__parent = parent
                        self.__parent._Base__private_method()


        def __init__(self):
                self.__internal = Base.__Internal(self)
                return

        def __private_method(self):
                print "hurray"
                return


if __name__ == "__main__":
        b = Base()

It results in:

hurray
Marcin
  • 215,873
  • 14
  • 235
  • 294
  • Thanks Marcin this works!!!! I wonder if there other alternative ways to approach this . Basically i have a class 'Base' that will be used by other clients. I want one special client 'friend_class' to invoke internal functions of 'Base'. So i added a internal class and i'll pass '_internal' reference to the 'friend' class. the 'internal' basically acts as a stub code and a gate for the friend class to work with Base class's private methods. If the class name needs to be added the friend will also be able achieve the same and the internal wont be needed in that case. – user3279954 Mar 27 '15 at 00:31
  • You could create public getter methods to work with private data or call privet methods. The methods are made private for a reason. Python does not really make them private like in c++ (you can still call them as u see in python) but, its better not to do it. Normal way is to make public interface to your class. – Marcin Mar 27 '15 at 00:36