1

I have created a class name Customer to hold a customer.

I have created a class named Customers that has a list of Customer.

I have in my main class created a iterator that iterates over Customers, but after I have iterated over Customers the list of Customers is left blank.

I guess the reason is that my function __next__() in customers is not correctly implemented.

main.py

from customers import Customers


customers = Customers()
print("Customers len before loop: " + str(len(customers)) + "")

print("Looping over customers:")
for customer in customers:
    print(" -> Name=" + customer.get_name())

print("Customers len after loop: " + str(len(customers)) + "")

main.py output:

Customers len before loop: 3
Looping over customers:
 -> Name=Test 3
 -> Name=Test 2
 -> Name=Test 1
Customers len after loop: 0

customers.py

#
# Customers class
# File: customers.py
#
# The Customers class is a list of Customer.
# Each customer has a name and abbreviation
#
# Usage:
#  customers = Customers()
#  customers.print_customers()
#
###

import json

from customer import Customer


class Customers:
    """ A list of Customers of class Customer. """

    __customers = []

    # Initialize Customers class ----------------------------------------------------------------
    def __init__(self):
        """ Initializes customer class with Customer and adds customers to it. """

        new_customer_to_list = Customer("Test 1", "T1")
        self.__customers.append(new_customer_to_list)

        new_customer_to_list = Customer("Test 2", "T2")
        self.__customers.append(new_customer_to_list)

        new_customer_to_list = Customer("Test 3", "T3")
        self.__customers.append(new_customer_to_list)

        print("%s customers were added" % len(self.__customers))

    # Print list of all customers ---------------------------------------------------------------
    def print_customers(self):
        """ Prints the abbrecated name of all customers in the list customers. """
        for customer in self.__customers:
            print(customer.get_name_abbreviated())

    # Iterate over customers --------------------------------------------------------------------
    def __iter__(self):
        """ Iterates over customers. Will return it self. """
        return self

    # Go to next customer ----------------------------------------------------------------------
    def __next__(self):
        """ Goes to next customers. When next is not avaialable it will stop iteration. """
        if not self.__customers:
            raise StopIteration
        return self.__customers.pop()

    # Lenght of customers list ------------------------------------------------------------------
    def __len__(self):
        """ Gives the lenght of customers list. If an error occurs the function will return -1 """
        try:
            return len(self.__customers)
        except:
            return -1

customer.py

#
# Customer class
# File: customer.py
#
# Usage:
#  customer = Customer("Name", "Name Abbreviated")
#

class Customer:
    """ A class representing a customer. """

    __name = None
    __name_abbreviated = None

    # Initialize Customer class ----------------------------------------------------------------
    def __init__(self, name='', name_abbreviated=''):
        """ Initializes customer class with name and name abbreviated """
        self.__name = name
        self.__name_abbreviated = name_abbreviated

    # Print customer class data ----------------------------------------------------------------
    def __repr__(self):
        """ Prints name and abbreviated """
        feedback = "" + str(self.__name) + " (" + str(self.__name_abbreviated) + ")";
        return feedback;

    # Get name ---------------------------------------------------------------------------------
    def get_name(self):
        """ Returns the name of the customer """
        return self.__name;

    # Get name abbreviated ----------------------------------------------------------------------
    def get_name_abbreviated(self):
        """ Returns the name abbreviated of the customer """
        return self.__name_abbreviated;
martineau
  • 119,623
  • 25
  • 170
  • 301
Europa
  • 974
  • 12
  • 40

1 Answers1

1

I see two ways to fix this issue. The first is the simplest. It involves not making a custom iterator and just subclassing list. Since you have no custom iteration logic this is the easiest. First you change the Customers class to this:

from collections import UserList
class my_customers(UserList):
    def print_customers(self):
        """ Prints the abbreviated name of all customers in the list customers. """
        for customer in self:
            print(customer.get_name_abbreviated())

This will give you the functions of a list and allow for adding custom methods and overwriting only the ones that are needed.
If you really need to do it your way then you need to modify the __iter__ and __next__ functions for __iter__ it needs to set the start of the iteration like so:

def __iter__(self):
    """ Iterates over customers. Will return it self. """
    self.current = 0
    return self

next you must change __next__ to use this counter and raise StopIteration when it gets to the length:

def __next__(self):
    """ Goes to next customers. When next is not available it will stop iteration. """
    while self.current != len(self.__customers):
        self.current += 1
        return self.__customers[self.current - 1]
    raise StopIteration
martineau
  • 119,623
  • 25
  • 170
  • 301
NTamez8
  • 109
  • 2