how to iterate list of objects - python

I have a list of objects. I would like to check some string if that string exists as a field value any object in the list. for example,
class Ani:
name = ''
def __init__(self, name):
self.name = name
def getName(self):
return self.name
animal1 = Ani('alica')
animal2 = Ani('rex')
animal3 = Ani('bobik')
animal4 = Ani('dobik')
animal5 = Ani('sobik')
a = [animal1, animal2, animal3,animal4,animal5]
my problem to write a code in order to see if there is an object with given name. for example "chip".

You can iterate over the array of objects, and check with each object's getName function.
class Ani:
name = ''
def __init__(self, name):
self.name = name
def getName(self):
return self.name
animal1 = Ani('alica')
animal2 = Ani('rex')
animal3 = Ani('bobik')
animal4 = Ani('dobik')
animal5 = Ani('sobik')
animals = [animal1, animal2, animal3,animal4,animal5]
searched_animal = 'rex'
for animal in animals:
if animal.getName() == searched_animal:
print('Found')
break

You can use any plus a comprehension:
any(animal.getName() == "chip" for animal in animals)

Iterating a list containing anything is quite simple really. Like so:
animal_to_find = "someAnimal"
for animal in animals:
if animal.getName() == animal_to_find:
print("Found a match for: " + animal)

You can use the getName method present in Ani class for this program
class Ani:
name = ''
def __init__(self, name):
self.name = name
def getName(self):
return self.name
animal1 = Ani('alica')
animal2 = Ani('rex')
animal3 = Ani('bobik')
animal4 = Ani('dobik')
animal5 = Ani('sobik')
animals = [animal1, animal2, animal3,animal4,animal5]
key = 'chip'
flag=0
for animal in animals:
if animal.getName() == key:
print('Found')
flag=1
break
if flag==0:
print("Not Found")

Related

print and sort a list of class in oop python

I have a class name Student like this:
class Student:
def __init__(self, name = '', age = 0, test_score = 0):
self.name = name
self.age = age
self.test_Scores = test_score
def __str__(self):
return "({0},{1},{2})".format(self.name,self.age, self.test_Scores)
and class name Students:
class Students():
stds = list()
def __init__(self) -> None:
pass
def Input(self):
while True:
inputName = input('Enter name: ')
inputAge = int(input('Enter age: '))
inputTestScore = int(input('Enter test score: '))
std = Student(inputName, inputAge, inputTestScore)
if inputAge == 0:
break
self.stds.append(std)
def __str__(self):
return str(self.stds)
Here are some code print out a list of students:
stds = Students()
stds.Input()
print(stds)
With 2 elements in the list, the result after excute look like this:
[<main.Student object at 0x0000026EDEBC5FA0>, <main.Student object at 0x0000026EDEBC5CD0>]
I can't print out stds under a string, how can i fix it. And how to sort stds by the decreasing of age ?
Pls help me !
You shouldn't have class Students, you should have a list of Student. To get the data from the class variables override the __repr__ method. To sort the list you can use lambda with the attribute to sort by as key in sort() function
class Student:
def __init__(self, name='', age=0, test_score=0):
self.name = name
self.age = age
self.test_Scores = test_score
def __repr__(self):
return "({0},{1},{2})".format(self.name, self.age, self.test_Scores)
if __name__ == '__main__':
stds = list()
while True:
inputName = input('Enter name: ')
inputAge = int(input('Enter age: '))
inputTestScore = int(input('Enter test score: '))
std = Student(inputName, inputAge, inputTestScore)
if inputAge == 0:
break
stds.append(std)
stds.sort(key=lambda s: s.name)
print(stds)
You need to write the function str for students class.
def __str__(self):
return '\n'.join(self.stds)
try this =>
class Student:
def __init__(self, name = '', age = 0, test_score = 0):
self.name = name
self.age = age
self.test_Scores = test_score
def __str__(self):
return "({0},{1},{2})".format(self.name,self.age, self.test_Scores)
def __repr__(self):
return "({0},{1},{2})".format(self.name,self.age, self.test_Scores)
def __lt__(self, other):
return self.age < other.age
class Students():
stds = list()
def __init__(self) -> None:
pass
def Input(self):
while True:
inputName = input('Enter name: ')
inputAge = int(input('Enter age: '))
inputTestScore = int(input('Enter test score: '))
std = Student(inputName, inputAge, inputTestScore)
if inputAge == 0:
break
self.stds.append(std)
def __str__(self):
return str(self.stds)
stds = Students()
stds.Input()
print(stds)
stds.stds.sort(reverse=True)
print(stds)
Define a natural order for the students based on their age using #functools.total_ordering:
import functools
#functools.total_ordering
class Student:
def __init__(self, name='', age=0, test_score=0):
self.name = name
self.age = age
self.test_Scores = test_score
def __lt__(self, other):
return self.age < other.age
def __str__(self):
return "({0},{1},{2})".format(self.name, self.age, self.test_Scores)
def test_sorting_students():
alice: Student = Student("Alice", 21, 86)
bob: Student = Student("Bob", 19, 75)
caroline: Student = Student("Caroline", 20, 93)
students = [alice, bob, caroline]
students.sort()
assert students[0] == bob
assert students[1] == caroline
assert students[2] == alice
Then just sort them:
print(stds.sort())

How can I print each item in an unknown length list that is a class attribute as a string in python?

I have a class (Student) with different attributes, such as studentId, address, and courses. My str method for the class returns all the information that the user put in. However, for the attributes that are lists, such as courses, the location of the information is printed out instead of the actual information. Here is the code (sorry it's a little long, there's a bunch of classes):
class Person:
__name = None
__age = None
__address = None
def __init__(self, name, age=0, address=None):
self.set_name(name)
self.set_age(age)
self.set_address(address)
def __str__(self):
return 'Name: ' + self.__name + '\n' + \
'Age: ' + str(self.__age) + '\n' + \
'Address: ' + str(self.__address)
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_age(self, age):
self.__age = age
def get_age(self):
return self.__age
def set_address(self, address):
self.__address = address
def get_address(self):
return self.__address
class Student(Person):
def __init__(self, name, studentID= None, age= 0, address= None):
super(Student, self).__init__(name, age, address)
self.set_studentID(studentID)
self.__courses =[]
def __str__(self):
result = Person.__str__(self)
result += '\nStudent ID:' + self.get_studentID()
for item in self.__courses:
result += '\n ' + str(item)
return result
def set_studentID(self, studentID):
if isinstance(studentID, str) and len(studentID.strip()) > 0:
self.__studentID = studentID.strip()
else:
self.__studentID = 'NA'
def get_studentID(self):
return self.__studentID
def add_course(self, course):
print('in add_course')
self.__courses.append(course)
def get_courses(self):
for i in range(len(self.__courses)):
return self.__courses[i]
class Course:
__courseName = None
__dept = None
__credits = None
def __init__(self, courseName, dept= 'GE', credits= None):
self.set_courseName(courseName)
self.set_dept(dept)
self.set_credits(credits)
def __str__(self):
return self.get_courseName() + '/' + self.get_dept() + '/' + str(self.get_credits())
def set_courseName(self, courseName):
if isinstance(courseName, str) and len(courseName.strip()) > 0:
self.__courseName = courseName.strip()
else:
print('ERROR: Name must be a non-empty string')
raise TypeError('Name must be a non-empty string')
def get_courseName(self):
return self.__courseName
def set_dept(self, dept):
if isinstance(dept, str) and len(dept.strip()) > 0:
self.__dept = dept.strip()
else:
self.__dept = "GE"
def get_dept(self):
return self.__dept
def set_credits(self, credits):
if isinstance(credits, int) and credits > 0:
self.__credits = credits
else:
self.__credits = 3
def get_credits(self):
return self.__credits
students = []
def recordStudentEntry():
name = input('What is your name? ')
age = input('How old are you? ')
studentID= input('What is your student ID? ')
address = input('What is your address? ')
s1 = Student(name, studentID, int(age), address)
students.append(s1)
s1.add_course(recordCourseEntry())
print('\ndisplaying students...')
displayStudents()
print()
def recordCourseEntry():
courses = []
for i in range(2):
courseName = input('What is the name of one course you are taking? ')
dept = input('What department is your course in? ')
credits = input('How many credits is this course? ')
c1 = Course(courseName, dept, credits)
print(c1)
courses.append(c1)
displayCourses(courses)
return courses
def displayCourses(courses):
print('\ndisplaying courses of student... ')
for c in range(len(courses)):
print(courses[c])
def displayStudents():
for s in range(len(students)):
print()
print(students[s])
recordStudentEntry()
This is how the code above prints out the 'displaying students...' part:
displaying students...
Name: sam
Age: 33
Address: 123 st
Student ID:123abc
[<__main__.Course object at 0x000002BE36E0F7F0>, <__main__.Course object at
0x000002BE36E0F040>]
I know that it is printing out the location because I need to index into the list. However, the length of the list will be different every time. Normally if I wanted to index into a list, for example, to print a list of names, I would do:
listOfNames = ['sam', 'john', 'sara']
for i in range(len(listOfNames)):
print(listOfNames[i])
or
listOfNames = ['sam', 'john', 'sara']
for i in listOfNames:
print(i)
(not sure what if any difference there is between the 2 ways since they both print out the same way:)
sam
john
sara
How can I write something like the indexing into a list technique shown here in my str method for my class so that it prints the information and not the location?
It would be good to keep to the standard conventions for Python, such as naming
private attributes for objects with single underscores, not double underscores.
The latter are reserved for Python "internal" attributes and methods.
Also, it is convention to use object attributes for objects with get/set methods,
not class attributes. This will make it easier to inspect your objects, while
still maintaining data hiding. Example:
class Course:
def __init__(self, courseName, dept= 'GE', credits= None):
self._courseName = None
self._dept = None
self._credits = None
self.set_courseName(courseName)
...
Your question about why the courses don't print out the way you expected
is rooted in a programming error with the way you programmed the recording
of courses. In recordCourseEntry(), you record two courses and put them
in a list. However, you pass that to your Student object using a method
intended for one course at a time. My suggested fix would be:
...
# s1.add_course(recordCourseEntry())
courses = recordCourseEntry()
for course in courses:
s1.add_course(course)
...
This will probably be enough to get you going. An example output I got was:
Name: Virtual Scooter
Age: 33
Address: 101 University St.
Student ID:2021
ff/GE/3
gg/GE/3

automatically instantiating objects

players_list = [Ani, Paty, Felix, Alex]
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
I tried to iterate over the list, but it always gives me an error: NameError: name 'Ani' is not defined
for player in players_list:
player = Player(str(player))
But doing all the process manually work:
Ani = Player("Ani"), etc
Is there any way that i can automate this process?
First of all the thing you should know, the players_list that you have declared are not containing strings, they are being considered as variables which you have not defined anywhere, and therefore the NameError.
Now, if you want to correct this, and if you actually intend to store objects of Player in players_list, then you can do the following:
players_list = ["Ani", "Paty", "Felix", "Alex"]
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
for i in range(len(players_list)):
players_list[i]=Player(players_list[i])
This will store Player objects in the list you have declared just the thing that you expect to get.
You are having problems with the players not being defined. So players_list = [Ani, Paty, Felix, Alex] will throw an error because the objects Ani, Paty, Felizx, and Alex do not exist.
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
Now, we need to iterate through the list.
players_list = ['Ani', 'Paty', 'Felix', 'Alex']
players = [Player(player) for player in players_list]
Sounds like you're trying to dynamically create variables - write code that writes code.
You could try to use the exec built-in function.
players = ['Ani', 'Paty', 'Felix', 'Alex']
class Player:
def __init__(self, name):
self.name = name
def p_vote(self):
print(self.name + " voted.")
for player in players:
exec( "%s = Player( '%s' )" %(player, player) )
Ani.p_vote()
Although, general internet advice has two points to make:
Be cautious where you use exec.
The Pythonic way is to write out the variables, "explicit is better than implicit."

How do I refer to an attribute of an object in a list, by using a string?

I'm writing a text adventure game and I'm trying to take an input for an object in a room, search for it in the objects list, then take that object and append it to the inventory (inv) list. I need to search for the object using the the input of its' name, which is one of the attributes.
class room():
def __init__(self, name):
self.objects = []
class player(room):
def __init__(self, name, inv):
self.name = name
self.inv = []
class things(room):
def __init__(self, name, is_weapon):
self.name = name
self.weapon = is_weapon
currentRoom = center
objLen = len(currentRoom.objects)
if currentRoom.objects:
for x in range(len(currentRoom.objects)):
print("Objects here: ",currentRoom.objects[x].name)
pickUp = input("Would you like to take any objects: ")
for a in range(0,objLen):
if pickUp.upper() == currentRoom.objects.name:
ind = currentRoom.objects.index(pickUp.upper().name)
Andy.inv.append(currentRoom.objects[ind])
currentRoom.objects.pop[ind]
else:
print("Object not found in this room!")
Got it.
for a in range(0,objLen):
if pickUp.upper() == currentRoom.objects[a].name:
Player.inv.append(currentRoom.objects[a])
currentRoom.objects.pop(a)

How to get rid of eval in subclass appending to superclass instance list?

I am using eval to run a generated string to append the newly created EggOrder instance to the list of the correct instance of the DailyOrders class. The day provided by EggOrder is used to used to append to the correct instance. This relies on eval and the variable name of the DailyOrders instance and so it would be great to get this removed. I know there must be a better way.
class DailyOrders:
PRICE_PER_DOZEN = 6.5
def __init__(self, day):
self.orders = []
self.day = day
def total_eggs(self):
total_eggs = 0
for order in self.orders:
total_eggs += order.eggs
return total_eggs
def show_report(self):
if self.total_eggs() < 0:
print("No Orders")
else:
print(f"Summary:\nTotal Eggs Ordered: {self.total_eggs()}")
print(f"Average Eggs Per Customer: {self.total_eggs() / len(self.orders):.0f}\n*********")
class EggOrder():
def __init__(self, eggs=0, name="", day=""):
if not name:
self.new_order()
else:
self.name = name
self.eggs = eggs
self.day = day
eval(f"{self.day.lower()}.orders.append(self)")
def new_order(self):
self.name = string_checker("Name: ")
self.eggs = num_checker("Number of Eggs: ")
self.day = string_checker("Date: ")
def get_dozens(self):
if self.eggs % 12 != 0:
dozens = int(math.ceil(self.eggs / 12))
else:
dozens = self.eggs / 12
return dozens
def show_order(self):
print(f"{self.name} ordered {self.eggs} eggs. The price is ${self.get_dozens() * DailyOrders.PRICE_PER_DOZEN}.")
if __name__ == "__main__":
friday = DailyOrders("Friday")
friday_order = EggOrder(12, "Someone", "Friday")
friday_order.show_order()
friday.show_report()
saturday = DailyOrders("Saturday")
saturday_order = EggOrder(19, "Something", "Saturday")
saturday_order = EggOrder(27, "Alex Stiles", "Saturday")
saturday.show_report()
DailyOrders isn't actually a superclass (it was in a earlier version), it acts like one and I suspect the answer might have some inheritance.

Categories

Resources