Veneer Buy_Artwork function not removing artwork

Veneer Project

class Art:
  def __init__(self, artist, title, medium, year, owner):
    self.artist = artist
    self.title = title
    self.medium = medium
    self.year = year
    self.owner = owner
  def __repr__(self):
    return str(self.artist + '. ' + self.title + '. ' + self.year + ', ' + self.medium + '. ' + self.owner.name + ', ' + self.owner.location + ".")

class Listing:
  def __init__(self, art, price, seller):
    self.art = art
    self.price = price
    self.seller = seller
  def __repr__(self):
    return str(self.art.title + " - " + self.price)

class Marketplace:
  def __init__(self):
    self.listings = []
  def add_listing(self, new_listing):
    self.listings.append(new_listing)
  def remove_listing(self, old_listing):
    self.listings.remove(old_listing)
  def show_listings(self):
    for listing in self.listings:
      print(listing)

class Clients:
  def __init__(self, name, location, is_museum):
    self.name = name
    self.is_museum = is_museum
    if is_museum:
      self.location = location
    else:
      self.location = "Private Collection" 
  def sell_artwork(self, artwork, price):
    if artwork.owner == self:
      new_listing = Listing(artwork, price, self)
      veneer.add_listing(new_listing)
  def buy_artwork(self, artwork):
    if artwork.owner != self:
      for listing in veneer.listings:
        if artwork == listing.art:
          art_listing = artwork
          art_listing.owner = self
          veneer.remove_listing(artwork)
        
veneer = Marketplace()
#veneer.show_listings()
moma = Clients("The MOMA", "New York", True)
edytta = Clients("Edytta Halpirt", None, False)
girl_with_mandolin = Art("Picasso, Pablo", "\"Girl with a Mandolin (Fanny Tellier)\"", "oil on canvas", "1910", edytta)
print(girl_with_mandolin)
edytta.sell_artwork(girl_with_mandolin, "$6M (USD)")
veneer.show_listings()
moma.buy_artwork(girl_with_mandolin)
print(girl_with_mandolin)
veneer.show_listings()

I can’t understand why the Buy_Artwork function doesn’t remove the artwork from the listings.

  def buy_artwork(self, artwork):
    if artwork.owner != self:
      for listing in veneer.listings:
        if artwork == listing.art:
          art_listing = artwork
          art_listing.owner = self
          veneer.remove_listing(artwork)

If I #comment out the (veneer.remove_listing(artwork)) part of that code, the owner switches correctly but the artwork remains listed.

Any assistance would be appreciated.

Your code throws an error:
ValueError: list.remove(x): x not in list

Investigating this will lead you to the path of the answer (like you said, the mistake is in the remove_listing method)

I’m unsure why that is the problem, the artwork I am passing into remove_listing exists in the list (considering it was able to change the owner), so why would it say that value is not in list?

veneer = Marketplace()
#veneer.show_listings()
moma = Clients("The MOMA", "New York", True)
edytta = Clients("Edytta Halpirt", None, False)
girl_with_mandolin = Art("Picasso, Pablo", "\"Girl with a Mandolin (Fanny Tellier)\"", "oil on canvas", "1910", edytta)
#print(girl_with_mandolin)
edytta.sell_artwork(girl_with_mandolin, "$6M (USD)")
veneer.show_listings()
#moma.buy_artwork(girl_with_mandolin)
#print(girl_with_mandolin)
#veneer.show_listings()

When I do this with your code the output is “Girl with a Mandolin (Fanny Tellier)” - $6M (USD).

Notice how the last show_listings() doesn’t return anything. So the error comes from trying to buy something that isn’t there (you can put conditionals in your code to prevent that!).

When debugging you have to be willing to put a lot of print lines to debug if you have no idea where it is. But ideally you’re double-checking every function you write so it doesn’t pile up (while you’re still getting used to the formats).

  def buy_artwork(self, artwork):
    if artwork.owner != self:
      for listing in veneer.listings:
        if artwork == listing.art:
          art_listing = artwork
          #print(art_listing)
          art_listing.owner = self
          #print(art_listing)
          #print(veneer.listings)
          veneer.remove_listing(listing)

I believe I fixed the code by passing ‘listing’ into the remove_listing method!

Thank you for the guidance.
I’ve noticed other people’s code, (and the video solution as well) include a line:

art_listing = None

I don’t understand what that line is included for?

You should delete everything that you cannot argue for. If you have code that you do not know what it does then that is a bug.
Consider what should happen and compare that to the code. And you do need to know what should happen before you write code describing what should happen.

having two variables refer to the same thing does not accomplish anything unless the variables are later treated differently which they aren’t

what should this function do?

it should find an artwork
change its owner
delist the artwork

so you’d start by finding it.
you’d look at some bunch of things. for each thing, you would ask, hey, is this what I’m looking for?
once you’ve found it, you can carry out the other two tasks which rely on having an artwork