Implementing Abstract class I used Pythons source code/documentation/textbook to come up with an abstract class and following subclasses.

My requirements are:


Domestic students don't require documentation
International student do require documentation (passports, etc..)

from abc import ABCMeta

class Student(metaclass=ABCMeta):

    def __init__(self, id, firstname, lastname):
        self.__id = id
        self.__firstname = firstname
        self.__lastname = lastname

    @property
    def iden(self):
        return self.__id

    @property
    def first_name(self):
        return self.__firstname

    @property
    def last_name(self):
        return self.__lastname



International Subclass:

from Student import Student
from copy import deepcopy


class International(Student):
    def __init__(self, iden, firstname, lastname, docuemnts):
        super().__init__(iden, firstname, lastname)

        self.__documents = deepcopy(docuemnts)
        self.__type_of_student = "International"

    @property
    def international_documents(self):
        return deepcopy(self.__documents)


Domestic Subclass:

from Student import Student


class Domestic(Student):

    def __init__(self, iden, firstname, lastname):
        super().__init__(iden, firstname, lastname)

        self.__type_of_student = "Domestic"

    @property
    def student_type(self):
        return self.__type_of_student


Have I constructed and implementation the abstract class correctly?
How do you tell what the student type is, without erroring on both International and Domestic?

With your current code, you'd have to do something like:

if hasattr(student, 'student_type'):
    student_type = student.student_type()
else:
    student_type = None


What makes this worse, is you assume None to be International.
Why can't Domestic students have international_documents?

In your requirements you state:


  
  Domestic students don't require documentation
  International student do require documentation (passports, etc..)
  

Why should these be separate classes?
Your name mangled variables make your code longer, and generally more horrible to read.
Instead you could make them just normal properties.

However, since they are unsetable, you may want to use a namedtuple instead.


And so I'd use something like:

from collections import namedtuple
from Enum import enum

class StudentType(Enum):
    INTERNATIONAL = 'international'
    DOMESTIC = 'domestic'

Student = namedtuple('Student', 'id first_name last_name type documents')

s1 = Student(0, 'John', 'Doe', StudentType.INTERNATIONAL, [...])
s2 = Student(1, 'Eva', 'Smith', StudentType.DOMESTIC, [])