Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialamandae
15,727 Pointsint object has no attribute 'num_die'
Hi. I'm stuck on this one. Much appreciation to anyone who can get me out of the mud!
I set this up a bit differently from the video, but it seems like it should work. PyCharm tells me the num_die attribute is an integer, but when the code runs, it says int object has no attribute 'num_die'
The die class and the die roller class work just fine, but then it stops in the for-loop of the dice_hand method.
It also seems like I should be able to call dice_hand without passing in arguments, because all of them are listed with default values, but it requires something. A number (ex. 10) or a variable (see below) work equally well.
In the DiceHand class, it seems like the initilaization of the dictionary should be self.dh_dict - but this returns and unresolved reference to self. Any idea why this is?
# main.py
from die import Die, DieRoll
from dice_hand_file import DiceHand
try_die = Die()
try_die_roll = DieRoll.roll_die(try_die)
print(try_die_roll)
try_die_hand = DiceHand.dice_hand(try_die_roll)
print(try_die_hand)
# die.py
import random
class Die:
# creates a single die
def __init__(self, sides=6, value=None):
self.sides = sides
self.value = value
def __int__(self):
return int(self)
def __add__(self, other):
return int(self) + other
class DieRoll(Die):
def __init__(self):
super().__init__()
# rolls a single die
def roll_die(self):
if self.value is None:
self.value = random.randint(1, self.sides + 1)
return self.value
else:
return self.value
# die_hand_file.py
from die import DieRoll
class DiceHand(DieRoll):
def __init__(self, num_die=5, dh_dict=None, die_counter=0):
super(DieRoll).__init__()
self.num_die = num_die
self.dh_dict = dh_dict
self.die_counter = die_counter
# returns a dictionary with the die number(key) and the value rolled by that die(value)
dh_dict = {}
def dice_hand(self):
for _ in range(self.num_die + 1):
self.die_counter += 1
self.dh_dict[self.die_counter] = self.roll_die()
return self.dh_dict
amandae
15,727 PointsHi, Chris. Thank you for continuing to help! Once I get this figured out, I think so much will fall together.
So, I'm guessing, from your question, that dh_dict=dh_dict
isn't defined anywhere. But, it also shouldn't be dh_dict2. dh_dict2 is created in the DiscardHand.save_dice()
function and will be passed to the NextRoll class (still being written).
The dh_dict is returned from the DiceHand.dice_hand()
function. This filled dictionary needs to come into the DiscardHand class to be used by the DiscardHand.reroll()
and DiscardHand.save_dice()
functions. So, what I was trying to do (unsuccessfully - you can see my confusion) is to tell the super().__init__ ()
function to pack up dh_dict in the passenger seat and bring it along - because it is defined in the parent class (DiceHand).
If I don't give any arguments to super().__init__()
, it will bring in dh_dict, but it is always empty.
Does what I'm trying to do make sense? What am I missing?
3 Answers
jb30
44,806 PointsThe value of try_die_roll
is set at try_die_roll = DieRoll.roll_die(try_die)
, and is a random number. You then used try_die_hand = DiceHand.dice_hand(try_die_roll)
, which passes a random number into DiceHand.dice_hand
and uses it as the value for self
, so self.num_die
tries to get the attribute num_die
from your random number.
You could create an instance of DiceHand with curr_hand = DiceHand()
and use it to get a value for try_die_hand
by try_die_hand = curr_hand.dice_hand()
. You could also simplify try_die_roll = DieRoll.roll_die(try_die)
as try_die_roll = try_die.roll_die()
.
Instead of def __init__(self, num_die=5, dh_dict=None, die_counter=0):
, have you considered using {}
as the default value for dh_dict
, as in def __init__(self, num_die=5, dh_dict={}, die_counter=0):
?
amandae
15,727 PointsThank you. I'm still working through the whole answer, but I have one question right off. Setting the dh_dict to an empty dictionary by default is exactly how I started, but PyCharm threw warning - not an error, but a warning. It said a default parameter should not be mutable. Any ideas why, or if it is the best solution, despite the warning?
amandae
15,727 PointsI have more questions. I am really trying to understand this and finish an object oriented project, so I'm just going to keep asking questions, because I'm not understanding what I'm not understanding. Any help is appreciated.
When I use try_die_roll = try_die.roll_die()
I get an attribute error - Die object has no attribute 'roll_die.'
When I use try_die_roll = try_die.DiceRoll.roll_die()
I get an attribute error - Die object has no attribute 'DiceRoll.'
But, try_die_roll = DieRoll.roll_die(try_die)
functions correctly.
What am I missing here?
Thanks, again!
jb30
44,806 PointsIf you want to use the roll_die method on try_die, then try_die would need to be an instance of DieRoll
rather than of Die
, so you would need to have try_die = DieRoll()
, since the class DieRoll
has a roll_die
method and the class Die
does not.
amandae
15,727 PointsNext question...
Thank you in advance for everyone's patience.
When I implement
try_curr_hand = DiceHand()
try_die_hand = try_curr_hand.dice_hand()
it returns "DiceHand object has no attribute 'value'"
whereas the orginal -
try_die_hand = DiceHand.dice_hand(try_die_roll)
or try_die_hand = DiceHand.dice_hand(5)'
returns 'int' object has no attribute 'num_die'
It is a different error, and sometimes that is a good start, but why does self.value in Die suddenly not exist?
amandae
15,727 PointsYea! Okay. I got the roll_die() method to work on try_die! This makes more sense to me. I didn't understand I could call a class without first instantiating the parent. I don't think we ever did that in the video. So, if I'm understanding correctly, I only need to call the Die class if I want to change the default parameters. For example, when I wanted to use a coin instead of a standard die, or to add a value for testing purposes. Thank you!
jb30
44,806 PointsIn the class DiceHand, instead of super(DieRoll).__init__()
, use super().__init__()
.
Apparently, Python does weird things with mutable default parameters, so keep dh_dict=None
, and inside your init function, you can check if dh_dict is None and set it to {}
.
amandae
15,727 PointsThank you for the clear explanation of how I was calling in a random number. I understand much better (and had a true face-palm moment).
Here's my follow-up question.
When I call dice_hand, why do I need arguments at all? Every parameter has a default, so it seems like it should call with just the parenthesis.
amandae
15,727 PointsIt works!
Yea!
Thank you so much!!
Never mind the previous question. It solved itself when I changed the super argument.
amandae
15,727 PointsUmmmm... sigh.... I got excited too soon...
It does run now, but it always calls the same random number. Every time I run the program, it is a different number, but all six values in the dictionary are the same.
For example:
{1: 3, 2: 3, 3: 3, 4: 3, 5: 3, 6: 3}
Any ideas?
If I'm seeing it correctly, self.roll_die is only running once. This goes back to the if-else clause in the roll_die function. It states that if value is already assigned, then it takes that value. Kenneth started with this logic in the videos to add testing functionality. I obviously haven't thought about it too much, but I don't know how to preserve that testing functionality while still calling for consecutive random numbers.
jb30
44,806 PointsYou could create a new instance of DiceRoll whenever you want a new random value, and call roll_die()
on the new instance of DiceRoll, but then you might want to reconsider DiceHand inheriting from DiceRoll,
You could change def roll_die(self):
to def roll_die(self, modify_value=False):
and then recalculate the value if you pass in True, but I don't know if that will preserve testing functionality enough for you.
Chris Freeman
Treehouse Moderator 68,441 PointsPyCharm is correct that a mutable object is a poor choice for a parameter default since the values in the mutable object may persist between calls. This side effect and be purposefully used but with caution.
Chris Freeman
Treehouse Moderator 68,441 PointsSince DiceHand
derives from DieRoll
which derives from Die
there is only one value
attribute that is set on the first call of roll_die
. Subsequent calls to roll_die
see self.value is None
as False
returning literally the same value each time.
Perhaps DiceHand
is not a subclass of DieRoll
but instead, calls self.dice_hand() from __init__
to create self.dh_dict
using separate instances of DieRoll()
.
amandae
15,727 Pointsrefactoring now.... Conflating classes and figuring out what to do with the value= for testing. I'm not sure if I need it, but I suppose it is good practice. It will be helpful when it comes to scoring.
This is soooo helpful! You all are the best!
I will post back when I have more - hopefully a solution!
amandae
15,727 PointsOkay. Here's my solution so far. It works! So exciting!
Another question follows these two sets of code...
# die.py
import random
class DieRoll:
# creates a single die
def __init__(self, sides=6, value=None):
self.sides = sides
self.value = value
def __int__(self):
return int(self)
def __add__(self, other):
return int(self) + other
# rolls a single die
def roll_die(self):
self.value = random.randint(1, self.sides)
return self.value
# This code is for testing the score-sheets - it is activated when needed and then rehashed out.
#
# if self.value is None:
# self.value = random.randint(1, self.sides)
# return self.value
# else:
# return self.value
I decided to go the simple route and simply employ different code when I need to test the score-sheet. It isn't the most graceful way, but it is the simplest to keep me moving on this project. I might come back at the very end and see if this can be improved.
I also conflated these two classes (Die and DieRoll). It seems like a die would always be rolled, so it wasn't of much value to have them separately.
#dice_hand_file.py
from die import DieRoll
class DiceHand(DieRoll):
def __init__(self, num_die=5, dh_dict=None, die_counter=0):
super().__init__()
# creates a dictionary or clears the dictionary for the next hand
if dh_dict is None:
dh_dict = {}
else:
dh_dict.clear()
self.num_die = num_die
self.dh_dict = dh_dict
self.die_counter = die_counter
# returns a dictionary with the die number(key) and the value rolled by that die(value)
def dice_hand(self):
for _ in range(self.num_die):
self.die_counter += 1
self.dh_dict[self.die_counter] = self.roll_die()
return self.dh_dict
This part works great! Thank you for your help! At least for now, I have decided to keep this class separate in order to have clarity with the next class, but I might eventually follow your advice and conflate it with the DieRoll class. I just can't quite see how that would work right now.
I can't figure out how to initialize the next class. I seem to be missing an important key in understanding super(). I'm pretty sure there are some mistakes in the methods of the code, also, but I can't get past the instantiation to work on them. For example, I'm pretty sure the reroll_ask will return the location of the map object in memory instead of a list, and I'm not sure how to fix that.
# continues from above in die_hand_file.py
class DiscardHand(DiceHand):
def __init__(self):
super().__init__()
# This was my first try at the init -- to say the least, it didn't work.... sigh...
# def __init__(self, dh_dict, reroll_input, reroll, num_die_2, dh_dict_2):
# super().__init__(num_die=self.num_die, dh_dict=self.dh_dict, die_counter=self.die_counter)
# self.dh_dict = dh_dict
# self.reroll_input = reroll_input
# self.reroll = reroll
# self.num_die_2 = num_die_2
# self.dh_dict_2 = dh_dict_2
# chooses the dice to reroll in next hand and creates list of the index of those dice
def reroll_ask(self):
self.reroll_input = input(f'Which die would you like to re-roll, by die number? (ex 1, 3, 4) ')
self.reroll = self.reroll_input.split(',*')
self.reroll = map(int, self.reroll)
return self.reroll
# The number of dice to be rerolled in next hand
def next_num_die(self):
self.num_die_2 = len(self.dh_dict) - len(self.reroll)
return self.num_die_2
# removes the reroll dice from hand and keeps the saved dice in the dictionary
def save_dice(self):
self.dh_dict_2 = self.dh_dict
for i in self.reroll:
self.dh_dict_2 = self.dh_dict.pop(i)
return self.dh_dict_2
The first attempt just broke the program. The second thing I tried was to add the dh_dict to both init's . That also brought errors. The version above doesn't draw errors, but it also doesn't bring in the dictionary that was just created.
Just for a complete view, here's my main.py file, also.
# main.py
from die import DieRoll
from dice_hand_file import DiceHand, DiscardHand
try_die = DieRoll()
try_die_roll = try_die.roll_die()
print(try_die_roll)
curr_try_hand = DiceHand()
try_die_hand = curr_try_hand.dice_hand()
print(try_die_hand)
try_discard = DiscardHand()
print(try_discard.reroll_ask())
print(try_discard.next_num_die())
print(try_discard.save_dice())
Again, thank you so much for your help, and thank you in advance to everyone who helps from here on out!
I will understand OOP! Soon!
amandae
15,727 PointsI added the =False functionality to the RollDie class (see below). It works exactly as it should for one die. Thank you!
My sticking point is that I can't figure out how to pass that die along to the DiceHand class to roll an entire hand of the appointed value. How does that work?
I'm guessing that problem wouldn't happen if I had combined the DieRoll and DieHand classes, as you suggested. I'm starting to see the logic there. My confusion is why Kenneth kept them apart in the video. It could make sense to me if everything about rolling the dice was in one class, with other classes for players, scoring, and scoresheets. It could also make sense that the dice hand is a different object than an individual die. I'm trying to understand why it would be better one way or the other - or is it just preference?
# rolls a single die
def roll_die(self, test_vlaue=False):
if test_vlaue is False:
self.value = random.randint(1, self.sides)
return self.value
else:
return self.value
test_die = DieRoll(6, 5)
test_die_roll = test_die.roll_die(True)
# this works. It will roll a 5 every time.
print(test_die_roll)
test_hand = DiceHand()
curr_try_hand = test_hand.dice_hand()
# this doesn't work. It will give random numbers.
print(f'test hand{curr_try_hand}')
jb30
44,806 Points # super().__init__(num_die=self.num_die, dh_dict=self.dh_dict, die_counter=self.die_counter)
You haven't defined self.num_die
, self.dh_dict
, or self.die_counter
before that point in the program. You could try passing your parameters into init using super().__init__(num_die=num_die, dh_dict=dh_dict, die_counter=die_counter)
and remove the other lines in the constructor that set self.num_die
, self.dh_dict
, and self.die_counter
after calling super
.
If you want self.reroll to be a list, you could try self.reroll = list(map(int, self.reroll))
.
Chris Freeman
Treehouse Moderator 68,441 PointsIt looks like DiscardHand
is a DiceHand
with a few more methods. This structure is fine if that is the goal. You don't have to define DiscardHand.__init__
if it is to behave exactly like the __init__
in DiceHand
(that's how inheritance is supposed to work!). A call to DiscardHand()
will call theDiceHand
version automatically and will expect the same parameters.
If the DiscardHand.__init__
method has additional work to be done, then use the catchall:
class DiscardHand(DiceHand):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# other work to be done here
jb30
44,806 PointsInstead of
def dice_hand(self):
for _ in range(self.num_die):
self.die_counter += 1
self.dh_dict[self.die_counter] = self.roll_die()
return self.dh_dict
you could try something like
def dice_hand(self):
temp_sides = self.sides
self.sides = self.sides ** self.num_die
temp_value = self.roll_die()
self.sides = temp_sides
for counter in range(self.num_die):
self.dh_dict[counter] = (temp_value % self.sides) + 1
temp_value = temp_value // self.sides
return self.dh_dict
This won't directly work when you start re-rolling values, but it would give you random values for each of your dice. Instead of calling self.roll_die()
for each dice, it calls it once for a die with more sides, one side for each possible permutation of rolls of the dice. Then for each die, it sets self.dh_dict[counter]
to a number between 1 and self.sides
based on the random value. It then does integer division on the random value to get another value to compare against.
When I tried running dice_hand
multiple times while using self.die_counter
to place things in self.dh_dict
, the dictionary kept getting longer as the same values were added to it each time I called dice_hand
, since self.die_counter
was not reset and never decreased.
amandae
15,727 Pointsjb30 -
Thank you so much for continuing to help!
I noticed the same thing. I got around it by creating a new instance of the DiceHand for each call, which is SLOPPY, but it worked. I cannot figure out why it is doing that, because there is nothing in obvious logic which would cause it! I was worried that when I got to the re-roll of the second dice, that it would give me a double dictionary, so maybe your way would work better. Right now, I'm still trying to get the dictionary passed into the DiscardHand function. That function seems to be working, but it always starts with an empty dictionary... As I said earlier, I think there is something fundamental I'm not understanding about super() and init()... More about that in my next question.
amandae
15,727 PointsI think I figured out the map function in the DiscardHand class. If I specifically change it to a list in every place, it will work. I still haven't figured out how to take the dictionary from the DiceHand class and use it in the DiscardHand class. I had the same problem with the test value for the Die passing into the DiceHand class, and I decided it wasn't important enough to mess with just for testing. But this, on the other hand, is necessary.
In the code below, other than dh_dict staying outside of the class, everything works (as far as I can tell). In order to make it work, I had to give every parameter a default value. This doesn't make sense, and isn't what I've seen in the (many) videos and blogs I've watched/read. The other option would be to define those attributes outside of the init, but PyCharm tells me this is unacceptable, even though it does run.
In the code below, I tried many things in the super()__init__()
, but the one which seems most likely to work is dh_dict=dh_dict
. This returns dh_dict is undefined
. I also commented out the dh_dict.clear
from the init method of the DiceHand, just in case I was somehow clearing it before I passed it on. But, this doesn't seem to make a difference.
# --- main.py ---
from die import DieRoll
from dice_hand_file import DiceHand, DiscardHand# , DiceHand2
# prints one roll of one die
try_die = DieRoll()
try_die_roll = try_die.roll_die()
print(try_die_roll)
# *******************************************************************
# prints one die with a value of 5. In theory, this should also print an entire hand with values of 5, but it doesn't.
# It also only accepts arguments in this format. Using value=5, isn't accepted.
test_die = DieRoll(6, 5)
test_die_roll = test_die.roll_die(True)
print(test_die_roll)
test_hand = DiceHand()
curr_try_hand = test_hand.dice_hand()
print(f'test hand{curr_try_hand}')
# ***************************************************************
curr_try_hand = DiceHand()
try_die_hand = curr_try_hand.dice_hand()
print(try_die_hand)
# **************************************************************
try_discard = DiscardHand()
print(try_discard.reroll_ask())
print(try_discard.next_num_die())
print(try_discard.save_dice())
# die.py
# I will probably change this per suggestion, but this is as it stands for the moment.
import random
class DieRoll:
# creates a single die
def __init__(self, sides=6, value=None):
self.sides = sides
self.value = value
def __int__(self):
return int(self)
def __add__(self, other):
return int(self) + other
# rolls a single die
def roll_die(self, test_vlaue=False):
if test_vlaue is False:
self.value = random.randint(1, self.sides)
return self.value
else:
return self.value
#dice_hand_file.py
from die import DieRoll
class DiceHand(DieRoll):
def __init__(self, num_die=5, dh_dict=None, die_counter=0, *args, **kwargs):
super().__init__()
if dh_dict is None:
dh_dict = {}
# else:
# dh_dict.clear()
self.num_die = num_die
self.dh_dict = dh_dict
self.die_counter = die_counter
# returns a dictionary with the die number(key) and the value rolled by that die(value)
def dice_hand(self):
for _ in range(self.num_die):
self.die_counter += 1
self.dh_dict[self.die_counter] = self.roll_die()
return self.dh_dict
class DiscardHand(DiceHand):
def __init__(self, reroll_input='', reroll=None, num_die_2=0, dh_dict_2=None, *args, **kwargs):
super().__init__(dh_dict=dh_dict)
if reroll is None:
reroll = []
if dh_dict_2 is None:
dh_dict_2 = {}
# self.dh_dict = dh_dict
self.reroll_input = reroll_input
self.reroll = reroll
self.num_die_2 = num_die_2
self.dh_dict_2 = dh_dict_2
# chooses the dice to reroll in next hand and creates list of the index of those dice
def reroll_ask(self):
self.reroll_input = input(f'Which die would you like to re-roll, by die number? (ex 1, 3, 4) ')
self.reroll = self.reroll_input.split(',*')
self.reroll = map(int, self.reroll)
return list(self.reroll)
# The number of dice to be rerolled in next hand
def next_num_die(self):
self.num_die_2 = len(self.dh_dict) - len(list(self.reroll))
return self.num_die_2
# removes the reroll dice from hand and keeps the saved dice in the dictionary
def save_dice(self):
self.dh_dict_2 = self.dh_dict
for i in self.reroll:
self.dh_dict_2 = self.dh_dict.pop(i)
return self.dh_dict_2
Chris Freeman
Treehouse Moderator 68,441 Points(comment moved from above)
In this snippet, where is dh_dict
defined?
class DiscardHand(DiceHand):
def __init__(self, reroll_input='', reroll=None, num_die_2=0, dh_dict_2=None, *args, **kwargs):
super().__init__(dh_dict=dh_dict)
# should this be dh_dict2? ^^^^^^^
jb30
44,806 PointsIn your code
class DiceHand(DieRoll):
def __init__(self, num_die=5, dh_dict=None, die_counter=0, *args, **kwargs):
super().__init__()
have you tried using super().__init__(*args, **kwargs)
instead? That should allow you to do test_hand = DiceHand(value=5)
.
super()
gets called as the first line of the function. Changing values of variables later in the function shouldn't affect what happens when super()
gets called.
If you don't pass arguments into super()
, then your superclass would need default values for its parameters because it's expecting values for all of its parameters. Your superclass won't need default values for parameters that you pass to it every time.
# The number of dice to be rerolled in next hand
def next_num_die(self):
self.num_die_2 = len(self.dh_dict) - len(list(self.reroll))
return self.num_die_2
It's possible to get a negative number as self.num_die_2
. It also looks like you are returning the number of dice that you aren't rerolling in the next hand contrary to the comment above it.
Chris Freeman
Treehouse Moderator 68,441 PointsHey amandae, I wanted to start a new thread regarding super()
. It doesn't start with the inheritance. It ends there.
A class is defined with it's attributes and methods. When running the class code, any reference not found locally is searched for in any inherited ("parent") classes. Inheriting is really just including the parent classes namespace.
When a new class instance is created, the default __new__
method (usually inherited from the base object
class) is run. By default the __new__
methods calls the __init__
method. The first __init__
found will be run (locally or from an inherited class). But what if we want to run the local __init__
and one from a parent? This is the purpose of calling super()
.
Calling super()
simply says "pause here to run the next found init method down the chain of inherited classes". This can cause a daisy chain of calls if an inherited class also utilizes super()
.
So, running the code try_discard = DiscardHand()
does the following
* calls DiscardHand.__new__(*args, **kwargs)
* calls DiscardHand.__init__(*args, **kwargs)
* running DiscardHand.__init__(*args, **kwargs)
* calls super().__init__(dh_dict=dh_dict) ==> DiceHand.__init__(dh_dict=dh_dict)
* running DiceHand.__init__(dh_dict=dh_dict) **(note `dh_dict` not defined yet)**
* calls super().__init__() ==> DieRoll.__init__()
* running DieRoll.__init__()
self.sides = sides
self.value = value
* return to `DiceHand`
* contiinue in DiceHand.__init__
if dh_dict is None:
dh_dict = {}
# else:
# dh_dict.clear()
self.num_die = num_die
self.dh_dict = dh_dict
self.die_counter = die_counter
* return to `DiscardHand`
* contiinue in DiscardHand.__init__
if reroll is None:
reroll = []
if dh_dict_2 is None:
dh_dict_2 = {}
# self.dh_dict = dh_dict
self.reroll_input = reroll_input
self.reroll = reroll
self.num_die_2 = num_die_2
self.dh_dict_2 = dh_dict_2
* return to DiscardHand.__new__
* return new instance of `DiscardHand` which is assigned to `try_discard`
Note that the self
in all this code points to the same newly created instance.
Running your code gets as predicted:
$ python main.py
5
5
test hand{1: 3, 2: 4, 3: 6, 4: 6, 5: 1}
{1: 3, 2: 1, 3: 2, 4: 3, 5: 3}
Traceback (most recent call last):
File "main.py", line 25, in <module>
try_discard = DiscardHand()
File "/home/chris/devel/Treehouse/forum/amandae/dice_hand_file.py", line 28, in __init__
super().__init__(dh_dict=dh_dict)
NameError: name 'dh_dict' is not defined
amandae
15,727 Pointsjb30 and Chris Freeman - Thank you, so much! I will work on this more and post back later - probably Monday.
jb30
44,806 PointsHalf of my original answer is inaccurate, so this answer should get Best Answer.
Chris Freeman
Treehouse Moderator 68,441 Pointsjb30 , one can always edit comments for clarity and correctness 🙂
amandae
15,727 PointsHi. Chris Freeman and jb30.
Thank you so much for all of your help on this one! I have put lots of the little pieces together, and understand SO MUCH better than I did before.
I am going to leave this for a while and come back to it at a later point. I think to go any farther is above my head right now.
I wish I could give both of you best answers!
Thank you, again!
Chris Freeman
Treehouse Moderator 68,441 PointsYou’re very welcome! Please give jb30 the Best Answer award. (I’ve also recommended them to be a moderator for the quality of their answers)
Chris Freeman
Treehouse Moderator 68,441 PointsChris Freeman
Treehouse Moderator 68,441 PointsComment move to end of thread (sorry using iPhone and added my comment in the wrong place)