Наведено абстрактний клас камери, яка характеризується розміром кадру. В класі передбачено можливість фотографування та масштабування зображення.

Для прикладу наведено методи get/set для поля __frameSize та властивість (@property) в стилі Python

In [1]:
class PhotoCamera:
    def __init__(self, frameSize):
        self.__frameSize = frameSize
        self._image = None
    
    def getFrameSize(self): 
        """So-called getter"""
        return self.__frameSize
    
    def setFrameSize(self, frameSize):
        self.__frameSize = frameSize
        
    @property
    def frameSize(self):
        """Property of the object"""
        return self.__frameSize
    
    def makeShot(self, image):
        pass
    
    def zoom(self, scale):
        pass
In [2]:
camera = PhotoCamera([1024, 768])
print(camera.getFrameSize())
print(camera.frameSize)
[1024, 768]
[1024, 768]

Звертання до приватного поля напряму заборонено:

In [3]:
print(camera.__frameSize)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [3], in <cell line: 1>()
----> 1 print(camera.__frameSize)

AttributeError: 'PhotoCamera' object has no attribute '__frameSize'

Конкретний клас камери, який реалізує абстрактний клас PhotoCamera

In [4]:
class NikonCamera(PhotoCamera):
    def __init__(self, matrixSize):
        self.__matrixSize = matrixSize
    
    def makeShot(self, image):
        self._image = image
        print('Click at {}!'.format(self._image))
    
    def zoom(self, scale):
        self._image /= scale
In [5]:
nikon = NikonCamera(0.5)
nikon.makeShot(49545654)
Click at 49545654!

Інший конкретний клас, який містить власну реалізацію методів камери:

In [6]:
class BlenderCamera(PhotoCamera):
    def __init__(self, position, direction):
        self.__position = position
        self.__direction = direction
    
    def makeShot(self, image):
        self._image = image
        print('Render from position {} with direction {} is done!'.format(self.__position, self.__direction))
    
    def zoom(self, scale):
        self._image /= scale
In [7]:
blender = BlenderCamera([10, 2, 4], [45, 15])
blender.makeShot(84549)
Render from position [10, 2, 4] with direction [45, 15] is done!

Поліморфізм: маємо список об'єктів, всі з яких реалізують клас PhotoCamera, тому можна звертатися до їх методу makeShot, який імплементовано по-різному в кожного з об'єктів

In [8]:
blender2 = BlenderCamera([85, 35, -38], [90, 0])
mycameras = [nikon, blender, blender2]
for cam in mycameras:
    cam.makeShot(844554)
Click at 844554!
Render from position [10, 2, 4] with direction [45, 15] is done!
Render from position [85, 35, -38] with direction [90, 0] is done!

Наявність об'єкту іншого типу "ламає" код:

In [9]:
mycameras = [nikon, blender, blender2, [6, 3, 5]]
for cam in mycameras:
    cam.makeShot(844554)
Click at 844554!
Render from position [10, 2, 4] with direction [45, 15] is done!
Render from position [85, 35, -38] with direction [90, 0] is done!
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [9], in <cell line: 2>()
      1 mycameras = [nikon, blender, blender2, [6, 3, 5]]
      2 for cam in mycameras:
----> 3     cam.makeShot(844554)

AttributeError: 'list' object has no attribute 'makeShot'

Приклад роботи з виключенням (exception) для відслідковування недопустимих аргументів методів:

In [10]:
class NikonCameraWithException(PhotoCamera):
    def __init__(self, matrixSize):
        self.__matrixSize = matrixSize
    
    def makeShot(self, image):
        self._image = image
        print('Click at {}!'.format(self._image))
    
    def zoom(self, scale):
        if scale >= 0.5 and scale <= 10:
            self._image /= scale
        else:
            raise ValueError('Scale should be within [0.5...10]!')
In [11]:
nikon.zoom(10)
In [12]:
nikon.zoom(0)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Input In [12], in <cell line: 1>()
----> 1 nikon.zoom(0)

Input In [4], in NikonCamera.zoom(self, scale)
      9 def zoom(self, scale):
---> 10     self._image /= scale

ZeroDivisionError: float division by zero
In [13]:
nikon2 = NikonCameraWithException(0.5)
nikon2.makeShot(48456)
nikon2.zoom(5)
Click at 48456!
In [14]:
nikon2.zoom(0.05)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [14], in <cell line: 1>()
----> 1 nikon2.zoom(0.05)

Input In [10], in NikonCameraWithException.zoom(self, scale)
     11     self._image /= scale
     12 else:
---> 13     raise ValueError('Scale should be within [0.5...10]!')

ValueError: Scale should be within [0.5...10]!
In [15]:
try:
    nikon2.zoom(0.05)
except:
    print('Wrong zoom was used')
Wrong zoom was used
In [ ]: