This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 4 years ago.
I tried to create two objects that both have their own inventories.
As far as I'm concerned I successfully managed to create two different objects called my_bag and toms_bag
This is the code I used
class bag(object):
def inventory_add(self, item):
self.inventory.append(item)
inventory = []
bags = [] #List of all bags
#Create bags
my_bag = bag()
my_bag.inventory_add("pencil")
bags.append(my_bag)
toms_bag = bag()
toms_bag.inventory_add("book")
bags.append(toms_bag)
for bag in bags: #Print inventories
print(bag, bag.inventory)
This is the result I get.
<__main__.bag object at 0x004D0830> ['pencil', 'book']
<__main__.bag object at 0x004D0790> ['pencil', 'book']
So why are the items added to both of their inventories? Are they even different objects now?
Your syntax looks like you're coming from C#, Java, C++, or some other more strictly OOP language. The way to do what you want in Python is to initialize the inventory array in the class constructor:
class bag(object):
def __init__(self):
self.inventory = []
def inventory_add(self, item):
self.inventory.append(item)
Related
This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 3 years ago.
I am trying to understand something in Python.
When I have a property that I want shared across all subclasses, I place it in the parent class. I was expecting that the actual value of this property would be unique for each object instance. However, if this property is iterable and I modify it in one object, the change is made for all other instantiated objects.
class Animal:
sounds = []
def add_sounds(self, sound):
return self.sounds.append(sound)
class Cat(Animal):
pass
class Dog(Animal):
pass
cat = Cat()
cat.add_sounds('meow')
dog = Dog()
dog.add_sounds('bark')
print('The cat says: ' + str(cat.sounds))
print('The dog says: ' + str(dog.sounds))
This gives:
The cat says: ['meow', 'bark']
The dog says: ['meow', 'bark']
... but I was expecting:
The cat says: ['meow']
The dog says: ['bark']
This doesn't seem to be the case for other variable types like strings or numbers. What am I missing? This is Python 3.7.3.
sounds is a class attribute shared by all instances. You want an instance attribute instead, which is best initialized in Animal.__init__.
class Animal:
def __init__(self):
self.sounds = []
def add_sounds(self, sound):
self.sounds.append(sound)
In your code, since sounds doesn't exist as an attribute on an individual instance of Animal, self.sounds resolves to Animal.sounds.
The difference you are observing with strings and numbers is the those types are immutable; you don't specify how you observe the difference, but here's an example:
x = 3
y = x
x += 1
assert y == 3
The += operator doesn't modify the existing int that both x and y refer to; it creates a new int object and makes x refer to that, leaving y as the sole reference to the previous int object.
This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Should I use instance or class attributes if there will only be one instance? [closed]
(4 answers)
Closed 7 years ago.
In Python 3, I have a list of classes, and each class has a list in it. I'm having difficulties updating those lists. As so:
class Item():
newPrice = 0
prices = [0]
def __init__(self, _prices):
self.prices = _prices
items = [Item([10]), Item([20]), Item([30])]
for item in items:
item.newPrice = SomeFunction()
item.prices.append(item.newPrice)
The function SomeFunction() is an elaborate function that retrieves a different value for each Item instance.
For some reason, each Item instance in the items list has the same value for prices, which is a list that contains the newPrice value for each Item instance. I hope this is clear enough.
What am I missing?
You should define prices as instance attribute, instead of class attribute, because class attributes are shared between all instances:
class Item():
def __init__(self, _prices):
self.newPrice = 0
self.price = _prices
This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 7 years ago.
I'm new to Python and I've searched for an answer but can't find one. Maybe I'm just asking it the wrong way...
As an example, if I have a class as follows:
class Person(object):
def __init__(self, name):
self.name = name
I create a couple instances as follows and can get their attributes like this:
person1 = Person("John")
person2 = Person("Mike")
print person1.name
print person2.name
What I want to do is substitute "personX" with a variable, and this is the part I haven't figured out yet. I'd like to to use this to iterate through a list of names that map to class instances and get/set their attributes.
name1 = "person1"
print "%s".name % (name1) <--- this fails with "AttributeError: 'str' object has no attribute 'name'
Whenever you want to create variableX where X is an incrementing number, you really want a list:
people = []
people.append(Person('John'))
people.append(Person('Mike'))
for person in people:
print person.name
print people[0].name
Use eval() to get instance referenced by the created string this way
name1 = "person1"
print eval(name1).name
Typically, this is considered bad practice, especially with the use of eval and exec to do so:
people = {'person1': Person('Bob'), 'person2': Person('Sam')}
This question already has answers here:
python: class attributes and instance attributes
(6 answers)
Closed 8 years ago.
I have a simple question:
Say that I have the following class:
class step:
alpha = []
and my main has the following:
listofstep = []
for i in range(20):
z = step()
z.alpha.append(0)
listofstep.append[z]
why does len(listofstep[0].alpha) gives me 20?
As you define it, alpha is a class variable and not an instance variable. When you do z.alpha it always points at the same list, regardless of which instance it is. Try to define step like this:
class step:
def __init__(self):
self.alpha = []
This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 9 years ago.
I have the following code:
import math
class h:
vektor = [0,0]
rel_chyba = 0
def __init__(self, hodnota, chyba):
self.vektor[0] = hodnota
self.vektor[1] = chyba
self.rel_chyba = chyba*1.0/hodnota
def __rmul__(self, hod2):
return h(hod2.vektor[0]*self.vektor[0], math.sqrt(self.rel_chyba*self.rel_chyba+hod2.rel_chyba*hod2.rel_chyba))
v = h(12,1)
print v.vektor[1]
t = h(25,2)
print v.vektor[1]
My problem is, that v.vektor[1] prints 1 for the first time and 2 for the second time. All the attributes of the object v are assigned the values of the attributes from t.
How can I create two different objects?
Thanks for your answers
Don't declare vektor at class level, that makes it a class variable. Just declare it inside __init__:
def __init__(self, hodnota, chyba):
self.vektor = [hodnota, chyba]