class Person:
number_of_people = 0 #class atribute,define for the entire class
def __init__(self,name):
self.name=name
p1 = Person('tim') # adding of object to class
p2 = Person('jill')
p3 = Person('Bill')
for x in range(Person.number_of_people): #will loop 3 time this case
print(Person.name) # how do i print all the names in a class
i cant seem to get this working
You would need a global variable to keep track of each instance this way, but more likely you would define a parent class, like People, and then have your Person class inherit from People. People would instead be in charge of tracking how many Person instances you've created. The latter option would be best if you have to look at more than just this one relationship between your Person instances. If you wanted to iterate through your Persons, for example, that could be a methods of your People class.
You could initialize a variable NUMBER_OF_PEOPLE=0 outside your class declaration and then each time someone call __init__ you can add one:
class Person:
# Declare class variables
NUMBER_OF_PEOPLE = 0
LIST_OF_PEOPLE = []
def __init__(self, name):
self.name = name
# Change the class variables
Person.LIST_OF_PEOPLE.append(self)
Person.NUMBER_OF_PEOPLE += 1
#classmethod
def get_number_of_people(cls):
return Person.NUMBER_OF_PEOPLE
p1 = Person("tim")
p2 = Person("jill")
people = [p1, p2] # create a list o two people
# Iterate through the list
for p in Person.LIST_OF_PEOPLE:
# Access the name by calling p.name
print("Name of the current person is: {}.".format(p.name))
# You can still access the NUMBER_OF_PEOPLE variable either by calling Person.get_number_of_people() (since it is a class method)
# or by simply using the NUMBER_OF_PEOPLE variable.
print("Currently, there are {} number of people in the class!".format(Person.get_number_of_people()))
# This will give 1 person.
Your issue here is that you don't completely understand object-oriented programming. You will get better by practising.
Related
(I'm fairly new to programming, so understand that my query might not make sense. I've tried my best to explain it but if you are still confused, you can ask me to clarify)
I understand the that we can call the class attribute number_of_people and increment by one so that when we create a new instance (in this context, a person), the number of people increases by one:
class Person:
# Class attribute
number_of_people = 0
# Constructor
def __init__(self, name):
self.name = name
# Every time we call the constructor, we increment the number of people.
Person.number_of_people += 1
# Driver code
p1 = Person("Jack")
print(Person.number_of_people)
# output gives 1
However, I'm having trouble with understanding the output of the code when we change the we choose to increment p1.number_of_people instead of Person.numer_of_people:
class Person:
# Class attribute
number_of_people = 0
# Constructor
def __init__(self, name):
self.name = name
# Every time we call the constructor, we increment the number of people.
p1.number_of_people += 1
# Driver code
p1 = Person("Jack")
print(p1.number_of_people)
# output gives 0 (I expected the output to be 1)
I thought that since class attributes can be accessed by both the class and instances, my change wouldn't make a difference. I suspect it has to do with p1 being mentioned in the class before it's mentioned in the driver code, but I'm not sure where to go from there.
I suspect the demonstration you were trying to do for yourself is to examine the difference between using the class attribute as a class attribute, vs as an instance attribute. Consider this difference:
class Person:
population = 0
def __init__(self,name):
self.name = name
Person.population += 1
p1 = Person("Jack")
p2 = Person("Tom")
p3 = Person("Bill")
print(p1.population)
print(p2.population)
print(p3.population)
Output:
3
3
3
Compared to:
class Person:
population = 0
def __init__(self,name):
self.name = name
self.population += 1
p1 = Person("Jack")
p2 = Person("Tom")
p3 = Person("Bill")
print(p1.population)
print(p2.population)
print(p3.population)
Output:
1
1
1
In the second example, the instance starts out using the class attribute, but as soon we change it, it creates an instance attribute that has a separate life.
I want to initialize variables with default values in a constructor without parameters, like this:
class Persons()
def __init__(self):
self.name="Joan"
p1=Persons()
print(p1.name)
So the result for this, will be "Joan". It will print the name of the person. All good. But how do I do this for multiple objects? I want to print p2.name, p3.name, with different names, just like above.
I got this from an exercise that asks me to "create a constructor without parameters that initializes variables with default data".
Just add name as a parameter:
class Persons()
def __init__(self, name):
self.name = name
p1=Persons(“Joan”)
print(p1.name)
Or
p1.name = “Jim”
If your class can provide a set of possible names, you can create an object from which each call to Person.__init__ gets a different name. For example:
from itertools import cycle
class Person:
names = cycle(["Alice", "Bob", "Carol", "Dan"])
def __init__(self):
self.name = next(Person.names)
Add as many names to the pool as desired.
Names will necessarily repeat once the initial set of names is exhausted and the cycle begins again. With a little more work, we can at least vary the order in which names are produced on each cycle:
from itertools import cycle
import random
class Person:
def shuffled_cycle(names):
while True:
random.shuffle(names)
yield from names
names = shuffled_cycle(["Alice", "Bob", "Carol", "Dan"])
def __init__(self):
self.name = next(Person.names)
Of course, if repeated names aren't a concern, just call random.choice from inside __init__. This is much simpler:
import random
class Person:
def __init__(self):
self.name = random.choice(["Alice", "Bob", "Carol", "Dan"])
Taken to its extreme, just generate random names from a primordial soup of letters:
import random
import string
class Person:
def __init__(self):
k = random.randint(3, 10)
self.name = ''.join(random.sample(string.ascii_lowercase, k)).title()
So the thing is you want to initialize with default values, The code you wrote is correct.Every new instance of "Person" class will initialize with the same default value which is good coding practice.Since it is "default" value thus same. However for the sake of knowledge I have written a small program that can give new names to 5 new instances of class Person however do not use this in production as it is a bad practice but good for learning.
class Person :
#class Variable
name_list=["Jhon","Naruto","James","Smith","Neo"]
instance_count = 0
def __init__(self):
#Resets instance count when instances become greater that 5
instance_count = instance_count%5
#Sets new name
self.name = name_list[instance_count]
#increment instance_count
instance_count = instance_count + 1
I want to create a parent object which creates its children and its children need to have access to one of the parent attributes.
I have found ways to create children inside a parent and ways to have access to one of the parent attributes, but no way to do both at the same time.
class Parent():
def __init__(self,number):
self.number = number
self.children = [Child(0), Child(2)]
class Child(Parent):
def __init__(self, number2):
self.number2 = number2
def printNumber(self):
print(self.number+self.number2)
I expect:
par = Parent(3)
par.children[0].printNumber()
<3>
par.children[1].printNumber()
<5>
But, this will crash because par.children[0].number does not exist.
Ok, I have to say that this does not seem an appropriate use of inheritance. Inheritance should be used to provide a multiple set of attributes and methods to different classes with things in common. Calling a child from a parent on initialization seems, a bit doubtful.
Still, I'm guessing there is a wider reason for this than this example. As such, I can offer a solution that does not require Child to use super() (as specified in the comments).
This solution has a caveat, though, and a big one. self.number becomes a class method and, as such, if a new Parent is instantiated with a diferent number value, it would change previously instantiated Parents.
So here it goes:
class Parent():
number = 0
def __init__(self, number):
self._change_number(number)
self.children = [Child(0), Child(2)]
#classmethod
def _change_number(cls, number):
cls.number = number
class Child(Parent):
def __init__(self, number2):
self.number2 = number2
def printNumber(self):
print(self.number+self.number2)
par = Parent(3)
par.children[0].printNumber()
# 3
par.children[1].printNumber()
# 5
Again be aware that number is a class variable!!. Then, continuing the script with:
pir = Parent(5) # Different instance
# changes the values in the previous instance par
par.children[0].printNumber()
# 5
par.children[1].printNumber()
# 7
I cannot see any other solution for this to work, as, without calling super from the Child there is no other way to initialize the self.number attribute if it is not a class one.
If you don't want this to happen, one option would be to calculate self.number2 at __init__ time. Then the value would be safely stored without more problem. In this case, Child would look like:
class Child(Parent):
def __init__(self, number2):
self.number2 = self.number+number2
def printNumber(self):
print(self.number2)
And a new instance would not affect the previous one:
par = Parent(3)
par.children[0].printNumber()
# 3
par.children[1].printNumber()
# 5
pir = Parent(5) # Different instance
# DOES NOT change the values in the previous instance par
par.children[0].printNumber()
# 3
par.children[1].printNumber()
# 5
my task is actually pretty simple. Maybe I'm too much used to c++ to not see my fault.
I have two classes and a list.
The list should include all objects made of class1, while class1 also includes a list for all objects of class2.
So we have:
All_Objects1 = [] # For class1 objects
class class1 (object):
All_Objects2 = [] # For class2 objects
class class2 (object):
name = ""
number = 0
Now I do this:
# class1 objects:
obj1= class1()
obj2= class1()
# class2 objects
obj3 = class2()
obj3.name, obj3.number = "hello world", 10
obj4 = class2()
obj4.name, obj3.number = "hello europe", 20
obj5 = class2()
obj5.name, obj3.number = "hello asia", 30
obj6 = class2()
obj6.name, obj3.number = "hello africa", 40
# Attach object3 and object4 to object1
obj1.All_Objects2.append(obj3)
obj1.All_Objects2.append(obj4)
# Attach object5 and object6 to object2
obj2.All_Objects2.append(obj5)
obj2.All_Objects2.append(obj6)
# Attach obj1 and obj2 to the global list.
All_Objects1.append(obj1)
All_Objects1.append(obj2)
And finally I do a print for checking if everything is where it belongs:
print (len(All_Objects1[0].All_Objects2)) # Should be 2.
for i in All_Objects1[0].All_Objects2:
print (i.name) # Should be world and europe.
print (len(All_Objects1[1].All_Objects2)) # Should be 2.
for i in All_Objects1[1].All_Objects2: # Should be asia, africa.
print (i.name)
Now the problem is, that every object2 is in every object1 and I have no clue why.
In my actual program I do something like this, what would actually work in c++:
#pseudo
for i in all_information:
if (i==Keyword):
currentObject = class1()
All_objects.append(currentObject)
And then I will have some independent objects in my list. But in Python I think I somehow can't overwrite "currentObject".
Thank you so much for your help.
In Python somethings could be making this error, first which version×of Python are you using?
I have not tested on my console yet but I would guess that it's a initialization issue, for how you are declaring the list, I would rather suggest to use a more Pythonic approach, I mean, build a constructor and use keyword self for instance variables, if this works, I can extend my answer explaining why this happened.
Create a method like this in class 1 and class 2:
def __init__(self, object_list=None) : # use corresponding classes attributes.
if self.name_of_your_variable:
self.name_of_your_variable= [] # or proper value
Adapt this to your classes and let me know, if it works, as soon I get home I'll extend it
With Python, all class members declared outside any function are static members. So they are shared by each object instantiated from the class.
What you want is the following:
class class1 (object):
def __init__(self):
self.All_Objects2 = [] # For class2 objects
class class2 (object):
def __init__(self):
self.name = ""
self.number = 0
You need just to initialized your class. init and you need only one All objects list. An example with class you can find below.
class firstA():
def __init__(self):
self.All_Objects = []
class secondB():
def __init__(self):
self.name ="None"
self.number = 0
When you are calling the class the initialization will be done :-) That is very nice in python2/3.
Whatever you initialized outside the class will be considered as a static variable! So in your example the All_Objects1 list for instance.
Hope this clarify your doubts! Have a nice day.
So I have this code:
class vehicle(object):
def __init__(self):
self.age = 6
self.make = 8
self.colour = 'colour'
self.cost = 'cost'
class car(vehicle):
def __init__(self):
vehicle.__init__(self)
self.type = 'car'
car1 = car()
print car1.make, car1.colour, car1.cost, car1.type, car1.age
n = raw_input()
dic = {'name' : n}
dic['name'] = car()
print dic['name'].make
In the last bit, I was able to resolve a previous issue I had: Creating an instance of the car class with its name being one that the user inputs in n
Now, say I wanna ask the user to input a name and now I have to find the class' instance that has that name.
For example if at one point an instance with the name car2 was created. Now user wants to get info about car2 and inputs 'car2'. how can I use this input to access attributes of the instance called car2?
I tried:
a = raw_input()
dic['fetch'] = a
dic['fetch'].make
does not work.
It seems to me you have a fair bit of misunderstanding. The way you're assigning the input into the dictionary doesn't make sense. Your description indicates that you want a dictionary that maps a "name" to a car description.
Your initial creation of the dictionary is off. The way you're currently doing it, you're actually losing the name the user inputs when you assign the car data. Some better variable naming might help you. Create your dictionary like this:
cars_by_name = dict()
name = raw_input()
cars_by_name[name] = car()
So now you have a name (given by the user) that maps to a car description.
Now you need to fetch that same car instance again. You do it by using the name as the key in the dictionary:
name2 = raw_input()
print cars_by_name[name2].make
Next, let's look at your classes. My first question: why do you need a vehicle and a car class? If you're never going to have classes other than car inheriting from vehicle, you don't really need them both. Even if you do plan the have more subclasses, I would probably still recommend against inheritance here. Your vehicle has no behavior (methods) for subclasses to inherit. It's just a data object. With duck typing so strongly encouraged in Python, inheriting from a class with no methods doesn't buy you anything. (What a base class would buy you with methods is that you'd only have to define the method in one place, making it easier to modify later on.) Particularly in your case, there doesn't seem to be any motivation to create a subclass at all. A single class for all vehicles will work just fine. So let's simplify your classes:
class Vehicle(object):
def __init__(self):
self.age = 6
self.make = 8
self.colour = 'colour'
self.cost = 'cost'
self.type = 'car'
(Also, note that class names are usually given in camel case in Python.) Now there's one more problem here: those constants. Not all Vehicles are going to have those same values; in fact, most won't. So lets make them arguments to the initializer:
class Vehicle(object):
def __init__(self, age, make, colour, cost, type):
self.age = age
self.make = make
self.colour = colour
self.cost = cost
self.type = type
Then you create one like this:
v = Vehicle(6, 8, 'colour', 'cost', 'car')
Good luck in your endeavors learning. Hope this helps.
If I understand you correctly and you want to map string names to instances:
n = raw_input()
dic = {n: car()}
print dic[n].make
print(dic)
dic[n].cost = 10000
print(dic[n].cost)
Another option would be to take a name for each car instance and have a class attribute dict mapping names to self.
In [13]: paste
class vehicle(object):
def __init__(self):
self.age = 6
self.make = 8
self.colour = 'colour'
self.cost = 'cost'
class car(vehicle):
dic = {}
def __init__(self, name):
vehicle.__init__(self)
car.dic = {name: self}
self.type = 'car'
self.name=name
car1 = car("car1")
car2 = car("car2")
car2.colour="blue"
print car1.make, car1.colour, car1.cost, car1.type, car1.age
n = raw_input()
print car.dic[n]
print car.dic[n].make
print car.dic[n].colour
## -- End pasted text --
8 colour cost car 6
car2
<__main__.car object at 0x7f823cd34490>
8
blue