This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 5 years ago.
I have a simple class with a string and a dictionary. When I make multiple objects of the class, apparently the dictionary does not get initialized properly. Dictionaries of all objects contains the entry for last object created. The code is:
# a simple class with a string and a dictionary:
class Myclass:
name = ""
valuedict = {}
# a list for objects:
mylist = []
# create 3 objects:
for i in range(3):
mc = Myclass()
mc.name = str(i)
mc.valuedict['name'] = str(i)
mylist.append(mc)
# disply objects in list:
for item in mylist:
print("-----------------")
print("name = ", item.name)
print("name in dict = ", item.valuedict['name'])
The output is:
-----------------
name = 0
name in dict = 2
-----------------
name = 1
name in dict = 2
-----------------
name = 2
name in dict = 2
The name strings are 0, 1 and 2 as expected but name in dictionary is 2 in all 3 objects. Where is the problem and how can it be solved? Thanks for your help.
Currently, valuedict is a class object. I believe what you're going for is to have separate instances, in which case you'll need a constructor (called __init__ in Python).
The corrected class code is as follows (self refers to the instance of the class)
class Myclass:
def __init__(self):
self.name = ""
self.valuedict = {}
So why isn't name acting the same way? In the first for loop, you're defining name, where you're accessing a key of valuedict, which doesn't exist, so you take the "next best thing", the class variable. name doesn't have this problem, as you're initializing it. A better explanation of this can be found here.
Related
This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 11 months ago.
My plan is to allocate 100 Participants with random attributes to a class.
What is the best way to do that without having to declare them one by one like this:
p1 = Participant()
p2 = Participant()
p3 = Participant() etc.
Class definition:
import names
import random
status_list = ["single", "married", "widowed", "complicated"]
class Paricipant():
def __init__(self, name= None, age = None, status = None):
if name is None:
self.name = names.get_first_name()
if age is None:
self.age = random.randint(22, 50)
if status is None:
self.status = random.choice(status_list)
def return_all(self):
print(self.name)
print(self.age)
print(self.status)
You can store them in a list. There are two ways to create the list:
First, you can use a list comprehension:
participants = [Paricipant() for _ in range(100)]
Alternatively, if you don't like list comprehensions, you can use a for loop instead:
participants = []
for _ in range(100):
participants.append(Paricipant())
I also think you misspelled "Participant" (the class name is currently "Paricipant").
This question already has answers here:
Is there a built-in function to print all the current properties and values of an object?
(30 answers)
Closed 1 year ago.
I have this simple Python code
class Person:
name = ""
surname = ""
age = ""
def __init__(self):
arr = #I want something like this ['name', 'surname', 'age']
How do I achieve putting that variables in order that I want (['name', 'surname', 'age']) to array? Without "initializing" them first with "self"? Thanks.
Edit: I need them in exact order how I defined them, not alphabetical order.
Maybe something like the below with __dict__:
class Person:
name = ""
surname = ""
age = ""
def __init__(self):
arr = [attr for attr in Person.__dict__ if ('_' not in attr) & (not callable(getattr(Person, attr)))]
print(arr)
Person()
Output:
['name', 'surname', 'age']
This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 1 year ago.
I'm currently learning Python in OOP,
I have a question about using list as a class attribute. The question is when I change something in objects it will also change that class attribute.
class Backet:
number_of_stone = 0
stone_collection = []
def __init__(self,name):
self.name = name
self.number_of_stone +=1
self.stone_collection.append(self.name)
stone_one = Backet('One')
stone_two = Backet('Two')
When I print out the stone_one and stone_two.number_of_two they are = 1 (I know this is correct). But when I print stone_one and stone_two.stone_collection they both give a list ["One","Two"].
My question is that should it be stone_one.stone_collection = ['One'] and stone_two.stone_collection = ['Two']
Change stone_collection to instance variable:
class Backet:
def __init__(self, name):
number_of_stone = 0
stone_collection = []
self.name = name
self.number_of_stone +=1
self.stone_collection.append(self.name)
stone_one = Backet('One')
stone_two = Backet('Two')
I have started learning Object Oriented concepts in python. I have got this sample code below:
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
class School(object):
students = []
def __init__(self, name):
self.name = name
def add_student(self, student):
self.students.append(student)
def show_students(self):
print("{0} Student Roster".format(self.name))
for s in self.students:
print("{0}: {1}".format(s.name, s.age))
my_school = School("Quora University")
first_student = Student("Rongan Li", 20)
second_student = Student("Jason Kane", 20)
my_school.add_student(first_student)
my_school.add_student(second_student)
my_school.show_students()
Question:
In the def show_students method of School class how they are accessing the construct variables of class student without instance of that class?
first_student = Student("Rongan Li", 20)
second_student = Student("Jason Kane", 20)
These lines create object of student class ,first_student which has name 'Rongan Li' and age '20'.
second_student which has name 'Jason Kane' and age '20'
Now, you add these 2 objects to the list.
my_school.add_student(first_student)
my_school.add_student(second_student)
Now, when you iterate in the list
for s in self.students:
print("{0}: {1}".format(s.name, s.age))
's' goes to first element of list, and since it is an object of class Student , 's' becomes object of student class. Now, since 's' is first element in the list and on first place you added 'Rongal Li' and 20 . So, s has 2 properties name and age. When you do s.name , it prints 'Rongal Li' and s.age prints 20
Then it goes to next element and same process is repeated.
in the method show_students there's a for loop :
for s in self.students:
print("{0}: {1}".format(s.name, s.age))
it loops over the list of students added by method add so inside the loop the variable "s" represent an instance of student class so s.name is a legit way of accessing an instance variable by using an instance of the class
The students are added to School.students list via the add_student method.
my_school.add_student(first_student)
my_school.add_student(second_student)
These two lines add two references to the School.students list in my_school. So now the list has two references pointing at first_student and second_student.
You can think of the list in my_school at this point as
students = [Pointer to first_student, Pointer to second_student]
When you call my_school.show_students(), my_school.students list (the list above) is accessed and through the references to first_student and second_student in the list, you access the original first_student object and second_student object and can then retrieve their properties.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
“Least Astonishment” in Python: The Mutable Default Argument
dictionary shared between objects for no reason?
class Player():
zones = {}
def __init__(self):
self.zones['hand'] = []
def InitHand(self):
for a in range(5):
self.zones['hand'].append(a)
lst = []
lst.append(Player())
lst.append(Player())
lst[0].InitHand()
print lst[1].zones['hand']
This prints "[0, 1, 2, 3, 4]", but I only initialized the 0th element...
Changing them to arrays as below fixes the problem, but for the life of me I can't figure out why this happens.
class Player2():
zones = []
def __init__(self):
self.zones = []
def InitHand(self):
for a in range(5):
self.zones.append(a)
lst = []
lst.append(Player2())
lst.append(Player2())
lst[0].InitHand()
print lst[1].zones
This prints "[]" as expected
In your code, all players share the same zones dictionary. Anything set in the class scope is a class attribute, not an instance attribute.
class Player():
def __init__(self):
self.zones = {}
self.zones['hand'] = []
def InitHand(self):
for a in range(5):
self.zones['hand'].append(a)