Why the type of a parameter of a function in a class would change into list? - python-3.x

class Employee:
num_of_emps = 0
raise_amount = 1.04
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = first + last + '#gmail.com'
Employee.num_of_emps += 1
def fullname(self):
return f'I am {self.first} {self.last}'
def apply_raise(self):
self.pay = int(self.pay * Employee.raise_amount)
#classmethod
def set_raise_amt(cls, amount):
cls.raise_amount = amount
#classmethod
def from_string(cls, emp_str):
first, last, pay = emp_str.split('-')
return cls(first, last, pay)
#staticmethod
def is_workday(day):
if day.weekday() == 5 or day.weekday() == 6:
return False
return True
class Developer(Employee):
raise_amount = 1.50
def __init__(self, first, last, pay, prog_lang):
super().__init__(first, last, pay)
self.prog_lang = prog_lang
class Manager(Employee):
def __init__(self, first, last, pay, employees=None):
super().__init__(first, last, pay)
if employees is None:
self.employees = []
else:
self.employees = employees
def add_emp(self,emp):
if emp not in self.employees:
self.employees.append(emp)
def remove_emp(self,emp):
if emp in self.employees:
self.employees.remove(emp)
def print_emps(self):
for emp in self.employees:
print('--->', emp.full_name())
dev_1 = Developer('John','Doe',30000, 'Python')
dev_2 = Developer('Emily','Smith',23000, 'Java')
# print(help(Developer))
print(dev_1.email)
print(dev_2.email)
print(dev_1.pay)
dev_1.apply_raise()
print(dev_1.pay)
mgr_1 = Manager('Sarah','Smith',34000, [dev_1])
print(type(mgr_1.employees))
print(mgr_1.employees)
print(type(dev_1))
print(type([dev_1]))
print([dev_1])
mgr_1.print_emps()
I recently studied this code on youtube. So basically this code started with a class named 'Employee' at the beginning, and then a subclass called 'Developer' was created. I still able to catch up with the logic behind the code at the moment, but after another subclass called 'Manager' was created, I lost.
I don't know why the parameter,'employees' in the class 'Manager' would suddenly become a list in the end
And I also don't know why the for loop could be able to run
Please help, thank you so much

mgr_1 = Manager('Sarah','Smith',34000, [dev_1])
first='Sarah', last='Smith', pay=34000, employees=[dev_1]
Your parameter is an list

Related

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.

How can I return all values inside of a class variable?

I'm writing a text adventure game in Python and I'm curious on how I can go about listing all the items inside of the Room class
I'm very new to Python and have very limited practice.
# Declaring items and assigning them rooms
dingus = Item("Dingus", "This really dings.")
room["garden"].add_item(dingus)
flippers = Item("Flippers", "Webbed in nature.")
room["garden"].add_item(flippers)
# Declare all the rooms
room = {
'garden': Room("Garden",
"""The flowers are blooming wonderfully. To the south lies a dark path.""")
}
class Room:
def __init__(self, title, description):
self.title = title
self.description = description
self.items = []
self.items_in_room = ''
def __repr__(self):
print(f"-" * 40)
return (f"You are at the {self.title}.")
def add_item(self, item):
return self.items.append(item)
def list_items_in_room(self):
for item in self.items:
self.items_in_room += item
', '.split(self.items)
return self.items
class Item:
def __init__(self, name, description):
self.name = name
self.description = description
def __str__(self):
return f'{self.name} - {self.description}' + '\n' + "-" * 40
I'm expecting Room.list_items_in_room to list all the items in the room in a comma separated string.
I have re-arranged your code and also changed the function list_items_in_room. Also, have changed the __str__ function to __repr__ and removed the '-' * 40 (I couldn't understand why that's there).
class Room:
def __init__(self, title, description):
self.title = title
self.description = description
self.__items = []
# __ so that it's not modifiable without getter and setter functions
def __repr__(self):
print(f"-" * 40)
return (f"You are at the {self.title}.")
def add_item(self, item):
return self.__items.append(item)
def list_items_in_room(self):
return self.__items
class Item:
def __init__(self, name, description):
self.name = name
self.description = description
def __repr__(self):
return f'{self.name} - {self.description}'
# Declare all the rooms
room = {
'garden': Room("Garden",
"""The flowers are blooming wonderfully. To the south lies a dark path.""")
}
dingus = Item("Dingus", "This really dings.")
room["garden"].add_item(dingus)
flippers = Item("Flippers", "Webbed in nature.")
room["garden"].add_item(flippers)
print(room['garden'].list_items_in_room())
Output:
[Dingus - This really dings., Flippers - Webbed in nature.]

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.

builtins.TypeError: unsupported operand type(s) for *: 'int' and 'method'

I'm writing some code from a YouTube tutorial and I keep running into a type error. Why?
class Employee():
''' keeps track of company employees'''
raise_amount = 1.04
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = last + '.' + first +'#tech.com'
def fullname(self):
return self.first +' ' + self.last
def Email(self): #not needed bc its already an attribute
return self.email
def raise_amount(self):
return ((self.pay * self.raise_amount) - self.pay)
def annual_raise(self):
self.pay = int(self.pay * self.raise_amount)
return pay
Here , You have used the same name raise_amount for method and the class variable. When you execute the below code
def raise_amount(self):
return ((self.pay * self.raise_amount) - self.pay)
self.raise_amount will point to the method raise_amount. So the multiplication operation fails as it expects its arguments as numbers. You can either change class variable name or method name.
If you are changing class variable name, change the code as below:
raise_amount_value = 1.04
inside the method :
def raise_amount(self):
return ((self.pay * self.raise_amount_value) - self.pay)
def annual_raise(self):
self.pay = int(self.pay * self.raise_amount_value)
return pay
class Employee():
''' keeps track of company employees'''
raise_amount = 1.04
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = last + '.' + first +'#tech.com'
def fullname(self):
return self.first +' ' + self.last
def Email(self): #not needed bc its already an attribute
return self.email
def raise_amount(self):
return ((self.pay * self.raise_amount) - self.pay)
def annual_raise(self):
self.pay = int(self.pay * self.raise_amount)
return pay
emp_1 =Employee("Joshua", "Ozoya", 9000)
print(emp_1.fullname())
your programme is running fine.
emp_1 =Employee("Joshua", "Ozoya", 9000)
print(emp_1.fullname())
Add those two lines of code to get the result.
And also, specify the error you were getting.

How to create addPlayer() method. (Python 3)

I'm currently working on an OOP project in my CSI class in which I have to create various sports team and athlete objects as well as a method addPlayer() for adding the athletes to a roster. This is what I have so far.
class Athlete:
def __init__(self, name, number):
self.name = name
self.number = number
def __str__(self):
return "Athlete(" + self.name + ", " + self.number + ")"
def name(self):
return self.name
def number(self):
return self.number
from Athlete import *
class SportsTeam:
roster = []
def __init__(self, city, name, colors):
self.city = city
self.name = name
self.colors = colors
SportsTeam.roster = roster
def __str__(self):
return "SportsTeam(" + self.city + ", " + self.name + \
", " + str(self.colors) + ", " + ")"
def getcity(self):
return self.city
def getname(self):
return self.name
def getcolors(self):
return self.colors
def getRoster(self):
return SportsTeam.roster
def printRoster(self):
for player in roster:
print("Current Team Roster: " + str(SportsTeam.roster))
def addPlayer(self, player):
SportsTeam.roster.append(player)
return SportsTeam.roster
The thing is when I try to use the addPlayer() method I created, I get an error message telling me that list has no attribute. Not sure what needs to be added to fix this.
P.S I have only been programming for a couple of months, so I apologize if the solution is obvious
When you are dealing with classes, you have your instance variables (like self.city = city) and your class variables (like roster = []).
Instance variables are tied to an instance of the class. So if you create 2 SportsTeam objects, they each have their own city.
Class variables are a little different. They are not tied to an instance of the class; meaning, no matter how many SportsTeam objects you create, there will only be one roster variable.
To me, roster being a class variable seems a bit odd because each SportsTeam should have its own roster. However, if you are required to use class variables for you CSI class, maybe you could keep a list of all_teams and/or all_players.
Taking this into consideration:
class SportsTeam:
all_teams = []
all_players = []
def __init__(self, city, name, colors):
self.city = city
self.name = name
self.colors = colors
self.roster = []
SportsTeam.all_teams.append(self)
def __str__(self):
return "SportsTeam(" + self.city + ", " + self.name + ", " + str(self.colors) + ")"
def getCity(self):
return self.city
def getName(self):
return self.name
def getColors(self):
return self.colors
def getRoster(self):
return self.roster
def printRoster(self):
# the for loop was unnecessary
print("Current Team Roster:", str(self.roster))
def addPlayer(self, player):
SportsTeam.all_players.append(player)
self.roster.append(player)
return self.roster
If you would like to keep roster as a class variable, leave a comment and I can help you adjust the code to accommodate for this.

Resources