This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 3 years ago.
Hello Just curious on why the second instance already gets the category that was added in the first instance creation. How can i fix it?
class Game_record:
category = []
def __init__(self,name):
self.name = name
def add_category(self, cat):
self.category.append(cat)
def reset_cat(self):
self.category = []
def ret_cat(self):
return self.category
game = ["a","b"]
for each in game:
g = Game_record( each )
g.add_category("kol")
g.add_category("bol")
print(g.ret_cat())
g.reset_cat()
print(g.ret_cat())
output
['kol', 'bol']
[]
['kol', 'bol', 'kol', 'bol']
[]
To fix it declare category in __init__(), e.g.:
class Game_record:
def __init__(self,name):
self.name = name
self.category = []
...
The reason why you observe that behavior is that if you declare category right after the class, it becomes a class-level attribute rather than an object-level attribute.
Related
This question already has an answer here:
How to use class name in class scope?
(1 answer)
Closed 3 years ago.
I'm trying to run a class named person. The error is name 'person' is not defined. How can I solve this problem?
class person:
person.count = 0
def __init__(self,gender,location,DOB):
# this is constructor method
self.__gender = gender
self.__location = location
self.__DOB = DOB
# to make the variable inaccessible from out of the class
# we have to prefix it with at least two underscores
print(person.__self)
print(person.__DOB)
person.count += 1
def getname(self):
#this is access method
return person.__self
def getDOB(self):
return person.__DOB
def _del_(self):
print('deleted')
First of all, put the line person.count = 0 inside __init__. Next, change every person to self (unless it's the class definition).
This question already has answers here:
Python - Classes and OOP Basics
(6 answers)
Closed 5 years ago.
Could anyone help with my understanding, please? I don't understand what is happening with this line or why it works : course_running.add_student(self).
I thought this was an OOP concept but could anyone help make this clearer?
class Student:
def __init__(self, name, student_number):
self.name = name
self.student_number = student_number
self.classes = []
def enrol(self, course_running):
self.classes.append(course_running)
course_running.add_student(self)
class CourseRunning:
def __init__(self, course, year):
self.course = course
self.year = year
self.students = []
def add_student(self, student):
self.students.append(student)
course_running is an object of class CourseRunning and course_running.add_student(self) is calling a method of it's class named add_student which is appending the student to students list.
Your enrol() function in the Student class is taking two parameters: self and course_running.
self is the instance of your current class (Student).
That's why in your add_student() function (which takes also two parameters: self (the current instance of the CourseRunning class) and student (which is simply an instance of a Student)).
That's why you can pass the self from enrol() as student in add_student().
This question already has answers here:
Getting the name of a variable as a string
(32 answers)
Closed 6 years ago.
Is there a way to get the name under which a variable or a property is stored?
Something like:
class X:
def __init__(self):
self.name = __name_under_which_I_m_stored__
jeff = X()
print(jeff.name) # yields 'jeff'
Pretty sure that this is not possible, but you never know... Furthermore, I'm aware that the name could be unspecified (do_something(X())) or ambiguous (jeff=frank=X()).
The Python VM has no way to know the literal name of a name. For objects, you can access the name via __name__ attribute.
If you want to do this, you'll need to implement a mapping of names to values. You can do this with a dict.
class X:
def __init__(self):
self.names = {};
def set(self, name, value):
self.names[name] = value
def get(self, name):
return (name, self.names[value])
jeff = X()
jeff.set("name", "jeff");
print(jeff.get("name")) # yields ("name", "jeff")
This question already has answers here:
Printing all instances of a class
(8 answers)
Closed 9 years ago.
I've been messing around in Python for about a month and a half at this point, and I was wondering: is there a way to print the values of one class variables for all objects in that class? e.g. (I was working on a mini-game kinda thing):
class potions:
def __init__(self, name, attribute, harmstat, cost):
self.name = name
self.attribute = attribute
self.harmstat = harmstat
self.cost = cost
Lightning = potions("Lightning Potion", "Fire", 15, 40.00)
Freeze = potions("Freezing Potion", "Ice", 20, 45.00)
I'd like to be able to print a list of all the names of the potions, but I couldn't find a way to do that.
If you have a list of all the potions it's simple:
potion_names = [p.name for p in list_of_potions]
If you don't have such a list, it is not so simple; you are better off maintaining such a list by adding potions to a list, or better still, a dictionary, explicitly.
You could use a dictionary to add potions to when creating instances of potions:
all_potions = {}
class potions:
def __init__(self, name, attribute, harmstat, cost):
self.name = name
self.attribute = attribute
self.harmstat = harmstat
self.cost = cost
all_potions[self.name] = self
Now you can always find all names:
all_potion_names = all_potions.keys()
and also look up potions by name:
all_potions['Freezing Potion']
You can use the garbage collector.
import gc
print [obj.name for obj in gc.get_objects() if isinstance(obj, potions)]
You could use a class attribute to hold references to all Potion instances:
class Potion(object):
all_potions = []
def __init__(self, name, attribute, harmstat, cost):
self.name = name
self.attribute = attribute
self.harmstat = harmstat
self.cost = cost
Potion.all_potions.append(self)
Then you can always access all the instances:
for potion in Potion.all_potions:
This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 9 years ago.
I can create class definition dynamically, like there:
class_name = 'Human'
base_classes = (object,)
attributes = {'name':'',
'books':list(),
'say_hello':lambda self: sys.stdout.write('Hello!')}
Human = type(class_name, base_classes, attributes)
uzumaxy = Human()
uzumaxy.name = 'Maxim'
uzumaxy.books.append('Programming via .NET')
print(uzumaxy.name) # Out: "Maxim"
print(uzumaxy.books) # Out: "['Programming via .NET']"
grandrey = Human()
grandrey.name = 'Andrey'
grandrey.books.append('Programming via python')
print(grandrey.name) # Out: "Andrey"
print(uzumaxy.name) # Out: "Maxim"
print(grandrey.books) # Out: "['Programming via .NET', 'Programming via python']"
print(uzumaxy.books) # Out: "['Programming via .NET', 'Programming via python']", but i'm expecting: "['Programming via .NET']"
Seems, attribute "name" is instance-level, but why attribute "books" is class-level?
How I can dynamically create definition of type with instance-level attributes? Thx for help.
Actually, both name and books are class-level. It's just that strings are immutable, so when you use uzumaxy.name = "Maxim", you're adding a new attribute called name hiding the class name, while for uzumaxy.books.append("Programming via .NET"), you're accessing the existing (class) books and modifying it. Your code is equivalent to this:
class Human(object):
name = ''
books = []
def say_hello(self):
sys.stdout.write("Hello!")
Note the same behavior. Traditionally, we'd fix that by writing Human like this:
class Human(object):
def __init__(self):
self.name = ''
self.books = []
def say_hello(self):
sys.stdout.write("Hello!")
Now each instance has its own name and books. To do this with a dynamically-created type, you do essentially the same thing, giving it an __init__:
def init_human(self):
self.name = ''
self.books = []
attributes = { '__init__': init_human,
'say_hello': lambda self: sys.stdout.write("Hello!") }
They're both class-level. name is simply immutable, so it doesn't look class-level at first glance. Most attempts to modify it will create a new instance-level attribute with the same name.
Just like when writing a class the normal way, you need to create instance attributes in the constructor:
def __init__(self):
self.name = ''
self.books = []
def say_hello(self):
# This prints a newline. The original didn't.
print 'Hello!'
Human = type('Human', (object,), {
'__init__': __init__,
'say_hello': say_hello,
})