I am trying to return the price of the computer based on "macType" which is the size of the computer. I cannot figure out where to integrate the if statement into my code, ahh!!!
class apple:
def __init__(self,pType,price):
self.__pType=pType
self.__price=price
def setpType(self,pType):
self.__pType=pType
def setprice(self,price):
self.__price=price
def getpType(self):
return self.__pType
def getprice(self):
return self.__price
class mac(apple):
def __init__(self,pType,price,macType):
apple.__init__(self,pType,price)
self.__price=price
self.__macType=macType
def setmacType(self,macType):
self.__macType=macType
def setmacPrice(self,price):
if(macType()=="11Inch"):
self.__price=float(price*.9)
elif(macType()=="13Inch"):
self.__price=price
elif(macType()=="15Inch"):
self.__price=float(price*1.2)
def getmacType(self):
return self.__macType
def getprice(self):
if (self.__macType == "11inch"):
return super(mac, self).getprice()*.9
elif (self.__macType == "13inch"):
return super(mac, self).getprice()
else:
return super(mac, self).getprice()*1.1
a1 = apple("computer",1000)
m1 = mac("computer",1000,"11Inch")
m2 = mac("computer",1000,"13Inch")
m3 = mac("computer",1000,"15Inch")
print("a1 is a ",a1.getpType(),"and it costs",a1.getprice())
print("m1 is a ",m1.getmacType(),"and it costs",m1.getprice())
print("m1 is a ",m2.getmacType(),"and it costs",m2.getprice())
print("m1 is a ",m3.getmacType(),"and it costs",m3.getprice())
Actual output should show that 11 inch is 900, 13 inch is 1000 and 15 inch is 1100.
Python string comparison is case sensitive. In your getprice method you user "11inch", but you give your construct "11Inch" notice the upper- and lowercase i? Does aren't going to compare equal. Just use the same everywhere, or even better, look into the enum module.
Related
I want to make the class score in python that takes each subject's score and return its average and sum. I know if I receive 4 arguments than denominator of average should be 4, but how I can make it to fixed codes that changed by number of inputs?, not just count numbers and type 4. I tried Len(self) or using for loop to count but Len makes error and for loop isn't that easy.
class score:
def __init__(self, language, math, english, science):
self.language = language
self.math = math
self.english = english
self.science = science
...
def sum_scores(self):
result = self.language + self.math + self.english + self.science
return result
def average(self):
average = self.sum_scores()/4 # Here is the problem!
return average
This is my first question on stack. so sorry for my poor English and stupid questions.
Don't use 4 separate attributes in the first place. Use a dict to store the attributes; then you can query the size of the dict.
class score:
def __init__(self, language, math, english, science):
self.scores = {'language': language, 'math': math, 'english': english, 'science': science}
...
def sum_scores(self):
return sum(self.scores.values())
def average(self):
return self.sum_scores() / len(self.scores)
If you still want attributes for each individual score, use properties:
class score:
def __init__(self, language, math, english, science):
self.scores = {'language': language, 'math': math, 'english': english, 'science': science}
#property
def language(self):
return self.scores['language']
# etc.
def sum_scores(self):
return sum(self.scores.values())
def average(self):
return self.sum_scores() / len(self.scores)
Assuming that it is OK that you don't know the subjects for which the scores apply, you can just use unnamed positional arguments
class score:
def __init__(self, *args):
self.scores = args
...
def sum_scores(self):
return sum(self.scores)
def average(self):
return self.sum_scores() / len(self.scores)
For your case, you could just note that the quantity is 4
However, you may want to use **kwargs as an argument (you can use any name, this is just convention; ** assigns all the keyword args not specifically named to a dict) instead
SUBJECTS = ("math", "science" ... )
class MyClass():
def __init__(self, **kwargs): # also consider *args
self.subjects = {k: v for k, v in kwargs.items() if k in SUBJECTS}
def sum_scores(self):
return sum(self.subjects.values())
def average(self):
return self.sum_scores() / len(self.subjects)
>>> c = MyClass(math=10, science=8)
>>> c.sum_scores()
18
>>> c.average()
9.0
You may also want to consider reporting on arguments that are not used to help users find usage errors
You can use keyword arguments in your init function:
class Score:
def __init__(self, **scores):
self.classes = []
for _class, score in scores.items():
setattr(self, _class, score) # self.english, self.math, etc.
self.classes.append(_class) # ["math", "english"]
def sum_scores(self):
sum = 0
for i in self.classes:
sum += getattr(self, i)
return sum
def average(self):
return self.sum_scores() / len(self.classes)
By using **scores, you can dynamically iterate over all arguments passed into the function as a dictionary. Here, I use the setattr function to give the Score object a property of its class name, and its value is the corresponding value from the dictionary. That way, I can dynamically iterate over each class, whether 3 or 100 classes are provided as input.
score1 = Score(math=67, english=98, art=76)
print(score1.sum_scores())
print(score1.average())
>>> 241
>>> 80.3333333333
So here's one example. I have a module with multiple classes for computing properties, let's say, Density. Then, I have substances, whom I make inherit the properties, so I can call them afterwards:
class Density():
def __init__(self):
self.rho_method_1_A = None
self.rho_method_1_B = None
self.rho_method_2_A = None
self.rho_method_2_B = None
def density_method_1(self,T):
return self.rho_method_1_A*T + self.rho_method_1_B*T**2
def density_method_2(self,T,P):
return P*(self.rho_method_2_A/T + self.rho_method_1_B*log(T))
class Water(Density):
def __init__(self):
self.rho_method_1_A = 0.2
self.rho_method_1_B = 0.0088
self.rho_method_2_A = 1.9
self.rho_method_2_B = 10
Water.density_method_1(T=300)
Basically, I want the user to be able to set beforehand the method of choice. The problem is, depending on the model that he/she chose, it will either accept only T, or both T and P (in some other cases, maybe T won't even be accepted). Essentially:
density_method = density_method_2 # This is chosen by the user in an outer module
Water.density_method(code magically knows what to put here by detecting the arguments that
density_method_2 accepts)
To be clear: The user itself will know which arguments the method accepts, so if he chose method_2, P will be known on the outer module. I suspect **kwargs and/or decorators are part of the solution, but I can't quite figure it out. Any help is appreciated. Thanks and have a great weekend.
Update: It is relevant to notice that density_method will be called inside a temporal loop of tens of thousands of iterations. So, I'm trying to avoid if/else statements by completely defining density_method before starting the temporal loop.
Possible solution (tested with Python 3.8):
from math import log
class Density():
def __init__(self, method=1):
self.method = method
self.rho_method_1_A = None
self.rho_method_1_B = None
self.rho_method_2_A = None
self.rho_method_2_B = None
def density_method_1(self, T):
return self.rho_method_1_A*T + self.rho_method_1_B*T**2
def density_method_2(self, T, P):
return P*(self.rho_method_2_A/T + self.rho_method_1_B*log(T))
def density_method(self, *args, **kwargs):
if self.method == 1:
return self.density_method_1(*args, **kwargs)
elif self.method == 2:
return self.density_method_2(*args, **kwargs)
else:
raise ValueError("No density method found")
class Water(Density):
def __init__(self, method):
super(Water, self).__init__(method=method)
self.rho_method_1_A = 0.2
self.rho_method_1_B = 0.0088
self.rho_method_2_A = 1.9
self.rho_method_2_B = 10
class Air(Density):
def __init__(self, method):
super(Air, self).__init__(method=method)
self.rho_method_1_A = 0.2
self.rho_method_1_B = 0.0088
self.rho_method_2_A = 1.9
self.rho_method_2_B = 10
water = Water(method=1)
air = Air(method=2)
print(water.density_method(T=1))
print(air.density_method(T=1, P=2))
The solution can be improved but the general idea is to have a "wrapper" method density_method that calls the relevant density_method_* for each sub-class of Density.
Edit (following the comments to my answer):
You should look into python method overloading, like the example here:
https://www.geeksforgeeks.org/python-method-overloading/
from multipledispatch import dispatch
#passing one parameter
#dispatch(int,int)
def product(first,second):
result = first*second
print(result);
#passing two parameters
#dispatch(int,int,int)
def product(first,second,third):
result = first * second * third
print(result);
#you can also pass data type of any value as per requirement
#dispatch(float,float,float)
def product(first,second,third):
result = first * second * third
print(result);
#calling product method with 2 arguments
product(2,3,2) #this will give output of 12
product(2.2,3.4,2.3) # this will give output of 17.985999999999997
i feel like this is a very simple concept but i just cant seem to wrap my head around classes and returning values from them... this what i've come up with to try and practice, very much WIP but i'm stuck here.
thanks in advance
import random
global d6
print("welcome to fight night")
#dice roll
class die():
def __init__(self, sides):
self.sides = sides
def roll(self):
chance = random.randint(1,self.sides)
if chance == 3:
return True
if chance != 3:
return False
d6 = die(6)
class Player():
def __init__(self, name, weight, spec):
self.name = name
self.weight = weight
self.spec = spec
fighter1 = Player("BRUCE LEE", 150, "SUPER SPEED")
fighter2 = Player(GEORGE FORMAN", 225, "REACH")
## how do i return true or false here to check hit?
print(fighter1(name) + "attacks"+ fighter2(name))
d6.roll()
if d6 == True:
print(fighter(name) + "hit" + fighter2(name))
if d6 == False:
print("attack missed")
A few things about class conventions:
The name of a class should typically start with an uppercase letter.
The () after the name of the class is not necessary unless you're
using inheritance.
Code:
class Die:
def __init__(self, number_of_sides):
self.number_of_sides = number_of_sides
def roll(self):
"""
Returns True if the roll succeeds, returns False otherwise.
There is a (1 / self.number_of_sides) chance the roll will succeed.
"""
from random import choice
return choice([True] + [False] * (self.number_of_sides-1))
die = Die(6)
if die.roll():
print("Nice!")
else:
print("Sorry, try again.")
EDIT I think you need a more fundamental example of how the return keyword works:
def give_me_a_number():
return 5 + 4
x = give_me_a_number()
print(x)
Output:
9
d6.roll() returns a value (which is True or False) -- d6 does not become that value, it returns it to you. When you roll a 3 on a real d6, the die does not itself entirely transform into the number 3 in a puff of smoke and mathemagicks, it just shows it to you on one of its faces. :)
So you could do:
if d6.roll():
print(fighter1.name + " hit " fighter2.name)
else:
print("attack missed")
Or if you wanted to be more verbose:
die_result = d6.roll()
if die_result is True:
print(fighter1.name + " hit " fighter2.name)
if die_result is False:
print("attack missed")
I would restructure your die class such that it only returns a random value as the result of roll. You generally want objects (instances of classes) to be independent - the user of the die object should determine what is done with the random value the object generates, not the die itself.
For example, let's say we have many players, of varying strengths. A strong player attacking a weak player should have odds different from a weak player attacking a strong player. This data (strong vs weak) should be inside the player object, not the die object. So I'd make two more methods for the Player, and an attribute like 'strength' which gets an int value...
import random
class Die:
def __init__(self, sides):
self.sides = sides
def roll(self):
chance = random.randint(1,self.sides)
return chance
class Player:
def __init__(self, name, weight, spec):
self.name = name
self.weight = weight
self.spec = spec
def get_stats(self):
return self.spec
def attack(self, target):
odds = self.spec / (self.spec + target.get_stats())
#print(odds)
d6 = Die(6);
temp = d6.roll()
#print(temp)
if (d6.roll() / 6 < odds):
return ("hit")
else:
return ("miss")
if __name__ == "__main__":
print("welcome to fight night")
fighter1 = Player("BRUCE LEE", 150, 100)
fighter2 = Player("GEORGE FORMAN", 225, 100)
for x in range(20):
result = fighter1.attack(fighter2)
print(result)
So, now the Player objects control the odds themselves, not the die objects, making everything more flexible. (Making the Die a local object inside the function is a bit high on overhead, incidentally, but global objects/variables have many issues and are probably best avoided)
I am working on creating a class for the first time, and I am thinking that I have done every thing to get it run, but I still get bunch of issues which is 'list' object has no attribute 'shffule' so the problem here is it will not shuffle the cards, and it will not tell the remaining cards, can any one tell me what am I doing wrong? Thanks in advance
import random
class card_deck:
def __init__(self, rank, suite, card):
self.rank= rank
self.suite = suite
def ranks(self):
return self.rank
def suites(self):
return self.suite
def cards(self,card):
suit_name= ['The suit of Spades','The suit of Hearts', 'The suit of Diamonds','Clubs']
rank_name=['Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King']
def value(self):
if self.rank == 'Ace':
return 1
elif self.rank == 'Jack':
return 11
elif self.rank == 'Queen':
return 12
elif self.rank == 'King':
return 13
def shffule(self):
random.shuffle(self.cards)
def remove(self,card):
self.cards.remove(card)
def cardremaining(self):
self.suite-self.rank
def main():
try:
deck=[]
for i in ['Spades','Hearts', ' Diamonds','Clubs']:
for c in ['Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King']:
deck.append((c, i))
deck.shffule
hand = []
user =eval(input('Enter a number of cards: 1-7 '))
print()
while user <1 or user >7:
print ("Only a number between 1-7:")
return main()
for i in range(user):
hand.append(deck[i])
print (hand)
except ValueError:
print("Only numbers")
main()
Apart from your code containing many small errors; I will try to answer your main problems.
If you are going to use shffule[sic] method of card_deck class, then you first need to create an instance of that class(whereas you tried to call that method with a list). Like this:
deck = card_deck(some_rank,some_suit,some_card)
deck.shffule() #Now you can call the method
Now, since you made it a class instance, you cannot get items from it like hand.append(deck[i])
Unless you defined the method __getitem__ in your class definition, like this:
#this will be in your class definition
def __getitem__(self,i):
return self.card_list[i] #Of course you have to define a list of cards in your class too.
In my opinion, you should spend a little more time trying to understand how is a class defined, how does methods work and how to access members of a class. After that you will be doing much better here
You are never actually creating an instance of the card_deck class. The expression
deck=[]
creates a variable named deck referring to an empty list.
In python, [a, b, c,...] is the syntax for creating list literals.
from collections import namedtuple
Card = namedtuple('Card', 'sign, value') # no need to write class to represent card
SIGNS = ['Hearts', 'Diamonds', 'Spades', 'Clubs']
class Deck:
def __init__(self):
self.cards = [Card(sign, value) for sign in SIGNS for value in range(2,
11) +
'J Q K A'.split()]
def __repr__(self):
return str([str(card) for card in self.cards])
def __len__(self):
return len(self.cards)
def __getitem__(self, item):
return self.cards[item]
def __setitem__(self, key, value):
self.cards[key] = value
deck = Deck()
print deck[11] # indexing works, prints Card(sign='Hearts', value='K')
print len(deck) # prints 52
print deck[13:16] # slicing works
import random
random.shuffle(deck) # shuffle works using no extra code
This question already exists:
Closed 11 years ago.
Possible Duplicate:
Fundamentals of Python Chapter 8 project 3
Hi I am a newbie programmer who just started to learn about python.
I have recently posted this same question before and I have solved it but my answer is not exactly what the question is asking.
I need help on why I need to implement a new method even though I could do the other way.
thanks
Question:
The __str__ method of the Bank class returns a string containing the
accounts in random order. Design and implement a change that causes
the accounts to be placed in the string by order of name.
[this is the part where I don't understand]
(Hint: You will also have to define a new method in the SavingsAccount class.)
class Bank(object):
def __init__(self):
self._accounts = {}
def __str__(self):
"""Return the string rep of the entire bank."""
pTemp =[]
for i in xrange(len(SavingsAccount.temp)-1):
if self._accounts.get(SavingsAccount.temp[i]).getName() >= self._accounts.get(SavingsAccount.temp[i+1]).getName():
temp = SavingsAccount.temp[i]
SavingsAccount.temp[i] = SavingsAccount.temp[i+1]
SavingsAccount.temp[i+1] = temp
for i in SavingsAccount.temp:
pTemp.append(self._accounts[i])
return '\n'.join(map(str, pTemp))
def add(self, account):
"""Inserts an account using its PIN as a key."""
self._accounts[account.getPin()] = account
def remove(self, pin):
return self._accounts.pop(pin, None)
def get(self, pin):
return self._accounts.get(pin, None)
def computeInterest(self):
"""Computes interest for each account and
returns the total."""
total = 0.0
for account in self._accounts.values():
total += account.computeInterest()
return total
class SavingsAccount(object):
"""This class represents a Savings account
with the owner's name, PIN, and balance."""
RATE = 0.02
temp = []
def __init__(self, name, pin, balance = 0.0):
self._name = name
self._pin = pin
self._balance = balance
SavingsAccount.temp.append(self)
def __str__(self):
result = 'Name: ' + self._name + '\n'
result += 'PIN: ' + self._pin + '\n'
result += 'Balance: ' + str(self._balance)
return result
def getBalance(self):
return self._balance
def getName(self):
return self._name
def getPin(self):
return self._pin
def deposit(self, amount):
"""Deposits the given amount and returns the
new balance."""
self._balance += amount
return self._balance
def withdraw(self, amount):
"""Withdraws the given amount.
Returns None if successful, or an
error message if unsuccessful."""
if amount < 0:
return 'Amount must be >= 0'
elif self._balance < amount:
return 'Insufficient funds'
else:
self._balance -= amount
return None
def computeInterest(self):
"""Computes, deposits, and returns the interest."""
interest = self._balance * SavingsAccount.RATE
self.deposit(interest)
def main():
bank = Bank()
bank.add(SavingsAccount("Zelda","1003",5000.00))
bank.add(SavingsAccount("Wilma","1001",4000.00))
bank.add(SavingsAccount("Fred","1002",1000.00))
print bank
main()
I think the question expects you to define ordering in the SavingsAccount class, that is, be able to determine whether an instance of SavingAccounts comes after or before another instance of SavingAccount. I don't want to write any spoiler here, but tell me if my hint is not enough ;).
UPDATE
Also, a common source of errors in Python with string ordering : a comes before z which comes before A which comes before Z ...
UPDATE2
more hints ;)
What you really want here is to sort a list of instances of SavingAccount according to a given criteria. There are 2 way to do this kind of thing. You can either :
have the one doing the sorting take care of it
or you can have the instances stored in your list taking care of it.
The second option is usually better because "the class to be sorted" should know better than anybody else how to sort itself (it's about encapsulation : not letting people outside control how your class works). Even though the question is not really clear, and the example is not very good (in my opinion), this is the option they would like you to chose.
The idea is that the Bank should just do something like this :
class Bank(object):
def __str__(self):
"""Return the string rep of the entire bank."""
#get a sorted copy of the list
#using default SavingAccount comparison
pTemp =sorted(self._accounts)
return '\n'.join(map(str, pTemp))
And SavingAccount contains information about how to sort.
You may want to have a look at this article from the PythonInfo Wiki.
Also: http://docs.python.org/reference/datamodel.html#object.__lt__