Python: sharing variables between contained class - python

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'

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

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?

Related

Create child class object using parent class instance

lets say we have class A and it has one instance - x. How to make a child class of class A where I would be able to pass x as an argument and get all its parameters and pass it to child class object. precisely speaking I want to do something like this.
class A:
def __init__(self, parameter1, parameter2):
self.parameter1 = parameter1
self.parameter2 = parameter2
class B(A):
def __init__(self, Ainstance, someParameter):
super().__init__(**Ainstance.__dict__)
self.someParameter = someParameter
x = A(parameter1='1', parameter2='2')
x = B(x, someParameter='3')
print(x.parameter1)
print(x.parameter2)
print(x.someParameter)
the goal is to create a class where I would be able to get all the parameters of parent class object, and add my own attributes. The problem in the code above is I won't be able to do that with all classes because not all of them has __dict__ attribute.
I have this example code which I use to remind myself how to construct a proxy.
#soProxyPattern
class Example:
def __init__(self):
self.tag_name = 'name'
def foo(self):
return 'foo'
def bar(self, param):
return param
class Container:
def __init__(self, contained):
self.contained = contained
self.user_name = 'username'
def zoo(self):
return 0
def __getattr__(self, item):
if hasattr(self.contained, item):
return getattr(self.contained,item)
#raise item
c = Container(Example())
print(c.zoo())
print(c.foo())
print(c.bar('BAR'))
print(c.tag_name)
print(c.user_name)
The output is:
0
foo
BAR
name
username
This shows that Container can have its own attributes (methods or variables) which you can access over and above all of the attributes of the contained instance.
Instead of dict you could use the dir and getattr like this:
class A:
def __init__(self, parameter1, parameter2):
self.parameter1 = parameter1
self.parameter2 = parameter2
class B(A):
def __init__(self, Ainstance, someParameter):
parameters = {param: getattr(Ainstance, param) for param in dir(Ainstance) if not param.startswith("__")}
super().__init__(**parameters)
self.someParameter = someParameter
For a more detailed explanation see: Get all object attributes in Python?

Run a method in initialize after class has been called

I want the results of the method_test() to to be stored in variable a. So that I access it outside my class
class test:
def __init__(self):
a = method()
def method_test():
return "working"
check = test
print(check.a)
You need to set it as an attribute, which can be done with self.a:
class test:
def __init__(self):
self.a = test.method_test()
def method_test():
return "working"
check = test()
print(check.a)
#working
class test:
def __init__(self):
self.a = self.method_test()
def method_test(self):
return "working"
check = test()
print (check.a)

Python : How to write class in class

How could I modify the class Auto, to make sure the main work?
class Tool:
def __init__(self, target):
self.target = target
class Wifi:
def __init__(self):
pass
def connect(self, id):
print id
self.target.write("xxxxxxxxx")
def verify(self)
pass
if __name__ == '__main__':
T = Tool(target)
T.Wifi.connect("dev")
I want to imitate the module like redmine:
from redmine import Redmine
redmine = Redmine(REDMINE_URL, key = REDMINE_API_KEY)
redmine.issue.get('16520')
This is not done with nested classes but with composition:
class Tool:
def __init__(self, target):
self.target = target
self.wifi = Wifi(self.target)
class Wifi:
def __init__(self, target):
self.target = target
def connect(self, id):
print id
self.target.write("xxxxxxxxx")
def verify(self)
pass
if __name__ == '__main__':
T = Tool(target)
T.wifi.connect("dev")

Implement Python class based on the parameter passed to constructor

I am implementing a python class, which constructs another object in the constructor whose type is determined based on the parameter passed to it. For example in the code below "workerA" has the behavior of class "MyAClass" and "workerB" object has the behavior of "MyBClass".
I am using this method instead of deriving different class from the base class because the BaseClass is already being used in a different code which cannot be changed. So if I want another behavior of BaseClass as for "MyBClass" behavior then I only need to passed the parameter dbtype = "MyBClass" to it.
Is there any better method which can be used and which gives the same result?
import sys
# MyAClass definition
class MyAClass :
def __init__(self, serverSettings):
self._serverSettings = serverSettings
def initialize(self):
self._init = 1;
print("Calling", sys._getframe(1).f_code.co_name)
def add(self):
self._init = 2;
print("Calling", sys._getframe(1).f_code.co_name)
def finalize(self):
self._init = 3;
print("Calling", sys._getframe(1).f_code.co_name)
def __del__(self):
print('Calling destructor of class ', self.__class__.__name__)
# MyBClass definition
class MyBClass :
def __init__(self, serverSettings):
self._serverSettings = serverSettings
def initialize(self):
self._init = 1;
print("Calling", sys._getframe(1).f_code.co_name)
def add(self):
self._init = 2;
print("Calling", sys._getframe(1).f_code.co_name)
def finalize(self):
self._init = 3;
print("Calling", sys._getframe(1).f_code.co_name)
def __del__(self):
print('Calling destructor of class ', self.__class__.__name__)
# The base class which will be called in main program
class BaseClass :
def __init__(self, serverSettings, dbtype = None):
if(dbtype == None):
self.__worker = MyAClass(serverSettings)
elif(dbtype == "MyBClass") :
self.__worker = MyBClass(serverSettings)
else :
print("Undefined type")
def initialize(self):
self.__worker.initialize()
def add(self):
self.__worker.add()
def finalize(self):
self.__worker.finalize()
if __name__ == "__main__":
serverSettings = dict()
serverSettings["address"] = "localhost"
serverSettings["name"] = "Testname"
workerA = BaseClass(serverSettings)
workerA.add()
workerB = BaseClass(serverSettings, dbtype = "MyBClass")
workerB.finalize()
I know this doesn't produce the same output as your original program, but would something like this work for your purposes? Unless you're querying the method name (as you are above), you should get functionally identical results.
class BaseClass :
def __init__(self, serverSettings, dbtype=None):
if(dbtype == None):
self.__worker = MyAClass(serverSettings)
elif(dbtype == "MyBClass") :
self.__worker = MyBClass(serverSettings)
else :
print("Undefined type")
def __getattribute__(self, x):
settings = object.__getattribute__(self, '__dict__').get('_BaseClass__worker')
return settings.__getattribute__(x)
Alternately, using some class twizzing like this:
class BaseClass :
def __init__(self, serverSettings, dbtype='MyAClass'):
dbtypes = {'MyAClass': MyAClass,
'MyBClass': MyBClass}
if dbtype not in dbtypes:
raise("Undefined type")
self.__class__ = dbtypes[dbtype]
self.__init__(serverSettings)
I made the following code changes based on the suggestions
class BaseClass :
def __init__(self, serverSettings, Classtype = MyAClass):
authclasses = [MyAClass, MyBClass]
if Classtype not in authclasses :
self.__worker = MyAClass(serverSettings)
else :
self.__worker = MyBClass(serverSettings)
def __getattribute__(self, x):
settings = object.__getattribute__(self, '__dict__').get('_BaseClass__worker')
return settings.__getattribute__(x)

object inheritance and nested cmd

This is probably a basic OO question:
I'm trying to do a nested console menu with cmd which has gone well.
I also want all my sub-consoles to have access to the same objects. This has not gone well.
My simple Example:
import cmd
class MainConsole(cmd.Cmd):
def __init__(self,obj1,obj2):
cmd.Cmd.__init__(self)
self.prompt = ">"
self.obj1 = obj1 # The objects I want access to in all my consoles.
self.obj2 = obj2
self.menu1 = SubConsole1() # I could pass in the objects here as arguments
self.menu2 = SubConsole2() # but there should be a better way.
def do_menu1(self,args):
self.menu1.cmdloop()
def do_menu2(self,args):
self.menu2.cmdloop()
def do_info(self,args):
self.menu1.do_info(args)
self.menu2.do_info(args)
def do_exit(self,args):
return -1
class SubConsole1(cmd.Cmd,MainConsole):
def __init__(self):
cmd.Cmd.__init__(self)
self.prompt = "1>"
def do_action(self,args):
print self.obj1.someattr1 # Doesn't work
class SubConsole2(cmd.Cmd,MainConsole):
def __init__(self):
cmd.Cmd.__init__(self)
self.prompt = "2>"
def do_action(self,args):
print obj1.someattr2 # Doesn't work
class anobject(object):
def __init__(self,init_value):
self.someattr1 = init_value
self.someattr2 = init_value * 2
object1 = anobject(1)
object2 = anobject(2)
c=MainConsole(object1,object2)
c.cmdloop()
When I run this I get
>
>menu1
1>info
AttributeError: SubConsole1 instance has no attribute 'obj1'
Try again.
>
>menu2
2>info
NameError: global name 'obj1' is not defined
I'm not sure if the SubConsoles should be sub-classes of MainConsole. I also tried nesting the SubConsoles inside of MainConsole.
EDIT Okay, I misunderstood what you're doing.
You are right, SubConsole1 and 2 do not need to inherit from MainConsole. But they should have a reference to the main console.
Something like:
class MainConsole(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self, obj1, obj2)
self.obj1 = obj2
self.obj2 = obj2
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
Then you can access the objects you want by accessing self.maincon.obj1 and self.maincon.obj2
The other option, and probably a better one from a design point of view, is to pull out all the objects you want to access into a Context container object, and have all the various Cmd objects maintain their own reference to that Context container.
Something like this:
import cmd
from collections import namedtuple
class MyConsole(cmd.Cmd):
def __init__(self, context):
cmd.Cmd.__init__(self)
self.context = context
class ConsoleContext(object):
def __init__(self, **kwargs):
self.__dict__ = kwargs
class MainConsole(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.menu1 = SubConsole1(context)
self.menu2 = SubConsole2(context)
self.prompt = '>'
def do_menu1(self, args):
self.menu1.cmdloop()
def do_menu2(self, args):
self.menu2.cmdloop()
def do_quit(self, args):
return True
class SubConsole1(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.prompt = '1>'
def do_action(self, args):
print self.context.message1
def do_quit(self, args):
return True
class SubConsole2(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.prompt = '2>'
def do_action(self, args):
print self.context.message2
def do_quit(self, args):
return True
if __name__ == '__main__':
context = ConsoleContext(message1='Message 1', message2='Message 2')
con = MainConsole(context)
con.cmdloop()
Hope I was clear enough.
You don't need multiple inheritance, but you need to give obj1 and obj2 to the inherited objects, except if you give some default values to obj1 and obj2.
class SubConsole1(MainConsole):
def __init__(self, obb1, obj2):
MainConsole.__init__(self, obj1, obj2)
self.prompt = "1>"
def do_action(self,args):
print self.obj1.someattr1 # Doesn't work
instanciated by :
sub1 = SubConsole1(object1, object2)
The other answer is correct insofar as you should not be using multiple inherritance, as the following is true:
class A(object):
pass
class B(A):
pass
class C(A):
pass
class D(B):
pass
a = A()
b = B()
c = C()
d = D()
isTrue = isinstance(a,A) and isinstance(b,A) and isinstance(c,A) and isinstance(d,A)
isTrue = isTrue and isinstance(b,B)and isinstance(d,B)
isTrue = isTrue and isinstance(c,C)
isTrue = isTrue and isinstance(d,D)
>>> print isTrue
True
It would also be wise to create a method of your main class wich creates subcmds, passing their reference to the subcmd's __init__ function. This way you have your object spawn its children more naturally.
class MainConsole(cmd.Cmd):
def spawnsubconsole(self):
return SubConsole1(self)
def __init__(self):
cmd.Cmd.__init__(self, obj1, obj2)
self.obj1 = obj2
self.obj2 = obj2
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
Then you can access the objects you want by accessing self.maincon.obj1 and self.maincon.obj2 and get the sub-cmd by running maincon.spawnsubconsole() assuming maincon is an instance of the main console class.

Categories

Resources