1

I've been searching a lot for this type of problem, haven't found a single similar question on SO yet.

I have tried using a for loop to put some validation in the train's init that would disregard those passengers although with no success.

tl;dr - How do I validate which passengers will be in the passengers list when I know that some of the passengers in the passengers list are ineligble to be in the train, due to seat_nr out of range or the carriage_nr out of range.

"""Train."""


class Train:
    def __init__(self, passengers: list, carriages: int, seats_in_carriage: int):
        

        #--Insert validation for passengers allowed on train--#        

        self._passengers = passengers
        self._carriages = carriages
        self._seats_in_carriage = seats_in_carriage

    @property
    def passengers(self) -> list:
        return self._passengers

    @property
    def carriages(self) -> int:
        return self._carriages

    @property
    def seats_in_carriage(self) -> int:
        return self._seats_in_carriage

    def get_seats_in_train(self) -> int:
        return self._seats_in_carriage * self._carriages

    def get_number_of_passengers(self) -> int:
        return len(self._passengers)

    def get_passengers_in_carriages(self) -> dict:
        return {}

    @passengers.setter
    def passengers(self, value_list: list):
        self._passengers = value_list

    @carriages.setter
    def carriages(self, value: int):
        self._carriages = value

    @seats_in_carriage.setter
    def seats_in_carriage(self, value: int):
        self._seats_in_carriage = value


class Passenger:
    def __init__(self, passenger_id: str, seat: str):
        self.carriage_number = seat.split("-")[0]
        self.seat_number = seat.split("-")[1]
        self._seat = seat
        self._passenger_id = passenger_id

    def __dict__(self):
        if str(2) >= self.seat_number > str(0) and self.carriage_number <= str(3):
            passenger_dct = {'id': str(self._passenger_id), 'seat': str(self._seat)}
            return passenger_dct


if __name__ == '__main__':
    passengers = [
        Passenger('test', '1-2'),   #--"test"= passenger_id, "x-y" : x= carriage_nr, y= seat_nr// valid
        Passenger('test2', '2-3'),  #-- invalid, seat_nr=3, train carriage has only 2 seats.
        Passenger('test3', '4-2'),  #-- invalid, carriage_nr = 4, train only has 3 carriages.
        Passenger('test4', '3-2'),  #-- valid
        Passenger('test5', '1-1'),  #-- valid
        Passenger('test6', '1-0'),  #-- invalid, no seat_nr 0 on train carriage
    ]
    assert passengers[0].__dict__() == {'id': 'test', 'seat': '1-2'}

    t = Train(passengers, 3, 2)  #--passengers list, number of carriages, number of seats in carriage.
    
    print(t.get_number_of_passengers()) # -- Should print 3, instead prints all 6.


Any info regarding to the topic is much appreciated, thanks in advance!

12
  • 1
    I would turn this question around with a different question: does a passenger without a train make sense? If not, then Passenger could be a nested class of Train, and a factory method could be added to Train that adds, validates, and returns Passenger instances. i.e. train.add_passenger(passenger_id="passenger-id", seat_nr=1, carriage_nr=2). Commented Oct 19, 2020 at 21:07
  • Thank you for this comment, very interesting approach! Commented Oct 19, 2020 at 21:16
  • 1
    @AttilaViniczai your overall point is a good one, but why a nested class? It solves no problems. Commented Oct 19, 2020 at 21:23
  • 1
    @Crimson don't post code in the comments. Edit your question to include a minimal reproducible example. Please remove all the unecessary details that just obscure what's going on. And try to give a precise problem statement. In any case, when you tried that code what didn't work. Please be precise. Check out How to Ask and the help center Commented Oct 19, 2020 at 21:32
  • 1
    @AttilaViniczai that is simply not a pythonic construct. The fundamental unit of code organization in Python is a module. The more conventional approach would be to have an appropriately named module, then make class Train: ... and name class _Passenger: ... which lets everyone know that _Passenger is an implementation detail of the model, and not a public part of the module's API Commented Oct 19, 2020 at 21:38

1 Answer 1

1

I think the solution is pretty straightforward and I'm not sure why this wouldn't work: "I have tried using a for loop to put some validation in the train's init that would disregard those passengers although with no success." Essentially you can just loop through the passenger list and filter out invalid passenger objects as such:

self._passengers = list(filter(lambda p: p.seat_number is valid, passengers))

This uses a lambda function to check certain criteria for including them in the final list. Also your getters and setters don't currently do anything so they are kind of pointless.

Sign up to request clarification or add additional context in comments.

3 Comments

Do note that above solution tightly couples Train and Passenger classes on the implementation level. In other words changes made to one, can affect the other.
Thank you for the answer! I tried to do it this way, however since there is nothing that indicates whether a seat_number is valid I tried comparing passenger class seat_number and carriage_number to the train class number of carriages and number of seats. However I mostly got attribute errors :/.
That should not be so difficult to achieve, attribute errors probably mean you have not added those attributes to the class before calling them but I won't know without more info. @AttilaViniczai You are right and I look forward to your answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.