Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
65a5168
Update README.md
ketaro Jan 13, 2014
40a3b3a
Spellcheck
Jan 13, 2014
9753907
Exercise 01 README
Jan 14, 2014
4a38f1e
Adding Version Control steps to Ex01
ketaro Jan 14, 2014
1799e31
README
Jan 14, 2014
1858ca1
README
Jan 14, 2014
34e84cb
Update README.md
ketaro Jan 14, 2014
55c2b6f
Adding git
ketaro Jan 15, 2014
a9bbb01
Update README.md
ketaro Jan 15, 2014
3220b53
Fixed some links to learnpython.org
Feb 5, 2014
b4c99f0
fixed more links
Feb 5, 2014
fa3cc4d
moved README to README.md
cdueltgen Feb 7, 2014
7b50ebf
removed README
cdueltgen Feb 7, 2014
a5621c4
formatting
Feb 7, 2014
c0604b4
moved README to README.md
cdueltgen Feb 7, 2014
126c38f
Merge branch 'master' of https://github.com/hackbrightacademy/Hackbri…
cdueltgen Feb 7, 2014
9d6f38b
Update README.md
Feb 7, 2014
c7a39c1
moved README to README.md
cdueltgen Feb 7, 2014
bdf3fab
PRETTY!
Feb 8, 2014
196c9e1
moved readme to README.md
cdueltgen Feb 10, 2014
e5a3650
Update README.md to proper markdown
Feb 10, 2014
1c7d765
moved README to README.md
cdueltgen Feb 10, 2014
429ba59
Update README.md
Feb 10, 2014
8419448
Fixed link to learnpython.org
Feb 10, 2014
32229b7
moving README to README.md
cdueltgen Feb 11, 2014
1a7c0ec
Update README.md
Feb 11, 2014
cd529e1
Update README
ketaro Feb 13, 2014
e409212
moving README to README.md
cdueltgen Feb 13, 2014
9a58f6e
Added resources and fun.
Feb 13, 2014
64185a1
Fixed link
Feb 13, 2014
99ef725
Adding wc
ketaro Feb 13, 2014
bf7c12e
moved README to README.md
cdueltgen Feb 13, 2014
8e3dd60
Update README.md
Feb 13, 2014
583b11b
Adding extra descriptions and test cases for ex9
Feb 15, 2014
56081bb
Fixing tests for fold_paper
ketaro Feb 16, 2014
99fe07f
Fixing test_reverse
ketaro Feb 18, 2014
f2ef476
Swapping Ex06 & Ex07
May 15, 2014
3462961
adding calculator stub
May 15, 2014
a20d6ed
removing old stuff. adding whiteboarding
May 15, 2014
46f0a9e
cleanup
May 15, 2014
fad66f0
readme
May 15, 2014
c0323e9
readme
May 15, 2014
adcf176
'removed broken link'
cadeParade May 27, 2014
5edd80d
correcting tiny typo -- moto -> motto
cadeParade May 27, 2014
1aa5b80
changed link so it works
cadeParade May 27, 2014
fe7c4b8
adding FixErrors
cdueltgen May 28, 2014
429f057
adding description of tests to ex 4 README
cadeParade May 29, 2014
8bee64b
combining ex 6-7 writeup
cadeParade May 29, 2014
04a3b55
combining ex 6-7 writeup
cadeParade May 29, 2014
f87e78b
fixing typo
cadeParade May 29, 2014
d687196
Merge pull request #2 from cadeParade/typos_and_extra_content
cadeParade May 30, 2014
ff19d0c
Folding in ex7 instructions
cadeParade May 30, 2014
a710caf
Moved content to ex 6.
cadeParade May 30, 2014
722ba23
Merge pull request #3 from hackbrightacademy/ex6-7_readme
cadeParade May 30, 2014
af380bc
Update README.md
Jun 4, 2014
caf51ee
Update README.md
Jun 4, 2014
6dc6742
Update README.md
Jun 4, 2014
e4da1f8
Update README.md
Jun 4, 2014
846f0d1
Update README.md
Jun 4, 2014
bc166e8
Update README.md
Jun 5, 2014
9fd84fd
Update README.md
cadeParade Jun 5, 2014
66ee4e8
Editing the description for part 2 allowing you to use functions from…
Steague Jun 6, 2014
d734b5e
Adding note that students may not use dictionaries in Ex05
Jun 6, 2014
fccc435
Update README.md
Jun 9, 2014
cfc3287
Update README.md
ketaro Jun 10, 2014
3ad9c37
Update README.md
Jun 10, 2014
d2e31e1
adding warning about API credentials and Github to Exercise08
Jun 11, 2014
eb0f126
moved old skills2, added new one
cdueltgen Jun 12, 2014
d676d65
Convert unicode apostrophes to ascii
naudo Jun 13, 2014
31c48ef
Update skills1.py
ketaro Jun 13, 2014
0c4b920
adding skills3
Jun 19, 2014
9c38806
Update README.md
ketaro Jun 19, 2014
3934fda
Update README.md
ketaro Jun 19, 2014
7c0d4dd
Update README.md
ketaro Jun 19, 2014
6cea127
Everybody gets a README.md!
naudo Jul 2, 2014
0e91389
Create DataModeling.md
ketaro Aug 21, 2014
c9ee2f1
Update DataModeling.md
ketaro Aug 21, 2014
43c1f48
Update DataModeling.md
ketaro Aug 21, 2014
c4e065a
Update DataModeling.md
ketaro Aug 21, 2014
d3a6383
Delete ListOperations which duplicates ex04 and fix week-1-project RE…
ktel1218 Sep 8, 2014
079b6ec
Add links to Exercise01 README
ktel1218 Sep 8, 2014
b3ed69a
Fix exercise06 README
ktel1218 Sep 8, 2014
b0b1fb4
Fix ambiguous instructions
ktel1218 Sep 9, 2014
b43c339
Fix example, off by one
ktel1218 Sep 11, 2014
7090444
Update README.md
ktel1218 Sep 19, 2014
3e9a172
Merge pull request #5 from ktel1218/patch-1
ketaro Sep 19, 2014
e353fdb
Merge pull request #4 from ktel1218/master
Sep 19, 2014
184f4c7
Updated for revised git processes.
joelburton Sep 30, 2014
43c96d9
Added extra credit
ketaro Sep 30, 2014
d5441eb
added comment re:code review
cdueltgen Oct 2, 2014
7ec388a
Convert twain.txt to standard unix-style text.
joelburton Oct 7, 2014
f183195
Update the logo
naudo Oct 15, 2014
e0b1a93
Switch to doctest for recursion whiteboarding.
joelburton Dec 8, 2014
0f9b864
Remove answers.
joelburton Dec 8, 2014
a754b43
minor reordering, ask for code review and then talk about extra credit
ktel1218 Dec 29, 2014
585f048
Add line asking for code review, make Spark extra credit
ktel1218 Dec 29, 2014
0eeba2a
By request, clearer comments for each step
ktel1218 Dec 29, 2014
3fed447
fixing typo + wording on git reset portion
mmahnken Dec 29, 2014
9bc47a9
add examples to part 1 comments, added descriptions to part 2
ktel1218 Dec 29, 2014
4e272a6
wrong one, no changes made
ktel1218 Dec 29, 2014
7c7fa5b
Needs review of changes to comments/instructions
ktel1218 Dec 29, 2014
9fb6334
updating README with a stopping point.
mmahnken Dec 30, 2014
c239b9f
updating README for code review
mmahnken Jan 6, 2015
f758d81
updating README, adding stopping point
mmahnken Jan 6, 2015
a944168
updating README
mmahnken Jan 6, 2015
c770647
Update README.md
HBCompass Jan 12, 2015
8dc5b3f
Update README.md
rhythmsection Jan 12, 2015
fb68b55
Update README.md
rhythmsection Jan 13, 2015
adc2072
add code review after 4 problems
ktel1218 Jan 13, 2015
b7dfa5b
Merge branch 'master' of https://github.com/hackbrightacademy/Hackbri…
ktel1218 Jan 13, 2015
930c3b6
Update README.md
Jan 13, 2015
e9b8b9a
clarifying instructions on README
mmahnken Jan 13, 2015
12e0e70
grammar fix
mmahnken Jan 13, 2015
66256b8
Update README.md
Jan 14, 2015
df08c10
Update README.md
Jan 14, 2015
1a83102
Update README.md
Jan 14, 2015
1bef605
Update README.md
Jan 14, 2015
1f42b79
Update README.md
Jan 15, 2015
ec01b7c
Update README.md
Jan 15, 2015
5e84cd5
Update calculator.py
Jan 15, 2015
5a387e1
Added note about not using built in list methods
Jan 15, 2015
e7f3ddf
More clarity in instructions, I hope.
Jan 15, 2015
3a649f2
Added more/clearer instructions in the GO section
Jan 15, 2015
f437727
Added no len(l)
Jan 15, 2015
b91277d
Update README.md
Jan 15, 2015
2d48fd6
Fixed inner_four_end example
Jan 16, 2015
aab2a0c
missing "returns" in long_words()
Jan 16, 2015
00e4f49
Update README.md
Jan 20, 2015
728313a
Add Classes exercise
joelburton Jan 22, 2015
a68eead
Add melons.py
joelburton Jan 22, 2015
f7c3e8a
Switch to doctests
joelburton Jan 23, 2015
cbbea53
Make sum_zero less restrictive.
joelburton Jan 23, 2015
14ded1e
fixing typo in count_unique test
mmahnken Jan 24, 2015
de9a191
Fix bug in skills2 doctest
joelburton Jan 24, 2015
1c6f5e0
Merge branch 'master' of github.com:hackbrightacademy/Hackbright-Curr…
joelburton Jan 24, 2015
96b299d
added Forms exercise
cdueltgen Jan 26, 2015
37f5f97
Update README.md
Jan 26, 2015
cf3c3a0
Add skills-javascript.
joelburton Jan 30, 2015
a4c7789
Merge branch 'master' of github.com:hackbrightacademy/Hackbright-Curr…
joelburton Jan 30, 2015
da7abf8
Fix missing bracket.
joelburton Jan 30, 2015
80f46b3
"world" -> "word"
joelburton Jan 30, 2015
26b60a7
it might > might it
ktel1218 Jan 30, 2015
625f257
Typo in isPrime comment
joelburton Jan 31, 2015
839c848
Merge remote-tracking branch 'origin/master'
joelburton Jan 31, 2015
51e6c5a
Update README.md
joelburton Oct 8, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ pip-log.txt

#Mr Developer
.mr.developer.cfg

_book/*
378 changes: 378 additions & 0 deletions Exercise-Classes/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
====================
Exercise for Classes
====================

Ubermelon sells different types of melons. The ways our melon prices and
availability vary can be:

- The species (e.g., Watermelon versus Cantaloupe)

- Whether this melon is imported or grown domestically.

- The shape of this melon. Most melons are natural-shaped (often round or
bullet-shaped) but we also sells melons which have been grown to be square,
at a considerably higher price.

- The season of the melons.

Up until this point, we've kept data about the melons in a simple Python
file (``data.py``) which is a list of tuples of this information.

Our salespeople use the following rules to determine the price of melons:

- Normally, melons cost $5

- The base cost of Casabas and Ogens is $1/each more, though, as they're
harder to grow.

- Imported melons cost 1.5 times as much as they otherwise would, because of
shipping cost.

- Square melons cost 2 times as much as they otherwise would, because of the
much more intense effort to grow them.

Right now, we've just had our salespeople look at the data file and figure out
how much a melon will cost by applying all of these rules to the melon.

So, for example, an foreign-grown natural-shaped Christmas melon would
cost $5 * 1.5 (for being foreign-grown) = $7.50. A Casaba is $9 (base price $5
plus $1 for being a Casba or Ogen, times 1.5 for being imported).

We have some new challenges, though: some of our melons are
discounted for multiple purchases. Starting now, we're offering the following
discounts:

- If you buy 3 or more Watermelons, you get all of them at 75% of what the
cost would otherwise be. So, determine the price for all of the Watermelons
someone wants and, if it's three melons or more, multiply that total by
0.75.

- If you buy 5 or more Cantaloupes, you get them all at half price (because,
really, who likes Cantaloupe *that much*?).

Part I: Classes
===============

This is really a pain for our salespeople, and also makes it hard to get
data right for our web site.

As we've been learning about classes, this seems like a great time to use
classes--since we're combining data *and* functionality.

Look at our requirements:

- Define a class for each melon type that we sell. You should do this in
the ``melons.py`` file (which is empty at the beginning except for
a docstring).

- Add attributes for things like their name/color/shape/origin/seasons

- Add a method with the following signature::

def get_price(qty):
"""Determine price for this quantity of melons of this type.

Return a float of the total price.
"""

This way, we can ask each melon class how much `x` number melons of that
type should cost.

Write the functionality to determine the price for each class of melon.
This will be different for our different types of melons, so this function
will be different, slightly, for each class you made.

- You can test your code by going into the python console and interactively
playing with your classes.

To do so::

$ python -i melons.py

The "-i" command for Python means "run in the interpreter"--it runs your
Python module (file) and leaves you in the Python interpreter, so you can
test out your code.

**Bonus idea:** try it as ``bpython -i``. Yay, code completion, docstrings,
and pretty colors!

At this point, you should be able to try things like::

>>> w = Watermelon()
>>> w.get_price(2)
10
>>> w.get_price(3)
11.25

(the latter price because of our special rule about discounts for quantity
purchases of Watermelons)

When you've built these classes, please **stop and ask for a code review**.


Part II: Hierarchies
====================

Our CEO is always toying with changing the base price of melons from $5 to
something else, sometimes on a whimsical basis.

Right now, you probably have code that looks like this::

class Watermelon(object):
species = "Watermelon"
color = "green"
imported = False
shape = 'natural'
seasons = ['Fall', 'Summer']

def get_price(self, qty):
total = 5.0 * qty
if qty >= 3:
total = total * 0.75
return total

(and similar classes for all of the other melons)

It would be a pain to change the base $5.00 cost of melons for each of the
melons by changing each class individually, though.

You *could* make the base price come from a constant, like::

BASE_MELON_PRICE = 5.00

class Watermelon(object):
species = "Watermelon"
color = "green"
imported = False
shape = 'natural'
seasons = ['Fall', 'Summer']

def get_price(self, qty):
total = BASE_MELON_PRICE * qty
if qty >= 3:
total = total * 0.75
return total


That would make it easier to update--but it wouldn't be flexible enough for
our CEO. Sometimes the CEO talks about making the base price vary on dynamic
things, like the weather that day or the day of the week, or other things.
If we had to put that dynamic logic into each melon type class, we'd be
duplicating a lot of code--so even though it's $5 for now, we want to
plan ahead.

We could solve this by making all of our melons subclass a common base class
(`Melon` might be a good name for this!), and they could get the base price
of melons by calling a method, `get_base_price()` on the parent `Melon` class.
For now, this ``get_base_price`` could just return 5--but we're creating a
"hook" where we could later do something smarter/more complex.

That is, if you change the base price on the Melon class, all of your other
classes would still be able to get the newly-updated cost.

When you've done this, please **stop and ask for a code review**.


Part III: Abstract Classes
==========================

So, in the last part, you probably ended up with a parent class like::

class Melon(object):
def get_base_price(self):
return 5.00

and child classes like::

class Watermelon(Melon):
species = "Watermelon"
color = "green"
imported = False
shape = 'natural'
seasons = ['Fall', 'Summer']

def get_price(self, qty):
total = self.get_base_price() * qty
if qty >= 3:
total = total * 0.75
return total

That's great.

However, some of our other programmers didn't realize we couldn't sell
"plain melons" (ie, not of any particular species!) -- they would create
instances of the `Melon` class and try to get their price::

>>> melon = Melon()
>>> melon.get_price(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Melon instance has no attribute 'get_price'

How can we suggest to other programmers that they shouldn't ever directly
create instances of the base `Melon` class?

There's a good naming convention for this. Go ahead and rename this class
and fix the code to use this naming convention (hint: read about how to do this kind of
replace-everywhere for Sublime! Good programmers are lazy).

However, even with this name change, some of our programmers STILL are
trying to instantiate from this class (that is, make instances of this class).

Think about a way you could prevent them from doing so.

You could do this either by:

- allowing them to make an instance of this class, but giving a better
error message when they try to call ``get_price(qty)`` on it (so you could
raise a message when ``get_price(qty)`` is called on the base class
directly).

or

- disallowing them from making an instance of this class at all. Is there
a method that is always called when an object is created? Can you raise
an error on the base class if you tried to make an instance directly from
it?

Which of these options do you like better?

Whichever you choose, learn how to "raise" an error ("exception") in Python.
You may find https://docs.python.org/2/library/exceptions.html helpful here.
Which of these errors sounds like it would be the most helpful/descriptive
to use?

When you've done this, please **stop and ask for a code review**.

BTW, notice how the Python exceptions are a hierarchy of classes--
this let's you catch a general class of error or a very specific error,
depending on which is what you want. So you can say things like::

try:
7 / 0
except ZeroDivisonError:
print "You can't divide by zero!"

or::

try:
7 / 0
except ArithmeticError:
print "You made some sort of mathy error"

Depending on whether you want to handle zero-division distinctly or just like
other math errors. You could even write something like::

try:
7 / 0
except ZeroDivisonError:
print "You can't divide by zero!"
except ArithmeticError:
print "You made some sort of mathy error"

Which would handle all cases, but handle zero-division separately.

Pretty neat, huh?

Part IV: Flexing Our Hierarchies
================================

Right now, you probably have code like::

class Watermelon(AbstractMelon):
species = "Watermelon"
color = "green"
imported = False
shape = 'natural'
seasons = ['Fall', 'Summer']

def get_price(self, qty):
total = self.get_base_price() * qty
if qty >= 3:
total = total * 0.75
return total

That's fine, but we have a few things we can improve.

Watermelons are our standard base price (except for quantity discounts)
since they're natural-shaped and domestically-grown. If our supplier for
Watermelons switched to being foreign-grown, we'd have to do two things:

- change that attribute to ``imported = True``

- update our ``get_price(qty)`` method to multiply the final price by 1.5,
since that's our markup for imported watermelons

It's easy to imagine that we'd do the first and forget to do the second.
Plus, even if we did, we'd be sprinkling the logic for this all over
the place.

For example, we could do this::

class Watermelon(AbstractMelon):
species = "Watermelon"
color = "green"
imported = False
shape = 'natural'
seasons = ['Fall', 'Summer']

def get_price(self, qty):
total = self.get_base_price() * qty

if qty >= 3:
total = total * 0.75

if self.imported:
total = total * 1.5

return total

And then we can't forget to update the price if the origin changes--but
we'd have a lot of duplicate code throughout.

Better would be for our base class, ``AbstractMelon``, to handle much of
our price calculating, but for it to rely on the attributes set on the
individual melon type.

In this ``get_price()`` for `AbstractMelon`, We'd need to get the "add-on" $1
for Casaba and Ogen somehow, then the total based on shape/origin/quantity.
For Watermelons and Cantaloupe, we'll need to then apply our discounts.

Create a method on the base class to handle this work. Where needed,
use that method from the individual melon classes.

To do this, it's probably going to be helpful to put an attribute on the
the Casaba and Ogen class to keep track of their $1 base price bump;
your logic in the base class ``get_price()`` could use that.

When you've done this, please **stop and ask for a code review**.

Part IV: Is the Melon Available?
================================

*(This section is advanced and optional)*

For availability, we keep track of the season that a melon is available for
purchase. We define these as:

- Winter: Jan, Feb, Mar
- Spring: Apr, May, Jun
- Summer: Jul, Aug, Sep
- Fall: Oct, Nov, Dec

Add a function onto our AbstractMelon class that tells us whether a
particular melon is available for sale today.

To do this, you'll want to learn about the Python `datetime` library. This
has features to give you today's date, as well as ways to figure out the
month part of that.

Create a function that returns `True` or `False` to let us know whether
this melon is available today.

Advanced: Update this function to *optionally* take a date argument so
that, if one is given, we check for melon availability on that date. If
no argument is given, it should use today's date. This requires a little
clever thinking around optional arguments.

When you've done this, please **stop and ask for a code review**.
Empty file added Exercise-Classes/__init__.py
Empty file.
Loading