What I don’t understand is how making the __add__
method return Molecule([self, other])
“returns a Molecule with the two Atom
s” like the exercise tells us to do. I’ve tried uncommenting the comment in line 16 and printing out salt but all that’s printed out is “<main.Molecule object at 0x7f66084df6a0>”. How is “<main.Molecule object at 0x7f66084df6a0>” a molecule with the two atoms? ;-;
Do you have reason to expect any other output?
Perhaps you might write code which causes a different string representation of your object.
I was expecting the output to be “NaCl”, as it’s a molecules with 2 atoms (I think). This was my initial solution to the exercise:
class Atom:
def init(self, label):
self.label = label
def add(self, other):
return self.label + other.label
class Molecule:
def init(self, atoms):
if type(atoms) is list:
self.atoms = atoms
sodium = Atom(“Na”)
chlorine = Atom(“Cl”)
salt = Molecule([sodium, chlorine])
salt = sodium + chlorine
print(salt)
“NaCl” gets printed to the console. But this wasn’t the right answer. My question now is how is the answer presented by codecademy a molecule with 2 atoms?
In order to expect that output there would need to be code which writes those specific characters to stdout. There’s not. So no reason to expect it. The number of atoms wouldn’t affect this. You could print out an atom and get a similar result, again, no code that is doing string formatting for that.
What affects the string representation of an object?
Oh I get it now. repr() is the method responsible for the string representation of an object not add(), so my solution was definitely wrong. And by making add() return Molecule([self, other]) we are literally returning a molecule with 2 atoms.
Thanks a lot for taking your time to reply. I was afraid no one would answer at first
Try add the following code inside of the Molecule class as the dunder method. Then try to print your “”.
def __repr__(self):
molecular_formula = ""
for index in range(len(self.atoms)):
molecular_formula += salt.atoms[index].label
return molecular_formula
This should definitely be added as a second task for this exercise, thank you!
Added some string representation to help see results.
class Atom:
def __init__(self, label):
self.label = label
def __repr__(self):
return self.label
def __add__(self, other):
return Molecule([self, other])
class Molecule:
def __init__(self, atoms):
if type(atoms) is list:
self.atoms = atoms
def __repr__(self):
return str(self.atoms)
sodium = Atom("Na")
chlorine = Atom("Cl")
salt = Molecule([sodium, chlorine])
print("Original Salt: " + str(salt))
newsalt = sodium + chlorine
print("New Salt: " + str(newsalt))
This confuses me even more. Shouldn’t the result be “NaCl” not the list?
I really, really just don’t understand this at all. The RGB example made sense but the exercise is totally throwing me for a loop. Grrrrr!!!
You are correct. I probably should have returned the string NaCl instead of the string [Na, Cl].
I was lazy and returned the string version of the list.
I could rewrite Molecule so it uses this return line instead.
return (f"{salt.atoms[0].label}{salt.atoms[1].label}")
Thanks to @mtf for that line.
I just wish we could go back to that lesson and join all the pieces of this conversation. The link in the above page no longer works. Is anybody closely connected enough to put us back in touch?
Another fun way to unpack this at the end using the asterisk and string formatting.
class Atom:
def __init__(self, label):
self.label = label
def __repr__(self):
return str(self.label)
def __add__(self, other):
return Molecule([self, other])
class Molecule:
def __init__(self, atoms):
if type(atoms) is list:
self.atoms = atoms
def __repr__(self):
return str(self.atoms)
sodium = Atom("Na")
chlorine = Atom("Cl")
salt = Molecule([sodium, chlorine])
print("Original Salt: " + str(salt))
newsalt = sodium + chlorine
print("New Salt: {}{}".format(*newsalt.atoms))
You can try this if you want to find the molecule printed with the atoms in the list side by side, ie: [‘Na’, ‘Cl’]
class Atom:
def __init__(self, label):
self.label = label
def __add__(self, other):
return Molecule([self.label, other.label])
class Molecule:
def __init__(self, atoms):
if type(atoms) is list:
self.atoms = atoms
def __repr__(self):
return "{}".format(self.atoms)
sodium = Atom("Na")
chlorine = Atom("Cl")
salt = Molecule([sodium, chlorine])
salt = sodium + chlorine
print(salt)
The __repr__
isn’t even necessary. We already have enough methods and instance variables to achieve this.
class Atom:
def __init__(self, label):
self.label = label
def __add__(self, other):
return Molecule([self, other])
class Molecule:
def __init__(self, atoms):
if type(atoms) is list:
self.atoms = atoms
sodium = Atom("Na")
chlorine = Atom("Cl")
#salt = Molecule([sodium, chlorine])
salt = sodium + chlorine
print("".join(atom.label for atom in salt.atoms))
That means having a line similar to this for every molecule our program produces. It makes so much more sense to just be able to print the instance…
print (salt)
That line need only be written once, in the class definition so it works for all molecules.
def __repr__(self):
return ''.join(x.label for x in self.atoms)
carbon_monoxide = Atom('C') + Atom('O')
print (carbon_monoxide)
# CO
True, it would definitely be more convenient in the scope of a more general program, where this would be reused.
Hey @mtf !
def add(self, other):
return Molecule([self.label , other.label])
In this exercise , why does this raise a error?
We’re not meant to pass strings to the Molecule class, but Atom objects.
return Molecule(self, other)
The dunder method will be used to combine their labels in,
salt = sodium + chlorine
Those two operands are objects with an add()
method. The dunder is triggered by the plus sign.
I agree with putting this in a representation module … but the response you provided takes a bit of a leap regarding what students are exposed to at this point in that “.join” has not been used. A clean approach using the techniques the student has been exposed to at this point would be.
def __repr__(self):
chem_name = ""
for atom in self.atoms:
chem_name += atom.label
return chem_name