class Athlete:
def __init__(self, name, points):
self.name = name
self.points = points
def calculateRacePoints(name):
for i in range(eventTotalVar):
racePoints = checkOverallPlacement(placementVar, eventType=eventVar) + checkPercentagePlacement(placementVar, totalVar, eventType=eventVar) + checkImprovement(seedTime, prelimTime, finalTime) # uses created 2 functions and finds the total
racePoints = racePoints + racePoints
return float(racePoints / eventTotalVar)
This is basically creating an athlete with inputted specifications. It will return the average points attained in the race (total points divided by number of events).
Do classes qualify as an algorithm? If so, do my two functions within it also qualify as an algorithm? What specifically makes an algorithm, well, an algorithm?
Oxford Dictionary defines an Algorithm as:
"A process or set of rules to be followed in calculations or other
problem-solving operations, especially by a computer".
By that definition something as simple as print("Hello World") would technically be considered an algorithm.
looking at your code:
class Athlete:
def __init__(self, name, points):
self.name = name
self.points = points
def calculateRacePoints(name):
for i in range(eventTotalVar):
racePoints = checkOverallPlacement(placementVar, eventType=eventVar) + checkPercentagePlacement(placementVar, totalVar, eventType=eventVar) + checkImprovement(seedTime, prelimTime, finalTime) # uses created 2 functions and finds the total
racePoints = racePoints + racePoints
return float(racePoints / eventTotalVar)
You have multiple algorithms at work.
class Athlete
Contains two or more algorithms
Contains logical and mathematical concepts
def __init__(self, name, points)
Solves the problem of describing who or what the athlete is
It allows you to create an athlete and give that athlete a name and score/points
def calculateRacePoints(name)
Solves the problem of interacting with the athlete
It allows you to get information about this athlete's score/points
Both of your class methods are algorithms that work together to help the program create new athletes and interact with them.
I would imagine you need to provide more detail to complete the assignment, but I hope this gets you started.
Related
I'm trying to get a class to spit out a number with units. The purpose of it having units would be to be able to work with the number later, but without the units getting in the way as a string. Though I have no idea how to do this. I'm quite new with (actually understanding) classes, I'm not even sure if what I ask is possible or not.
My goal is to make a class for making atoms, based on their protons, electrons and neutons. The thing I wanna try is to be able to see the units of the mass (in kgs for my purpose) when I try printing it. Here's what I have:
class Atom:
def __init__(self, protons, electrons, neutrons):
ElemCharge = 1.6021765*(10**-19)
UMAS = 1.66054*(10**-27)
self.protons = protons
self.electrons = electrons
self.neutrons = neutrons
self.charge = ElemCharge*(self.protons - self.electrons)
self.mass = (self.protons + self.neutrons)*UMAS
def main():
Hydrogen = Atom(1,1,0)
print (Hydrogen.mass)
Argon = Atom(18,18,22)
print (Argon.mass)
if __name__ == "__main__":
main()
This code works completely fine, so no worries about that :p
Is there a way to even do this? If so, how can it be done? Thanks!
I'm not sure if this is exactly what you're looking for, but you could have a method inside the Atom class that prints the mass of the atom plus a unit string.
class Atom:
def __init__(self, protons, electrons, neutrons):
ElemCharge = 1.6021765*(10**-19)
UMAS = 1.66054*(10**-27)
self.protons = protons
self.electrons = electrons
self.neutrons = neutrons
self.charge = ElemCharge*(self.protons - self.electrons)
self.mass = (self.protons + self.neutrons)*UMAS
def print_mass_str(self):
print('{} {}'.format(self.mass, 'kg'))
Then this:
Argon = Atom(18,18,22)
print(Argon.mass)
Argon.print_mass_str()
would print:
6.64216e-26
6.64216e-26 kg
There are ways of doing it, but firstly you should ask yourself whether you want this. Having different units can get confusing. You can put conversions at the appropriate places (e.g. after reading the input from user) and have your system work solely on a given unit (that's why we have SI units, after all). Being able to support multiple units internally not only complicates the code, but introduces another source of possible confusion.
There are packages which do this for you, such as units, numericalunits or pint.
An example taken from units documentation is:
>>> from units import unit
>>> metre = unit('m')
>>> second = unit('s')
>>> print(metre(10) / second(2))
5.00 m / s
>>> print(metre(10) ** 3)
1000.00 m * m * m
See how metre creates a meter value, and it keeps track of its usage. It has also support for defining custom units.
Therefore, you could simply store the values in your class as values from units or other package, and you're all set. I looked a bit into the code of units and is quite short and I think it's a good source of learning how to handle stuff like this in your own code.
I have to cite the failure of Nasa Mars Climate Orbiter, which was due to a unit discrepancy.
To override the string representation of the number, make a wrapper class:
class FloatWrapper:
def __init__(self, float, unit):
self.float = float
self.unit = unit
def __getattr__(self, key):
try:
return object.__getattr__(self, key)
except AttributeError:
return getattr(self.float, key)
def __str__(self):
return str(self.float) + self.unit
Now in your __init__, after defining self.mass, add:
self.mass = FloatWrapper(self.mass, 'kg')
This works?
Basically I have added another property to the Atom class so that all objects of type Atom can use it. Another way of doing it would be to pass it as you are doing with the neutrons/protons/electrons. That way it you can perform your own calculations (if there was a requirement to do so) given a unit (say you wanted to show weight in grams for Hydrogen , while in KGs for Argon)
class Atom:
def __init__(self, protons, electrons, neutrons):
ElemCharge = 1.6021765*(10**-19)
UMAS = 1.66054*(10**-27)
self.protons = protons
self.electrons = electrons
self.neutrons = neutrons
self.charge = ElemCharge*(self.protons - self.electrons)
self.mass = (self.protons + self.neutrons)*UMAS
self.massUnit = "kgs"
def main():
Hydrogen = Atom(1,1,0)
print ("{0} {1}".format(Hydrogen.mass,Hydrogen.massUnit))
Argon = Atom(18,18,22)
print ("{0} {1}".format(Argon.mass,Argon.massUnit))
if __name__ == "__main__":
main()
Output
1.66054e-27 kgs
6.64216e-26 kgs
I'm working on a school project which has to store the names of people and their respective score on a test in a list so that I can manipulate it to find averages as well as printing out each persons score with their name. Relatively new to Python so any help is appreciated :)
I would recommend using a dictionary. This pairs keys (the name of students) to values (the score on a test). Here is an example below that gets you the output that you would want.
import math
student_scores = {}
student_scores['Rick'] = 89
student_scores['Pat'] = 79
student_scores['Larry'] = 82
score_list = []
for name, score in student_scores.items():
score_list.append(score)
print(name.title() + "'s score was: " + str(score) + '%')
sum_scores = sum(score_list)
division_scores = len(score_list)
average_score = sum_scores / division_scores
print('The average score was {0:.2f}%'.format(average_score))
I created an empty dictionary that you will use to add student names and scores to a list. So in the dictionary (student_scores) The student name 'Rick' will be a key, and the score 89 will the value. I do this for 2 additional students, pairing their name up with the score that they received.
I create an empty list called score_list. You'll use this list later to add he sum of all scores, and divide by the number of total scores to get an average score for your test.
We start a for loop that iterates over each key and value in your dictionary. For each score, we append it to the empty score list. For each name and score, we print a message showing what the student got on the test.
Now that we have appended the scores to the dictionary we can use the sum method to get the sum of all scores in your score list. We put it in a variable called sum_scores. We also get the number of scores in your list by finding the length of the list (which will be 3 in this case since I put 3 scores in it). We will store that in a variable called division_scores (since I am dividing the sum of all scores by the number of scores recorded). We create a variable called average_score which is the result of the sum of scores divided by the total number of observations.
We then print what the average score was using the .format() method. We just format the average score so that you get it to extend two decimal places {0:.2f}%.
Your output is as follows:
Rick's score was: 89%
Pat's score was: 79%
Larry's score was: 82%
The average score was 83.33%
The above answer is a great data structure for pairing strings. It'll set you on the right track for enumerating scores, averages, etc in simple cases.
Another way to store relationships is with classes (or tuples, at the bottom!) There's a rough sketch of an OOP approach below.
The most important parts are
The properties of the ExamAttempt class store the information (names, scores)
In the Exam.record_attempt method, a new ExamAttempt object is created from the ExamAttempt class and added to the list of attempts on the Exam object.
From here, you could easily add other features. You'd probably want to model a Question and Answer, and maybe a Student object too, if you're going all out. If you store questions and answers, as well as which answer each student selected, you can start doing things like throwing out questions, grading on a curve, discovering questions to throw out, etc. The OOP approach makes it easier to extend functionality like plotting all kinds of fancy graphs, export to CSV or Excel, and so on.
Not all of the code below is necessary.. it can definitely be simplified a little, or reimagined entirely, but hopefully this should give you enough to start looking down that path. Even if it seems complicated now, it's not that bad, and it's what you'll want to be doing eventually (with Python, anyway!)
class ExamAttempt:
def __init__(self, id, name, correct, total):
self.id = id
self.name = name
self.correct = correct
self.total = total
self.score = (self.correct / float(self.total))
def __repr__(self):
return "<ExamAttempt: Id={}, Student={}, Score={}>".format(self.id, self.name, self.score)
class Exam:
def __init__(self, name, questions):
self.name = name
self.attempts = []
self.questions = questions
self.num_questions = len(questions)
def __str__(self):
return "<Exam ({})>".format(self.name)
def load(self, filename):
pass
def saveAttemptsToFile(self, filename):
pass
def record_attempt(self, student_name, num_correct):
id = len(self.attempts) + 1
self.attempts.append(
ExamAttempt(id, student_name, num_correct, self.num_questions))
def get_student_attempt(self, student_name):
for att in self.attempts:
if student_name == att.name:
return att
def get_average_score(self):
return "homework"
def get_results_by_score(self):
return sorted(self.attempts, key=lambda x: x.score, reverse=True)
def get_attempts_by_name(self):
return sorted(self.attempts, key=lambda x: x.name)
if __name__ == '__main__':
questions = ['Question?' for i in range(100)] # Generate 100 "questions" = 100%
exam = Exam('Programming 101', questions)
data = [('Rick', 89), ('Pat', 79), ('Larry', 82)]
for name, correct in data:
exam.record_attempt(name, correct)
for attempt in exam.get_results_by_score():
print("{} scored {}".format(attempt.name, attempt.score))
I am doing a program that simulates population growth, but I am not competent enough to understand how to assign a variable to a newly generated person.
Here's my (very much incomplete) code so far:
from random import seed
from random import randint
seed()
m = "male"
f = "female"
class Person:
def __init__(self, gender, age):
if gender == 0:
self.gender = m
else:
self.gender = f
self.age = age
def person_Birth():
x = Person(randint(0,1), 0)
return x
new_Person = person_Birth() #here's the problem
Every time i want to "cause birth" to a new human, how can i store his/her information separately i.e. automatically assign a new variable to store his/her information without explicitly stating a new variable?
I'm sorry if this is confusing to you, I am not sure of the correct terms.
You need to store the references to the people in a container structure like a list or a dictionary:
people = []
for _ in range(20):
people.append(person_Birth())
Now the people list would contain 20 instances of Person, which you can either iterate over, or access each one individually with people[0] to people[19].
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am having trouble with an hw problem in my CS class. The problem has to do with creating a class in python. Heres the prompt
Your class should be named Student, and you should define the following methods:
__init__: This method initializes a Student object.
Parameters: a name, a GPA, and a number of units taken
• Should initialize instance variables for name, GPA, and units based on
the information that was passed in. If the GPA or number of units is negative, sets it to 0. (Donʼt worry about non-numeric values in this method.)
update: This method updates the instance variables of the Student object if the Student takes a new class.
• Parameters: units for the new class, grade points earned (as a number) in the new class.
• Should modify the instance variable for units to add the units for the new class
• Should modify the GPA to incorporate the grade earned in the new class. (Note that this will be a weighted average using both the unit counts and both sets of GPAs.)
get_gpa: This method should return the studentʼs GPA.
get_name: This method should return the studentʼs name.
Heres what i have
class Student:
def__init__(self,name,GPA,units):
if units <0:
units=0
if GPA<0:
GPA=0
self.name=name
self.GPA=GPA
self.units=units
def update(newunits,GPE):
thats all i can come up with
Let’s go through some points which will hopefully help you:
Constructor (__init__)
If the GPA or number of units is negative, sets it to 0.
So you probably want to check each separately:
if units < 0:
units = 0
if GPA < 0:
GPA = 0
Update method
Methods in general take a reference to the current object as the first argument, named self per convention (just as in __init__). So your update method declaration should look like this:
def update(self, newunits, GPE):
...
Should modify the instance variable for units to add the units for the new class
Just as you did in the constructor, you can access instance variables using self.varname. So you probably want to do something like this:
self.units += newunits
Should modify the GPA to incorporate the grade earned in the new class. (Note that this will be a weighted average using both the unit counts and both sets of GPAs.)
Just as you update self.units you have to update self.GPA here. Unfortunately, I have no idea what a GPA is and how it is calculated, so I can only guess:
self.GPA = ((self.GPA * oldunits) + (GPE * newunits)) / self.units
Note that I introduced a new local variable oldunits here that simply stores the units temporarily from before it was updated (so oldunits = self.units - newunits after updating).
get_gpa and get_name
These are simple getters that just return a value from the object. Here you have an example for the units, i.e. you should figure it out for the actual wanted values yourself:
def get_units (self):
return self.units
Note that it’s rather unpythonic to have getters (get_x methods), as you would just expect people to access the properties directly (while handling them with care).
I'll help you to complete the question, but let me point out a little mistake first:
if units <0 and GPA <0:
units=0
GPA=0
This will set units and GPA to zero only if they are both negative. You'll want to set each to zero if it's negative, even if the other is not. Change it to:
if units < 0: units = 0
if GPA < 0: GPA = 0
Concerning your update method, the correct signature would be:
def update(self, newunits, GPE):
Python object methods should always start with self.
Now, I'm not sure about how to calculate the GPA (we use a different system were I live), but according to some quite google queries, your update method should be something like:
def update(self, newunits, GPE):
GPE_earned_before = self.GPA * self.units
total_GPE = GPE_earned_before + GPE
self.GPA = total_GPE / (self.units + newunits)
self.units += newunits
I used a lot of variables here, to make things clear, but this can be shortened to:
def update(self, newunits, GPE):
self.GPA = (self.GPA * self.units + GPE) / (self.units + newunits)
self.units += newunits
I'm making a game and one of the methods calculates a character's base hit numbers based on skill values. The method currently calculates each value individually, since each skill can be used at short, medium, and long range.
I originally thought I could combine the skills into a tuple and iterate over it, dynamically creating each hit number. But I don't know if it's actually possible, since I currently have each hit number assigned to it's own variable.
I also thought about creating a method for each range, and passing the tuple as an argument. I could create a new tuple or list with the resulting values and then assign them to the individual variables, but I don't see how it would be any better than do it this way, except that it won't look so copy & pasted.
Here's what I currently have:
def calcBaseHitNumbers(self, dict):
"""Calculate character's base hit numbers depending on skill level."""
self.skill_dict = dict
self.rifle = self.skill_dict.get('CRM', 0)
self.pistol = self.skill_dict.get('PST', 0)
self.big_gun = self.skill_dict.get('LCG', 0)
self.heavy_weapon = self.skill_dict.get('HW', 0)
self.bow = self.skill_dict.get('LB', 0)
#self.skill_tuple = (self.rifle, self.pistol, self.big_gun, self.heavy_weapon,
# self.bow)
#---Short range
## for skill in self.skill_tuple:
## self.base_hit_short = skill * 0.6
self.charAttribs.bhCRM_short = self.rifle * 0.6
self.charAttribs.bhPST_short = self.pistol * 0.6
self.charAttribs.bhHW_short = self.heavy_weapon * 0.6
self.charAttribs.bhLCG_short = self.big_gun * 0.6
self.charAttribs.bhLB_short = self.bow * 0.6
#---Med range
self.charAttribs.bhCRM_med = self.rifle * 0.3
self.charAttribs.bhPST_med = self.pistol * 0.3
self.charAttribs.bhHW_med = self.heavy_weapon * 0.3
self.charAttribs.bhLCG_med = self.big_gun * 0.3
self.charAttribs.bhLB_med = self.bow * 0.3
#---Long range
self.charAttribs.bhCRM_long = self.rifle * 0.1
self.charAttribs.bhPST_long = self.pistol * 0.1
self.charAttribs.bhHW_long = self.heavy_weapon * 0.1
self.charAttribs.bhLCG_long = self.big_gun * 0.1
self.charAttribs.bhLB_long = self.bow * 0.1
How would you refactor this so it's more dynamic?
Edit: I guess what I want to do is something like this:
Have a tuple (like the one I commented out) and iterate over it 3 times, each time making a new value (for each skill) based on the modifier for each particular range. The resulting value is then automatically assigned to it's respective variable.
In my head, it makes sense. But when I actually try to code it, I get lost. The problem, I think, is that this is the first "real" program I've written; all I've done before are small scripts.
This is only the 0.1 version of my program, so it's not critical to refactor it now. However, it seems very un-Pythonic to do this manually and I also want to "future-proof" this in case things change down the road.
It feels like what you really want is a class representing the weapon, with attributes to handle the base values and calculate hit values with various modifiers. Here's a simple example:
SHORT_RANGE = 'S'
MEDIUM_RANGE = 'M'
LONG_RANGE = 'L'
SHORT_RANGE_MODIFIER = 0.6
MEDIUM_RANGE_MODIFIER = 0.3
LONG_RANGE_MODIFIER = 0.1
class Weapon(object):
def __init__(self, code_name, full_name, base_hit_value,
short_range_modifier=None, medium_range_modifier=None,
long_range_modifier=None):
self.code_name, self.full_name = code_name, full_name
self.base_hit_value = base_hit_value
self.range_modifiers = {
SHORT_RANGE: short_range_modifier or SHORT_RANGE_MODIFIER,
MEDIUM_RANGE: medium_range_modifier or MEDIUM_RANGE_MODIFIER,
LONG_RANGE: long_range_modifier or LONG_RANGE_MODIFIER,
}
def hit_value(self, range, modifier=1):
return self.base_hit_value * self.range_modifiers[range] * modifier
From there, you might create instances of Weapon inside your Character object like so:
self.rifle = Weapon('CRM', 'rifle', 5)
self.pistol = Weapon('PST', 'pistol', 10)
And then if, say, the character fires the pistol at short range:
hit_value = self.pistol.hit_value(SHORT_RANGE)
The extra argument to the hit_value() method can be used to pass in character- or situation-specific modifications.
Of course, the next step beyond this would be to directly model the weapons as subclasses of Weapon (perhaps breaking down into specific types of weapons, like guns, bows, grenades, etc., each with their own base values) and add an Inventory class to represent the weapons a character is carrying.
All of this is pretty standard, boring object-oriented design procedure, but for plenty of situations this type of thinking will get you off the ground quickly and provide at least a little bit of basic flexibility.
Lets see if I understand you scenario: each weapon has its own distinct hit point so a rifle may have 1, a heavy weapon may have 2 etc. Then each character has a short, medium and long value to be multiplied by the hit point of the weapon.
You should consider using a Strategy design. That is create a weapon superclass with a hit point property. Create sub class weapons for rifle, pistol, bow etc. I am sure that the differences between the weapons are more than just the hit points.
Then the Character has one or more weapons depending on your gameplay. To calculate the hit point for a particular weapon is as simple as
current_weapon * self.medium
If you decide to add more weapons later on then you do not have to edit your Character code because your character can handle any weapon.
In Pseudo Python
class Weapon
hit = 1
#other properties of weapon
class Rifle(Weapon)
#other properties of Rifle
class Pistol(Weapon)
#other properties of Pistol
class Character
weapon = Rifle()
long=0.6
def calcHit()
return self.long*weapon.hit
john = Character()
john.weapon= Rifle()
john.calcHit
#Vinko: perhaps make calcBaseHitNumbers, do the "if not self.calculatedBase:" check internally, and just no-op if it's been done before. That said, I can't see the pressing need for precalculating this information. But I'm no Python performance expert.
What sense of dynamic do you mean? What is likely to vary - the number of skills, or the weighting factors, the number of ranges (short, med, long) or all of these?
What happens to the (e.g.) bhPST_* values afterwards - do they get combined into one number?
One thing that leaps out is that the list of skills is hardwired in the code - I would be inclined to replace the bh variables with a method
So (please take into account I don't know the first thing about Python :) )
def bh_short(self, key)
skill = self.skill_dict.get(key, 0)
return skill * 0.6
Now you can keep a list of skills that contribute to hit points and iterate over that calling bh_short etc.
Possibly also pass the range (long med short) unto the function, or return all three values - this all depends on what you're going to do next with the calculated hitpoints.
Basically, we need more information about the context this is to be used in
I would have a class for the character's attributes (so you don't have heaps of things in the character class) and a class for a weapon's attributes:
class WeaponAttribute(object):
short_mod = 0.6
med_mod = 0.3
long_mod = 0.1
def __init__(self, base):
self.base = base
#property
def short(self):
return self.base * self.short_mod
#property
def med(self):
return self.base * self.med_mod
#property
def long(self):
return self.base * self.long_mod
class CharacterAttributes(object):
def __init__(self, attributes):
for weapon, base in attributes.items():
setattr(self, weapon, WeaponAttribute(base))
Have a CharacterAttributes object in the character class and use it like this:
# Initialise
self.charAttribs = CharacterAttributes(self.skill_dict)
# Get some values
print self.charAttribs.CRM.short
print self.charAttribs.PST.med
print self.charAttribs.LCG.long