Accessing a class instance's attributes using user input - python

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

Related

How to count total number of person in a class

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.

Python initialize variables with default data for multiple objects

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

python pass object or instantiate from within second object

I wondered if its better to:
Pass Object1 into Object2 for use
or
Instantiate Object1 from Object2
I could do either, but I am wondering what is better practice, or where i could get caught up.
These are rather rudimentary examples, and of course in the second example, i could just use the list. The actual code I am using, i need to use a lot of Object1 values to do things in Object2.
Example 1:
class Object1:
def __init__(self, person):
self.id = person[0]
self.name = person[1]
self.age = person[2]
class Object2:
def __init__(self, object1):
self.object1 = object1
retirement_age = self.object1.age + 25
print(self.object1.id)
print(self.object1.name)
print(retirement_age)
person = [1, 'Ryan', 30]
o = Object1(person)
r = Object2(o)
Example 2:
class Object1:
def __init__(self, person):
self.id = person[0]
self.name = person[1]
self.age = person[2]
class Object2:
def __init__(self, person):
self.o = Object1(person)
retirement_age = self.o.age + 25
print(self.o.id)
print(self.o.name)
print(retirement_age)
person = [1, 'Ryan', 30]
r = Object2(person)
Well, it depends, and only you can decide.
In the first example, you can use o in many places throughout your program without creating the same object over and over again (just make sure you are not modifying it anywhere, see below why).
The second option encapsulates the fact that Object1 even exists.
You need to ask yourself a few questions:
Will you use Object1 instances anywhere else in the code base? Does it even make sense to have a "standalone" Object1 instance outside of Object2 instance?
Does Object2 need to know about Object1? Does it need to know how to construct it? should it even care?
Can Object2 instances simply contain the attributes of Object1 directly? If the answer is 'yes' then Object1 is redundant.
You have to be very careful with option 1.
If the object you pass through to Object2 is modified anywhere, the changes will affect all of the corresponding Object2 instances.
class Object1:
def __init__(self, person):
self.id = person[0]
self.name = person[1]
self.age = person[2]
class Object2:
def __init__(self, object1):
self.object1 = object1
retirement_age = self.object1.age + 25
print(self.object1.id)
print(self.object1.name)
print(retirement_age)
person = [1, 'Ryan', 30]
o = Object1(person)
r = Object2(o)
# modifying o.name will affect r.object1.name as well
o.name = 'John'
print(r.object1.name)
# 1
# Ryan
# 55
# John
It depends on the context.
You could use the first method as Object2 doesn't need any information about how to construct an Object1.
On the other hand, if you needed to use person in Object2, you should use the second method as it would be easier to use person instead of self.object1.id, especially if you had to use person many times.

Unintuitive output given by classes in Python

So I've got this class:
class Student(object):
def __init__(self, studentID, name):
self.__studentID = studentID
self.__name = name
def set_studentID(self, value):
self.__studentID = value
def get_name(self):
return self.__name
and running this code:
x = Student
x.set_name(x, input("Name: "))
x.set_studentID(x, len(students))
students.append(copy.deepcopy(x))
x.set_name(x, input("Name: "))
x.set_studentID(x, len(students))
students.append(copy.deepcopy(x))
for i in (students):
print(i.get_name(i))
gives an unexpected output:
For the input:
a
b
the output is:
b
b
The expected output is:
a
b
If you answer please give me a short explanation of why it doesn't work
The reason your code isn't working is because you never instantiate your class, instead, you assign the class object itself to the name x
x = Student
When you really needed
x = Student()
Then you call the methods on the class object, whilst passing the class object itself as the first parameter, thus your getters and setters act on the class object.
Finally, classes are meant to be singletons, and the copy module special cases them. So if x is a class
copy.deepcopy(x) is x
Is always True, thus you never actually make a copy.
As a side note, your class definition looks like it was written by a Java developer using Python for the first time. The Pythonic way to do it is not to use getters and setters use properties, and only when you need to. Also, don't use double-underscores name-mangling unless you actually want that, which in this case, you dont.
The other answer explains why your code doesn't work as you expect it to. Here's how you could rewrite your code in a more pythonic way.
class Student(object):
def __init__(self, studentID, name):
self.studentID = studentID
self.name = name
students = []
name = input("Name: ")
students.append(Student(len(students), name))
name = input("Name: ")
students.append(Student(len(students), name))
for student in students:
print(student.name)
You don't need to write getter and setter methods unless you have to do some special processing.

Printing Attributes of Objects in a Class in Python [duplicate]

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:

Categories

Resources