How in Pyhton's OOP a class's method access to another class's method? - python-3.x

I am new to Python OOP and I am trying to learn the basics of Python OOP and I came across a video on YouTube that teaches the basics of it. The code is an example code from the video. I understood all of it but I am not able to understand how the class "Course's" "get_average_grade()" method is accessing the class "Student's" "get_grade()" method? Any help is highly appreciated.
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade # 0-100
def get_grade(self): #<---- This method was used inside the Course class
return self.grade
class Course:
def __init__(self, name, max_students):
self.name = name
self.max_students = max_students
self.students = []
def add_student(self, student):
if len(self.students) < self.max_students:
self.students.append(student)
return True
return False
def get_average_grade(self):
value = 0
for student in self.students:
value = value + student.get_grade() #<---- This Method is from the Student class
return value / len(self.students)
s1 = Student("Tim", 19, 95)
s2 = Student("Bill", 19, 75)
s3 = Student("Jill", 19, 65)
course = Course("Science", 2)
course.add_student(s1)
course.add_student(s2)

Related

I'm supposed to create database class of student.I have to create a function which adds courses accounting for addition in attributes of the object

class student:
def __init__(self, class_student, name, GPA=0,number_of_course=0, number_of_credits=0):
self.class_student= class_student
self.name= name
self.GPA= GPA
self.number_of_course=number_of_course
self.number_of_credits= number_of_credits
def add_course(self,GPA, number_of_credits):
return student(self.class_student,self.name, self.GPA,self.number_of_course,self.number_of_credits)
mylad= student('Senior', 'Ardy', 2.7, 0, 0)
print(mylad.add_course(3.2, 3))
This code displays <main.student object at 0x7ff427458460>.
I am a beginner at Python and do not know how to fix this. If anyone can help me I would appreciate it very much!
I believe that you are just trying to re-assign a different value the existing self attributes of the Student class. In this case, you shouldn't use return statements, instead re-assign the class attributes themselves.
class Student:
def __init__(self, class_student, name, GPA=0, num_courses=0, num_credits=0):
self.class_student = class_student
self.name = name
self.GPA = GPA
self.num_courses = num_courses
self.num_credits = num_credits
def add_course(self, GPA, num_credits):
self.GPA = GPA
self.num_credits = num_credits
sample_student = Student('Senior', 'Ardy', 2.7, 0, 0)
sample_student.add_course(3.2, 3)
print(sample_student.GPA)
print(sample_student.num_courses)
...
Alternatively, you could elimate the add_course classmethod and just do this:
class Student:
def __init__(self, ...):
...
sample_student = Student("Senior", "Ardy", 2.7, 0, 0)
sample_student.GPA = 3.2
sample_student.num_credits = 3
...

how to access to data from a class which is stored in another class in python?

This is my code. I got a problem when i want to print the information inside the class 'pokemon'
class trainer(object):
def __init__(self, name, pokemons = [], money = 0):
self.name = name
self.pokemons = pokemons
self.money = money
this is my first class which has every pokemon per trainer
class pokemon(object):
def __init__(self, name, attribute, attacks = {}, health = '==========='):
self.name = name
self.attribute = attribute
self.health = health
self.attacks = attacks
The other class where I take the pokemon to import to the other class
class fight():
def __init__(self, fighter1, fighter2):
self.fighter1 = fighter1
self.fighter2 = fighter2
def fighting(self):
if len(Trainer1.pokemons) >= 1 and len(Trainer2.pokemons) >= 1:
print('{} wanna fight against {}'.format(Trainer1.name, Trainer2.name))
keepgoing = True
print('{} got this Pokemons: '.format(Trainer1.name))
i = 0
for i in Trainer1.pokemons:
print(i)
#while (keepgoing):
else:
print('You gotta have pokemons to fight')
return False
I thought that creating a class named fight for getting in battle would be the most wise idea but I'd like to know another method to do it
Pokemon1 = pokemon('Charizard', 'Fire', attacks={'1':'ball fire', '2':'cut', '3':'fire blast', '4':'mega kick'})
Pokemon2 = pokemon('Charmander', 'fire', attacks={'1':'blast', '2':'scratch', '3':'heat', '4':'tear'})
Trainer1 = trainer('Santiago', pokemons=[Pokemon1, Pokemon2])
Pokemon3 = pokemon('Charizard', 'Fire', attacks={'1':'ball fire', '2':'cut', '3':'fire blast', '4':'mega kick'})
Pokemon4 = pokemon('Charmander', 'fire', attacks={'1':'blast', '2':'scratch', '3':'heat', '4':'tear'})
Trainer2 = trainer('Alejandra', pokemons=[Pokemon3, Pokemon4])
Okay my problem is in the class fight. when i want to print the names of the pokemons i get the following message:
Santiago got this Pokemons:
<__main__.pokemon object at 0x000002AAD9B64D00>
<__main__.pokemon object at 0x000002AAD9B92DF0>
i know that the pokemon class has various instances, but how can i access to them?
To make your life easier, I recommend that you implement the __str__ dunder method on pokemon. This will resolve the issue that you are seeing right now, and make future prints of pokemon much easier.
That would look something like this:
class pokemon(object):
def __init__(self, name, attribute, attacks = {}, health = '==========='):
self.name = name
self.attribute = attribute
self.health = health
self.attacks = attacks
def __str__(self):
return "Pokemon: %s (Health: %11s)" % (self.name, self.health)
When you print the 'Charmander' pokemon, it'll look something like this:
Pokemon: Charmander (Health: ===========)
Of course, you can change the return of the __str__ to return whatever you want out of the pokemon.

In OOP in python, are different instances of an object when initialised with a default value the same?

I am trying to understand object oriented programming. I am doing this by creating a small poker like program. I have come across a problem whose minimal working example is this:
For this code:
import random
class superthing(object):
def __init__(self,name,listthing=[]):
self.name = name
self.listthing = listthing
def randomlyadd(self):
self.listthing.append(random.randint(1,50))
def __str__(self):
return '\nName: '+str(self.name)+'\nList: '+str(self.listthing)
Aboy = superthing('Aboy')
Aboy.randomlyadd()
print(Aboy)
Anotherboy = superthing('Anotherboy')
Anotherboy.randomlyadd()
print(Anotherboy)
I expect this output :
Name: Aboy
List: [44]
(some number between 1 and 50)
Name: Anotherboy
List: [11]
(again a random number between 1 and 50)
But what I get is:
Name: Aboy
List: [44]
(Meets my expectation)
Name: Anotherboy
List: [44,11]
(it appends this number to the list in the previous instance)
Why is this happening? The context is that two players are dealt a card from a deck. I am sorry if a similar question exists, if it does, I will read up on it if you can just point it out. New to stack overflow. Thanks in advance.
For the non minimal example, I am trying this:
import random
class Card(object):
def __init__(self, suit, value):
self.suit = suit
self.value = value
def getsuit(self):
return self.suit
def getval(self):
return self.value
def __str__(self):
if(self.suit == 'Clubs'):
suitstr = u'\u2663'
elif(self.suit == 'Diamonds'):
suitstr = u'\u2666'
elif(self.suit == 'Hearts'):
suitstr = u'\u2665'
elif(self.suit == 'Spades'):
suitstr = u'\u2660'
if((self.value<11)&(self.value>1)):
valuestr = str(self.value)
elif(self.value == 11):
valuestr = 'J'
elif(self.value == 12):
valuestr = 'Q'
elif(self.value == 13):
valuestr = 'K'
elif((self.value == 1)|(self.value == 14)):
valuestr = 'A'
return(valuestr+suitstr)
class Deck(object):
def __init__(self,DeckCards=[]):
self.DeckCards = DeckCards
def builddeck(self):
suits = ['Hearts','Diamonds','Clubs','Spades']
for suit in suits:
for i in range(13):
self.DeckCards.append(Card(suit,i+1))
def shuffle(self):
for i in range(len(self)):
r = random.randint(0,len(self)-1)
self.DeckCards[i],self.DeckCards[r] = self.DeckCards[r],self.DeckCards[i]
def draw(self):
return self.DeckCards.pop()
def __str__(self):
return str([card.__str__() for card in self.DeckCards])
def __len__(self):
return len(self.DeckCards)
class Player(object):
def __init__(self,Name,PlayerHandcards = [],Balance = 1000):
self.Name = Name
self.Hand = PlayerHandcards
self.Balance = Balance
def deal(self,deck):
self.Hand.append(deck.draw())
def __str__(self):
return 'Name :'+str(self.Name)+'\n'+'Hand: '+str([card.__str__() for card in self.Hand])+'\n'+'Balance: '+str(self.Balance)
deck1 = Deck()
deck1.builddeck()
deck1.shuffle()
Alice = Player('Alice')
Alice.deal(deck1)
print(Alice)
Bob = Player('Bob')
Bob.deal(deck1)
print(Bob)
And after dealing to Bob they both have the same hands. If you have some other suggestions regarding the code, you are welcome to share that as well.
This is a duplicate of “Least Astonishment” and the Mutable Default Argument as indicated by #Mad Physicist. Closing this question for the same.

Python get object attributes

My loop at the bottom of my code doesn't seem to print song title if I type print SongList[i] it prints the memory address for the given object. I'm sure it's returning the Song List but the object attributes. Am I missing a method? Sorry if this has already been answered in the past I cannot find an example.
class Song:
def __init__(self, title, artist, duration = 0):
self.title = title
self.artist = artist
self.duration = duration
class Album:
def __init__(self, albumTitle, releaseYear, albumSize):
self.albumTitle = albumTitle
self.releaseYear = releaseYear
self.trackList = []
self.albumSize = albumSize
def addSong(self, albumSong, position):
self.trackList.append((position, albumSong))
class Artist:
def __init__(self, name, year):
self.name = name
self.year = year
self.members = []
def addMembers(self, bandMember):
self.members.append(bandMember)
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
BlinkAndSee = Album("Blink and See", 2018, 5)
Band = Artist("Dinkers", 2002)
AlexThomas = Person("Alex Thomas", 23, "Female")
SeanJohnson = Person("Sean Johnson", 25, "Male")
SineadMcAdams = Person("Sinead McAdams", 21, "Female")
Band.members.append(AlexThomas)
Band.members.append(SeanJohnson)
Band.members.append(SineadMcAdams)
Stoner = Song("Stoner", Band, 320)
Blink = Song("Blink and See", Band, 280)
See = Song("See", Band, 291)
DumbnessAndSand = Song("Dumbness and Sand", Band, 231)
OrangeYellow = Song("Orange Yellow", Band, 353)
BlinkAndSee.trackList.append(Stoner)
BlinkAndSee.trackList.append(BlinkAndSee)
BlinkAndSee.trackList.append(See)
BlinkAndSee.trackList.append(DumbnessAndSand)
BlinkAndSee.trackList.append(OrangeYellow)
SongList = BlinkAndSee.trackList
#Loop through the Song list from album tracklist
for i in range(SongList.__len__()):
print(SongList[i].title)
This is caused by (probably) a typo:
Note how you append BlinkAndSee.trackList.append(BlinkAndSee)?
This essentially appends the object itself to the track list;
of course, this will cause an error, since an Artist does not have the attribute title that you are accessing further down when iterating over the list.
In that case, I would suggest you add some lines to your Album.addSong() function that verifies that the passed argument is of a certain type;
Something like
def addSong(self, albumSong, position):
if not isinstance(albumSong, Song):
print("Passed wrong type to addSong")
else:
self.trackList.append((position, albumSong))

Name Error python, a text adventure game

So i have a problem, that i don't quite understand why it's happening. I get a (Name Error global variable "value" is not defined) when it should be on my weapons class.
from items import *
class weapons(Item):
def __init__(self, name, attack_damage, lifesteal = 0):
super(weapons,self).__init__(name, value, quantity=1)
self.attack_damage = attack_damage
self.lifesteal = lifesteal
Here is the class that weapons is getting it from that already has value defined.
class Item(object):
def __init__(self, name, value, quantity=1):
self.name = name
self.raw = name.replace(" ","").lower()
self.quantity = quantity
self.value = value
self.netValue = quantity * value
def recalc(self):
self.netValue = self.quantity * self.value
I already have a piece of code similar to this that is working, but for some reason this value error is happening. I'm just going to include it.
from character import*
class player(character):
def __init__(self,name,hp,maxhp,attack_damage,ability_power):
super(player,self).__init__(name, hp, maxhp)
self.attack_damage = attack_damage
self.ability_power = ability_power
and the class that player is getting its stuff from
class character(object):
def __init__(self,name,hp,maxhp):
self.name = name
self.hp = hp
self.maxhp = maxhp
def attack(self,other):
pass
as you can see i did it here and this piece of code works when i call a player.
You need to add the value argument to the __init__ constructor of the weapons class.
super needs a parameter value but you did not pass it into the init

Resources