Duplication of class inside two different objects - python

I found a bug in my program and I did some digging before making something much simpler to understand the problem.
In a nutshell: I'm creating two objects from a class where I want to store an object from another class. But When I'm doing this, both objects are getting the same result. How can I prevent this duplication?
It seems like both objects are pointing on the same class.
# Sub-class that may not be extendable
class MyClass:
def __init__(self, number):
self.number = number
#classmethod
def add_number(cls, number=0):
return cls(number)
# Main class
class MyOtherClass:
my_objects = []
"""
Initialize the class
:param List[MyClass] my_objects: List of MyClass objects
"""
def __init__(self, this_object):
self.my_objects.append(this_object)
if __name__ == "__main__":
my_object1 = MyOtherClass(MyClass.add_number())
my_object2 = MyOtherClass(MyClass.add_number())
for i in range(100):
my_object1.my_objects.append(MyClass.add_number(i))
print(f"Appending obj1 : {my_object1.my_objects[i].number}")
for y in range(100, 0, -1):
my_object2.my_objects.append(MyClass.add_number(y))
print(f"Appending obj2 : {my_object2.my_objects[y].number}")
# later
z = 0
while z < len(my_object1.my_objects):
print(f"obj1 : {my_object1.my_objects[z].number}")
print(f"obj2 : {my_object2.my_objects[z].number}")
z += 1

Related

Circular attributes in Python

I am working with several classes, with each having it's own attributes.
Trying to avoid to pass a lot of variables when calling sub_functions, I would rather call classe's attributes.
As an example, let's concider 2 classes such as :
class Class_A(object):
def __init__(self, element_b):
self.value_specific_to_a = 1
self.element_b = element_b
def element_a_can_do(self):
print(self.element_b.value_specific_to_b)
class Class_B(object):
def __init__(self):
self.element_a = None
self.value_specific_to_b = 2
def add_a(self, element_a):
self.element_a = element_a
def element_b_can_do(self):
print(self.element_a.value_specific_to_a)
item_b = Class_B()
item_a = Class_A(item_b)
item_b.add_a(item_a)
I think that it is pointer's addresses of those classes that are save to each other, but I wonder if it can cause any issue/leak in my code.

Python 2.7, defining a base class with attributes, id with init constructor

I am trying to define a generic base class Geometry, with a unique id for each object starting at 0. I am using init as the method.
I am trying to create a generic base class named Geometry that I will use to organize geometry objects like point or polygon and containing an id attribute starting at 0. I know all of the objects should have a unique ID. I'm using the constructor (__init__) when creating a new Geometry object (integer). And would like for the base class to automatically assign the ID of the Geometry object.
Current code:
class Geometry(object):
def__init__(self,id):
self.id = id
I think I am on the right path but I am not positive. Should I have id = 0 above def__init__(self,id)?
Any guidance will be appreciated.
If the first line of your class is id = 0 then it becomes a class attribute and is shared by all instances of Geometry and all of its children.
Here is an example of using a class scoped variable:
#!/usr/bin/env python2
class Geometry(object):
# ident is a class scoped variable, better known as Geometry.ident
ident = 0
def __init__(self):
self.ident = Geometry.ident
Geometry.ident += 1
class Circle(Geometry):
def __init__(self, radius):
Geometry.__init__(self)
self.radius = radius
def __str__(self):
return '<Circle ident={}, {}>'.format(self.ident, self.radius)
class Equilateral(Geometry):
def __init__(self, sides, length):
# super is another way to call Geometry.__init__() without
# needing the name of the parent class
super(Equilateral, self).__init__()
self.sides = sides
self.length = length
def __str__(self):
return '<Equilateral ident={}, {}, {}>'.format(self.ident,
self.sides, self.length)
# test that ident gets incremented between calls to Geometry.__init__()
c = Circle(12)
e = Equilateral(3, 8)
f = Circle(11)
print c
assert c.ident == 0
print e
assert e.ident == 1
print f
assert f.ident == 2
Something feels wrong about this, though I've not put my finger on it.
class Geometry(object):
def __init__(self,id=0):
self.id = id
__init__ in python is invoked when you create an instance of that class
circle = Geometry(1)

How do I reference the variable declared under a class in Python?

I am relatively new to Python and I am using Python 2.7.x
I have a question regarding namespaces in Python:
class Team():
x = 2
def p(self):
print x
a = Team()
a.p()
When I run the code, it says global x is not defined. Shouldn't x belong to the Team object? My goal is to create a Team class where x has a default value of 2.
In Java it would be something like:
class Team()
{
int x = 2;
}
a = new Team();
If you want an instance attribute and a default value of 2 :
class Team(object): # use object for new style classes
def __init__(self, x=2):
self.x = x # use self to refer to the instance
def p(self):
print self.x # self.x
a = Team()
a.p()
2
b = Team(4) # give b a different value for x
b.p()
4
Difference between class vs instance attributes
new vs old style classes
If you want make x as class variable, just try this way:
class Team(object):
x = 2
def __init__(self):
pass
print Team.x
Team.x = 3
print Team.x
You don't need to instance to get the value and you can change it as you want.
If you want to make the num as instance property, you have to use self(like this in Java):
class Team(object):
def __init__(self, num):
self.num = num
def get_num(self):
return self.num
def set_num(self, change_num):
self.num = change_num
t1 = Team(2)
print t1.get_num()
t1.set_num(3)
print t1.get_num()

Creating an object with a reference to the object that created it

I have a program where an object creates another object. However, the second object that gets created needs to be able to access the first. Is this possible?
EG (pseudocode)
class parentObject():
parentVar = 1
# Create Child
x = childObject()
class childObject():
#Assign Var to the Var of the childs parent
childVar = parent.parentVar
>>> x.childVar = 1
is there a straitforward way to do this?
UPDATE:
I don't want to inheret the class, I need to be able to access the actual object that created it, as each object created from that class has different values.
Why not inherit the class?
class parentObject():
parentVar = 1
class childObject(parentObject):
childVar = parentObject.parentVar
>>> x = childObject()
>>> print(x.childVar)
1
If you are going to have different instances of the class, you should do it as this instead:
class parentObject(object):
def __init__(self):
self.parentVar = 1
class childObject(parentObject):
def __init__(self):
super(childObject, self).__init__()
self.childVar = self.parentVar
>>> x = childObject()
>>> print(x.childVar)
1
If you want a reference to the "parent" class, but inheritance is illogical, consider sending self in to the constructor:
class Room:
def __init__(self, name):
self.name = name
self.furniture = []
def add_chair(self):
self.furniture.append(Chair(self))
def __str__(self):
return '{} with {}'.format(self.name, self.furniture)
class Chair:
def __init__(self, room):
self.room = room
def __str__(self):
return 'Chair in {}'.format(self.room.name)
r = Room('Kitchen')
r.add_chair()
r.add_chair()
print r
print r.furniture[0]
Output:
Kitchen with [<__main__.Chair instance at 0x01F45F58>, <__main__.Chair instance at 0x01F45F80>]
Chair in Kitchen

Adding elements to a set , adds elements to all the instances of the object containing this set

Hi
I have created a List of Objects. Each object contains a Set. I want to update the set's contents for all the objects in the list. The code that i wrote to accomplish this is
class Player:
name = ""
cardsInHand = set()
hasBid = False
def __init__(self, name):
self.name = name
class CardDeck:
deck = []
def __init__(self):
for i in range(39) :
if i%10>0 and i%10<9 :
self.deck.append(i)
def dealCards(self,player):
cardIndex = 0
for tempPlayer in player:
for j in range(4): # since want to add four elements at a time
tempPlayer.cardsInHand.add(self.deck.pop(cardIndex))
cardIndex = cardIndex +1
in the main method I am calling the above classes with the following code
players = []
players.append(Player("Player0"))
players.append(Player("Player1"))
players.append(Player("Player2"))
players.append(Player("Player3"))
cards.dealCards(players)
The problem is that dealCards method adds the elements to all the sets of objects. Instead of 4 elements in each object's set, I endup with same 16 elements in each objects's set?
I am new to python, am i doing something wrong ?
You're creating class attributes.
class Player:
def __init__(self, name):
self.name = name
self.cardsInHand = set()
self.hasBid = False
You've defined cardsInHand (as well as name and hasBid) to be class variables instead of instance variables; by defining them in the class body, you're defining them to be variables shared by all instances. If you're familiar with Java, they are essentially like static variables. To make them instance variables, you need to declare them in the __init__ method, like so:
def __init__(self, name):
self.name = name
self.hasBid = False
self.cardsInHand = set()

Categories

Resources