Accessing method variables of one class in another python class - python

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.

Related

Python Count function not work on instances of a class?

So Ive been trying to make a method which checks if an entered Item is present in the players inventory. For that I used the count to check if the item exists atleast once. However it seems like that it does not instances of the class. (All the items in the inventory of the player are instance of a classs)
inventory = []
def equipItem(self):
equipinput = input("Chosse Item to equip: ")
#Get Input which item to equip
itemcount = self.inventory.count(equipinput)
#Count how many times the item was found
if itemcount >= 1:
itemindex = self.inventory.index(equipinput)
if self.inventory[itemindex].typeitem == "weapontype":
#Check the item type(is an attribute of the item/Class)
self.inventory[0], self.inventory[itemindex] = self.inventory[itemindex], self.inventory[0]
#Switch position of the item to equip and that of the current item (It is always on the first position)
print("Changed Weapon to " + str(equipinput))
game()
#Go back to the game
else:
self.inventory[1], self.inventory[itemindex] = self.inventory[itemindex], self.inventory[1]
print("Changed Armor to " + str(equipinput))
game()
else:
print(f"{Fore.RED}You do not have this item!{Style.RESET_ALL}")
#Output an error Message in red
game()
Example inventory:
self.inventory = [Wooden Dagger, Steel Sword]
Example input would be then: Steel Sword
Expected Output/inventory:
self.inventory = [Steel Sword, Wooden Dagger]
You are comparing apples to oranges. The returned value of input is type string and the inventory array contains instances of some class (which you have omitted but i will call the "equipment" class).
You could create a __str__(self): method for the omitted "equipment" class like so.
class Equipment:
def __init__(self, name: str):
self.name = name
def __str__(self):
return self.name
You could then use list comprehension to create an array of string representations of the inventory and compare the input to that.
inventory = [Equipment('steel sword'), Equipment('basic axe')]
def equip_item(self):
string_inventory = [str(item) for item in self.inventory] # creates array ['steel sword', 'basic axe']
print(string_inventory.count('basic axe')) # now we can compare strings to strings with the count method
I would also recommend looking into the __repr__(self): magic method.
lastly, if comparing string, I also recommend using the .upper() method so capitalization does not cause problems.
You cannot count instances of a class this way. If you look at the representation of it by printing it, you will see something like <__main__.SteelSword object at 0x7f15e6f97430>. They are obviously different, but are instances of the same class. So you can do:
[isinstance(ins, SteelSword) for ins in self.inventory].count(True)
Now, if you use input(), you will always get a string back, which is different from a class reference: 'SteelSword' != <class '__main__.SteelSword'>
So you need a way to address this issue. What you could do, for example, is to create a dict that takes your class names as a string ('SteelSword') key and the class references as the corresponding values.

How to retrieve a class object inside the dictionary in python?

I have added a employee class object inside a dictionary successfully .But i am not able to get back the value from the same dictionary? Below are the code and output.
source code:
# decalre a dict
employee_collection = {}
# Class object to store employee's details
class employee:
# Constructor
def __init__(self,name,age):
self.name = name
self.age = age
# Display the object values
def print_property(self):
print(f"name is {self.name} and age is {str(self.age)}")
# loop to add multiple employee details
for x in range(1, 6):
obj= employee("xxx", 28+x)
employee_collection.update({x : obj})
# extract the employee detail from and print the vaue to user
for x in employee_collection:
# print(x.name)
print(x)
print(employee_collection)
output :
1
2
3
4
5
{1: <__main__.employee object at 0x0327F610>, 2: <__main__.employee object at 0x03550C70>, 3: <__main__.employee object at 0x03550580>, 4: <__main__.employee object at 0x035503B8>, 5: <__main__.employee object at 0x03550FB8>}
My question is:
How to print the name and age using loop in main method?
Two methods. The dict is storing the instance of each employee (which should be Employee btw).
You can either print the properties of the instance, or change what happens when you try to print an object.
The former:
for key, e in employee_collection.items():
print(f'{x} {e.name} {e.age}')
The latter:
class Employee:
...
def __str__(self):
return f'{self.name} {self.age}'
for e in employee_collection.values():
print(e)
To iterate through a dictionary you can use its keys(), values() or items(). Since you want both the key (x) and the value (employee) you want to use items() which returns all dictionary key-value pairs as so-called tuple in a list:
for x, employee in employee_collection.items():
print(f'Number: {x}, Name: {employee.name}, age: {employee.age}') # this is printing a format-string

How can I check if an attribute of a class exists in array?

I want to know if it is possible to check if an array of a class has a specific instance of an attribute, and return True if it does. In other words, does an instance of a class attribute exist in an array of that class?
In my example, I have an array of class Team. The class Team has an attribute, name. I want to check if a Team instance with a specific name exists by iterating over an array of Team instances.
Class Team:
class Team:
def __init__(self):
self.name = name # (String)
[Invalid] This is the how I wanted to write the function:
# team_name is a String variable
# teams is an array of the Team class
def team_name_taken(team_name, teams):
if team_name in teams.name:
return True
else:
return False
I know this doesn't work, but is it possible to iterate over the same attribute within an array in this fashion?
[Valid] Regarding the goal of my code, I have the following code that works properly:
def team_name_taken(team_name, teams):
for team in teams:
if team_name == team.name:
return True
return False
I know that this works, I was just wondering if there was another way to do it, similar to the invalid way I represented above.
What you could do is the following:
def team_name_taken(team_name, teams):
team_names = [team.name for team in teams]
if team_name in team_names:
return True
else:
return False
This will generate a list with the items of the list being all team names. Once you have done that you can do if team_name in team_names: and get the desired outcome.
If on the other hand you just want to make it a oneliner you could do this:
def team_name_taken(team_name, teams):
return len([ team for team in teams if team.name == team_name ]) >= 1
This will make a list then check if the len() of the list is 1 (or bigger) and if that is the case return True else False.
The following class definition allows name from the user to be assigned to the Team.name attribute and forces it to be a str object:
class Team(object):
def __init__(self, name):
self.name = str(name)
Here is an example list of Team instances:
teams = [Team(x) for x in range(10)]
You can do what I think you want with some one-liners:
Using another list comprehension to find out if any of the names equal '3':
any([team.name == '3' for team in teams])
Or if you really want to use a function you can use the following:
any(map(lambda obj: obj.name == '3', teams))

How to create and set variables as classes from a list of tuples?

I am trying to figure out how to create variables from a list of tuple and assign them to a class.
I have data organized like this
Name Age Status
John 30 Employed
That I have created a list of tuple like this
employeelist = [(John, 30, Employed), (Steve, 25, Part-Time)]
And a class set up like this
class Employee():
ecount = 0
elist = []
def __init__(self, name, age, emp_status):
self.name = name
self.age = age
self.emp_status = emp_status
self.lookup = {}
Employee.ecount = Employee.ecount+1
Employee.elist.append(self.name)
Using this code I am able to turn the tuple into an instance of the class
for i in range(0, len(employeelist),1):
sublist = [str(n) for n in employeelist[i]]
Employee(sublist[0], sublist[1], sublist[2])
But I am not able to access them. Is there a way to think about setting up the for loop to create a variable from sublist[0] and then create a class out of it (e.g. sublist[0] = Employee(sublist[0], sublist[1], sublist[2]))?
You just need
employees = [Employee(*v) for v in employee_list]
Note that employees and Employee.elist are essentially the same once
each Employee object has been created.

Searching a list to see if there is a match python

Basically this is within a class which appends objects of another class to list self. There are 200 objects in list self. So basically if I call self[1] I will get ['John',['Alex', 'Rob']. Basically 'john' refers to self.firstname and the other names refer to there group members. For example the below will print the firstnames and groupmembers of each object for all 200 objects
for line in self:
print line.firstname
for line in self:
print line.groupmembers
Now I have to create something that goes through all the names and checks the names. So basically if John has Alex and Rob as members then there has to be another object with a first name Alex and another object with a firstname Rob. So say there is no object with firstname Alex I want to print 'mismatch'. This is what I have so far but its not doing what its intended to do.
def name(self):
firstnames = []
for item in self:
firstnames.append(item.firstname)
for item1 in self:
for i in item1.groupmembers:
if i not in hello:
print 'mismatch'
Okay so first off, line and self are bad variable names.
self should only be used within a class to be used as a way to call or use its own variables.
Secondly, you say each value in this self list contains values like ['John',['Alex', 'Rob'], but then you go on to use it like a class object... and frankly that don't do make none sense.
So to remedy this, I'm going to assume its done with class objects. I would also rename self to something like school, and instead of calling an element of self; line, which yields no information to the reader.. call it a student!
I'm going to assume your class would start looking like this:
class Student:
# having an empty default value makes it easy to see what types variables should be!
firstname = ""
groupmembers = []
def __init__(self,firstname,groupmembers ):
self.firstname = firstname
self.groupmembers = groupmembers
Then if you have a list of people you can loop through them like so..
>>>school = [Student("foo", ["bar", "that guy"]),
Student("bar", ["foo", "that guy"])]
>>>for student in school:
print student.firstname
print student.groupmembers
foo
["bar", "that guy"]
bar
["foo", "that guy"]
Then to check it a students group members are in school you can add a function to the Student class
class Student:
# having an empty default value makes it easy to see what types variables should be!
firstname = ""
groupmembers = []
def __init__(self,firstname,groupmembers ):
self.firstname = firstname
self.groupmembers = groupmembers
def group_present(self, school):
# This is how you would get all the names of kids in school without list comprehension
attendance = []
for student in school:
attendance.append(student.firstname)
# this is with list comprehension
attendance = [ student.firstname for student in school]
#compare group members with attendance
#note that I write student_name, not student
## helps point out that it is a string not a class
for student_name in self.groupmembers:
if not student_name in attendance:
print "Group member '{}' is missing :o!! GASP!".format(student_name)
In idle:
>>> school[0].group_present(school)
Group member 'that guy' is missing :o!! GASP!
Hope that helps!
I am not sure if i understand exactly but maybe you can use contains
self[1].__contains__('Alex')
this should return true in case of existence or false otherwise.

Categories

Resources