Python: Sharing Class Variables Between Multiple Classes - python

My problem is how to share a variable or a buffer between more than one class
e.g. writing into a single buffer from multiple classes knowing that some classes are running in a threaded environment
example
class my1(object):
def __init__(self):
self.buffer=[0]*5
self.size=0
def insert(self,data):
self.data=data
self.buffer[self.size]=self.data
self.size+=1
class my2(my1):
def __init__(self):
self.insert('data1')
class my3(my1):
def __init__(self):
self.insert('data2')
The desired result would be the buffer containing both data1 and data2 to be processed
yet the buffer within class my1 is defined inside the (init) section and cannot be shared
any suggestions?
Thanks alot

You're doing it wrong.
Just create an object of class my1 and pass it to objects of class my2 and my3.
# leave my1 as it is
class my2(): # no need to inherit from my1
def __init__(self, my1obj): # buffer is object of my1
my1obj.insert('data1')
class my3():
def __init__(self, my1obj):
my1obj.insert('data2')
mybuffer = my1()
my2obj = my2(mybuffer)
my3obj = my3(mybuffer)

If you really want the buffer to be bound to the My1 class, you can use a static class variable
class My1(object):
buffer = [0] * 5

Related

Can we use super method in a newly created class without any inheritance?

I am new to classes in python. I searched and went through so many articles on super() method which creates so much of confusion.
Type - 1
class Square():
def __init__(self,side):
self.side = side
print("Its confusing")
super().__init__()
def area(self):
return self.side * self.side
c = Square()
print(c.area())
In Type - 1 , if I mention super().__init__() what is the use of it? I don't understand why we use super().__init__() in a newly created class which is not inherited from any other class. And I don't understand what it does here.
If we give it after assigning self.side = side it runs properly and is executed.
Type - 2
class Square():
def __init__(self):
# self.side = side
# print("Its confusing")
super().__init__()
e = Square()
e()
If I just give only super().__init__() inside __init__ it gives error.
TypeError: 'Square' object is not callable
My doubt is:
1.Can we use super().__init__() in a newly created class? and It runs well without error.
2.Then why is Type - 2 throwing error if I put only super().__init__() inside __init__?
Can you please make it in simple words?
For type-1 because Square class does not inherit from any base class, then the call for super().__init__() actually does nothing.
However, it's still good to keep this code, in case you use Square class for multiple inheritance. There is an example in a different question, see here:
https://stackoverflow.com/a/8613067/362792.
So copying that example, suppose you had class Square, class Color, and then class ColoredSquare:
class ColoredSquare(Square, Color):
...
In this case, when creating ColoredSquare instance, the super().__init__() from Square is actually calling Color.__init__() method. So it's indeed necessary then.
For type-2, your error is not from the init method. Instead, it's actually e() is producing your error for "TypeError: 'Square' object is not callable".
To use an object in this way you need to have call method.
eg.
class Square():
def __init__(self):
super().__init__()
def __call__(self):
print('call for square')
e = Square()
e()
Inheritance is used to recycle code... and you use super to "fetch" code defined in a parent class.
# parent class
class Parallelogram:
def __init__(self, side1, side2):
self.side1, self.side2 = side1, side2
def area(self):
return self.side1 * self.side2
# child class
class Square(Parallelogram):
def __init__(self, side):
super().__init__(side, side)
p = Parallelogram(2, 3)
print(p.area())
# 6
s = Square(4)
print(s.area())
# 16
print(issubclass(Parallelogram, object))
#True
print(issubclass(Square, Parallelogram))
#True
print(hasattr(Square, 'area')) # inherited from the parent
True

Global Inheritance with thread classes in Python

I am wondering how I could use a property of one threaded class as a variable in all other classes (kind of like a global variable), in python. Here is a brief outline.
class A(Thread):
def__init__(self):
Thread.__init__(self)
global globalTime
self.actualTime = gpsd.utc #This gets the real time from a gps module
globalTime = self.actualTime
self.classAvar1 = 1
self.start()
class B(Thread):
def __init__(self):
Thread.__init__(self)
self.classBvar2 = 2
self.actualTime = globalTime
self.start()
class C(Thread):
def __init__(self):
Thread.__init__(self)
self.classCvar3 = 3
self.actualTime = globalTime
self.start()
I am trying to declare actualTime in class A and get the time from data read from a gps module. I am then trying to pass this and only this property into classes B and C. Right now I get around it by declaring a global variable called globalTime, and setting it equal to the actualTime property in class A.
Is this the right approach? Thanks for the help!

Python: Access to other Classes Objects

I have a question regarding the classes in python3. In my programm i have a "main" class that is getting started first and sets some parameters that are needed for the other parts of the programm. But now my other classes need some objects of the main class. How can i use the objects of the main class without initialising the main class everytime the subclass needs the object ? I looked into python inheritance but maybe i didnt understand it correctly
class Chunk(main.Main):
def __init__(self,pos_in_world_x,pos_in_world_y):
#self.chunksize = settings.blocks_per_chunk
self.prog = main.Main.prog
self.ctx = main.Main.ctx
this is my code for the subclass
You can use class variables:
class Main():
prog = 1
ctx = 2
def __init__(self):
pass
class Chunk(Main):
def __init__(self, pos_in_world_x, pos_in_world_y):
self.prog = Main.prog
self.ctx = Main.ctx
a = Chunk(3, 4)
print(a.prog) # 1
print(a.ctx) # 2
If you can't change Main to move your definitions outside __init__, then what you're asking for is impossible. If your variable is defined in __init__, you can't access it before calling __init__, i.e. initialising the class. You can't get round this.
You need a super __init__ call in your subclass and if you have that you only need to do:
class Chunk(main.Main):
def __init__(self,pos_in_world_x,pos_in_world_y):
super().__init__()
#self.chunksize = settings.blocks_per_chunk
Both of the assignments are done by Main's __init__.
But I think that Chunk has not an is-a but rather a has-a relation with Main so Main should actually be an argument rather than a super class:
class Chunk(object):
def __init__(self, main, pos_in_world_x,pos_in_world_y):
#self.chunksize = settings.blocks_per_chunk
self.prog = main.prog
self.ctx = main.ctx
Any one that creates a Chunk must pass a Main instance.
It is actually difficult to hide information in Python, so here are a few options which don't require inheritance (see jpp's answer for the inheritance option). In general, the code is easier to understand when you pass information explicitly (option 1 below, or inheritance), but there may be cases where you'd prefer the other options.
Option 1: The needed info can simply be passed as additional arguments to Chunk's __init__ (either by passing the prog and ctx values themselves, or by passing the Main class or its instance - depending on whether the needed info is stored as class or instance variables). Here's an example of passing Main as an argument:
class Main():
prog = 1
ctx = 2
def __init__(self):
pass
class Chunk():
def __init__(self, pos_in_world_x, pos_in_world_y, M):
#self.chunksize = settings.blocks_per_chunk
self.prog = M.prog
self.ctx = M.ctx
c = Chunk(3, 4, Main)
print(c.prog) # 1
print(c.ctx) # 2
Option 2: Chunk can access Main's class variables directly:
class Main():
prog = 1
ctx = 2
def __init__(self):
pass
class Chunk():
def __init__(self, pos_in_world_x, pos_in_world_y):
#self.chunksize = settings.blocks_per_chunk
self.prog = Main.prog
self.ctx = Main.ctx
c = Chunk(3, 4)
print(c.prog) # 1
print(c.ctx) # 2
Option 3: Chunk can access the instance variables of the Main instance directly (Main needs to be instantiated before Chunk is instantiated):
class Main():
def __init__(self):
self.prog = 1
self.ctx = 2
class Chunk():
def __init__(self, pos_in_world_x, pos_in_world_y):
#self.chunksize = settings.blocks_per_chunk
self.prog = m.prog
self.ctx = m.ctx
m = Main()
c = Chunk(3, 4)
print(c.prog) # 1
print(c.ctx) # 2

Allow object access to its owning object's attribute

I've got a whole bunch of classes that are effectively algorithms, and they all inherit from a Mechanism class. I then have a MechanismStack class which holds a list of a bunch of these algorithm classes, they are all interchangeable/modular - i.e. output of Mechanism1.encode() goes into Mechanism2.encode() as the input etc. (effectively a queue of functions).
A couple of these classes produce extra data than just the output. I want to store this extra data in the MechanismStack class (which is also an object - there are multiple different stacks comprised of different algorithms)
class MechanismStack:
self.stack = [Mechanism1(), Mechanism2(), Mechanism3()]
self.attribute = list()
def encode(self, input):
#process input through self.stack Mechanisms
class Mechanism1(Mechanism):
def function(self, input):
#code
owningMechanismStack.attribute = ['some', 'list']
myStack = MechanismStack()
myStack.encode('myInputString')
Add the owning MechanismStack as a property of Mechanism, which you supply when calling the constructor.
class Mechanism:
def __init__(self, owner):
this.owningMechanismStack = owner
class MechanismStack:
self.stack = [Mechanism1(self), Mechanism2(self), Mechanism3(self)]
...

python - setting property of class on module loading

I'm working on a code dealing with dict data on python.
While implementing such class, I have to define a lot of properties. It's not that hard, but recently I thought it would be much better if I could use something like helper function.
For example, let's assume that I have a class like the following.
class MyClass(object):
def __init__(self, data):
self.data = data
#property
def version(self):
return self.data["version"]
If I could write this class in something like the following.
class MyClass(object):
def __init__(self, data):
self.data = data
define_own_property("data", "version")
It looks trivial, but if I can do that, I think I can reuse a lot of validation/exception handling cases.
Any idea? :D
You can achieve something like that by just writing a function to return the accessor you want:
def define_own_property(attr, key):
def prop(self):
return getattr(self, attr)[key]
return property(prop)
class MyClass(object):
def __init__(self, data):
self.data = data
version = define_own_property("data", "version")
Note that you must do version = ... There is no way to make a simple function call define_own_property add a property to the class being defined, because that class doesn't yet exist so you can't reference it.
Another possibility is to give your class an attribute that is a list or dict or something containing the relevant parameters ("data", "version", etc.), then write a class decorator that reads these parameters and auto-creates the series of properties. This would remove the need to define the properties inside the class at all; you would just give a list of the things you wanted the properties to access, and use the decorator once on the class.
It seems like you could use a descriptor:
class Descr(object):
def __init__(self,attr,key):
self.attr = attr
self.key = key
def __get__(self,obj,type=None):
return getattr(obj,self.attr)[self.key]
def __set__(self,obj,value):
getattr(obj,self.attr)[self.key] = value
def __delete__(self,obj):
del getattr(obj,self.attr)[self.key]
class MyClass(object):
def __init__(self, data):
self.data = data
version = Descr("data","version")
foobar = Descr("data","foobar")
a = MyClass({})
a.version = 1
print a.version
a.foobar = 'string'
print a.data

Categories

Resources