comunication between parent and child class python - python

Does anyone know how i can get the name of an object with a class function?
I want to use this because i have a class that is supposed to have multiple players in a list, and get their cordinates
object that wants to give their cordinates:
import math
class Pixel:
"""Represents a posision in a grid with a x posistion, a y position and
a character, the x and y position are saved in one tuple"""`
def __init__(self, char='#', pos=(0, 0)):
assert type(char) == str
assert type(pos[0]) == int and type(pos[1]) == int
self.pos = pos
self.x = self.pos[0]
self.y = self.pos[1]
self.char = char
def __str__(self):
return self.char
def __repr__(self):
return self.char
# possible debug repr 'Pixel object with
# char = ' + str(self.char) + ' and pos = ' + str(self.pos)`
class TestObject(Pixel):
def __str__(self, parent):
return '+'
The parent object wants to know what self.pos is from theTestObject (the parent has a list with different testObjects) is there a way for me to give the TestObject the name of the parent object when i am creating it so that he can push that information (parent.funcname(position)) I need it for a function that doesn't return values.
if anyone knows another way to get TestObject.pos to my parent object please tell too, thanks in advance

You could give your instances of TestObject a reference to the parent. This could be done via the __init__ method of TestObject. This way however, the parent has to be known at the time of the instance's construction. I would make it an optional (keyword) parameter and implement a setter method. For example:
class Pixel:
def __init__(self, char='#', pos=(0, 0), parent=None):
assert type(char) == str
assert type(pos[0]) == int and type(pos[1]) == int
self.pos = pos
self.x = self.pos[0]
self.y = self.pos[1]
self.char = char
self._parent = parent
def set_parent(self, parent):
self._parent = parent
class TestObject(Pixel):
def somemethod(self):
position = 0
# do what ever you need to do here
if isinstance(self._parent, Pixel):
self._parent.set_value(self)
When you add an instance obj of TestObject to the list in the parent object, the parent object should call obj.set_parent(self) to set itself as the object's parent.
Here is an example for a parent class:
class PixelList:
def __init__(self):
self._pixels = []
def add_pixel(self, pixel):
self._pixels.append(pixel)
pixel.set_parent(self)
def set_value(self, pixel):
# do stuff here
position = pixel.pos
If you then call obj.somemethod, your parent object's set_value method is called with the pixel as argument. In the set_value method you can thus access any information of the pixel you like (e.g. pixel.pos).

Related

Getting variables from an outer class

I'm doing a project in Python which requires me to make a nested class. I need to get a variable from the class it is nested in but haven't been able to. I want to be able to get the self variables from Parent in the Child class but my code isn't working, is there any way I could inherit the Parent class' variables? Here is what I tried:
class Parent:
def __init__(self):
self.x = 1;
self.y = 2;
class Child:
def __init__(self):
pass;
def parent_vars(self):
att = super()["x"];
print(att);
parent = Parent();
child = parent.Child();
child.parent_vars();
In python, unlike in Java, a class serves more as a namespace than as an object. An inner class (in this case Parent.Child) is no different semantically than the same class defined as a standalone - the outer class is simply how it's accessed (and it's accessed statically, not requiring an instance - again unlike Java).
If you want a Child to take its Parent's variables, you'll need to tell the Child explicitly which object is its Parent:
class Parent:
def __init__(self):
self.x = 1
self.y = 2
class Child:
def __init__(self, parent):
self.parent = parent
def parent_vars(self):
att = self.parent.x
print(att)
par = Parent()
child = Parent.Child(par) # note how `Parent.Child`, not `par.Child()`
child.parent_vars()
# 1

Why Instance variables reference the same object in this code?

I want to implement the move method in Shape class in has-a relation(So Shape class does not inherit CPoint class), but have a problem in setting class variables.
The given code is:
class CPoint:
def __init__(self, x = 0, y = 0):
self.__x = x
self.__y = y
def __str__(self):
return f"pos({self.__x},{self.__y})"
def get_x(self):
return self.__x
def set_x(self, new_x):
self.__x = new_x
def get_y(self):
return self.__y
def set_y(self, new_y):
self.__y = new_y
def move(self, a, b):
self.__x += a
self.__y += b
return CPoint(self.__x,self.__y)
class Shape:
def __init__(self, color = "yellow", filled = True, pos = CPoint()):
#So each pos must reference the different CPoint() instance
self.__color = color
self.__filled = filled
self.__pos = pos
def __str__(self):
return f"{self.__pos}({self.__color},{self.__filled})"
def move(self, a, b):
self.__pos.move(a,b)
if type(self) == Shape:
return f"{self}"
else:
return f"{self.__pos}{self}"
def main():
a = Shape()
b = Shape("red")
a.move(2,3)
print(b.move(4,5))
main()
the result is:
pos(0,0)(yellow,True)
pos(0,0)(red,True)
pos(2,3)(yellow,True)
pos(6,8)(red,True)
and the result should be like:
pos(0,0)(yellow,True)
pos(0,0)(red,True)
pos(2,3)(yellow,True)
pos(4,5)(red,True)
And I executed the code on the python tutor, and the visualization of the code is like this:
python tutor visualization
So Shape() and Shape("red") objects should reference different CPoint instance (cuz they have their own position data), but they reference the same instance even though I set the default parameter like 'pos = CPoint()'.
Can someone please explain why they're referencing the same instance, and how to get around it?
This is how python does argument defaults, default arguments are initialized once during function declaration and not every time when the function is called like you might expect if you've used other languages like Javascript https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
Because of this, the same CPoint() instance is shared between different constructor calls.
To avoid this behavior you could try setting it inside the function itself.
class Shape:
def __init__(self, color = "yellow", filled = True, pos = None):
if pos is None:
pos = CPoint()
#So each pos must reference the different CPoint() instance
self.__color = color
self.__filled = filled
self.__pos = pos

Attempting to connect classes, where one class has a list the other class

I'm trying to have two classes where one class has a list of the other class. Like a Bag class that has a list of what Balls are in it, where Ball is a class.
class Bag:
Inside = []
def CreateBag(self):
self.Inside.append(Ball("Blue", "Small"))
class Ball:
def __init__(self, Color, Size):
self.Color = Color
self.Size = Size
B = Bag()
B.CreateBag()
print(B.Inside)
When I do print(B.Inside) I get [<__main__.Ball object at 0x000002B7EFF8BA20>]. I've tried B.Inside.Color, but that gives me an error, making me think I have set this up wrong.
You have the basics, although try to follow PEP 8 (Style Guide for Python Code). To display objects beyond the default "<object # address>" you have to define a __repr__ (debug representation) of the object, and perhaps a __str__ (print representation):
class Bag:
def __init__(self):
self.inside = []
def add(self, item):
self.inside.append(item)
def __repr__(self):
return f'Bag({self.inside})'
def __getitem__(self,index):
return self.inside[index]
def __setitem__(self,index,value):
self.inside[index] = value
class Ball:
def __init__(self, color, size):
self.color = color
self.size = size
def __repr__(self):
return f'Ball(color={self.color!r}, size={self.size!r})'
def __str__(self):
return f'{self.size} {self.color} Ball'
bag = Bag()
bag.add(Ball('Blue','Small'))
bag.add(Ball('Red','Big'))
print(bag) # uses Bag.__repr__ since Bag.__str__ isn't defined
print(bag[0]) # uses Bag.__getitem__ and Ball.__str__
bag[0] = Ball('Green','Medium') # uses Bag.__setitem__
print(bag)
print(bag[0].color)
Bag([Ball(color='Blue', size='Small'), Ball(color='Red', size='Big')])
Small Blue Ball
Bag([Ball(color='Green', size='Medium'), Ball(color='Red', size='Big')])
Green

Create a class which dispatches to a random object

Suppose I have classes which have a common method (add), and I want to create a new class RandomPair which would contain a pair of objects of the same class and dispatch add to a random one.
E.g.,
class C1 (object):
def __init__ (self, title, plus = True):
self.title = title
self.plus = plus
self.acc = 0
def add (self, x):
if self.plus:
self.acc += x
else:
self.acc -= x
def __str__ (self):
return "C1(%s,%g)" % (self.title,self.acc)
class C2 (object):
def __init__ (self, title):
self.title = title
self.all = list()
def add (self, x, pos = None):
if pos:
self.all.insert(pos,x)
else:
self.all.append(x)
def __str__ (self):
return "C2(%s,%s)" % (self.title,self.all)
import random
class RandomPair (object):
def __init__ (self, klass, title, **kwargs):
self.objects = [klass(title + "#" + str(i), kwargs) for i in range(2)]
def add (self, *args, **kwargs):
self.objects[random.randint(0,1)].add(args,kwargs)
def __str__ (self):
return "\n".join([str(o) for o in self.objects])
Now, I want to be able to do
rp1 = RandomPair(C1,"test")
rp1.add(1)
rp1.add(2)
rp2 = RandomPair(C2,"test")
rp2.add(1)
rp2.add(2, pos=0)
but I get
TypeError: add() got multiple values for keyword argument 'self'
in self.objects[random.randint(0,1)].add(args,kwargs).
You need to apply the args and kwargs, using similar notation as when you defined the arguments. You need to do this in two places; in both RandomPair.__init__() and in RandomPair.add():
self.objects = [klass(title + "#" + str(i), **kwargs) for i in range(2)]
and
self.objects[random.randint(0,1)].add(*args, **kwargs)
otherwise you are just passing in two arguments, a tuple and a dictionary.
Your next problem is in C2.add(); you are using pos if it is empty; you want to inverse that test. Better still, test explicitly for None:
def add(self, x, pos=None):
if pos is None:
self.all.append(x)
else:
self.all.insert(pos,x)

Class "super" variable

There is a class as following:
class N:
def __init__(self, node_id):
self.id = node_id # id (as an integer for example)
self.super = 0
self.color = 0
It is about creating a node. As you can see, there is an attribute, super. I want to call the color of the supernode.
I tried to implement:
node.color = node.super.color
but, it was wrong implementation. Do you have any idea how to get the information of other node?
You need to explicitly pass the parent node -or at least its color, to the class init function
- there is no way a simplist node class can "guess" how it is connected with other node objects.
One way to go is:
class N(object):
def __init__(self, node_id, parent_node):
self.id = node_ide
self.parent = parent_node
self.color = 0
# and you canget parentnode color with self.node.color

Categories

Resources