Конструктор класса – метод __init__()

В объектно-ориентированном программировании конструктором класса называют метод, который автоматически вызывается при создании объектов. Его также можно назвать конструктором объектов класса. Имя такого метода обычно регламентируется синтаксисом конкретного языка программирования. Так в Java имя конструктора класса совпадает с именем самого класса. В Python же роль конструктора играет метод __init__().

В Python наличие пар знаков подчеркивания спереди и сзади в имени метода говорит о том, что он принадлежит к группе методов перегрузки операторов. Если подобные методы определены в классе, то объекты могут участвовать в таких операциях как сложение, вычитание, вызываться как функции и др.

При этом методы перегрузки операторов не надо вызывать по имени. Вызовом для них является сам факт участия объекта в определенной операции. В случае конструктора класса – это операция создания объекта. Так как объект создается в момент вызова класса по имени, то в этот момент вызывается метод __init__(), если он определен в классе.

Необходимость конструкторов связана с тем, что нередко объекты должны иметь собственные свойства сразу. Пусть имеется класс Person, объекты которого обязательно должны иметь имя и фамилию. Если класс будет описан подобным образом

class Person:
    def setName(self, n, s):
        self.name = n
        self.surname = s

то создание объекта возможно без полей. Для установки имени и фамилии метод setName() нужно вызывать отдельно:

>>> from test import Person 
>>> p1 = Person()
>>> p1.setName("Bill", "Ross")
>>> p1.name, p1.surname
('Bill', 'Ross')

В свою очередь, конструктор класса не позволит создать объект без обязательных полей:

class Person:
    def __init__(self, n, s):
        self.name = n
        self.surname = s
 
p1 = Person("Sam", "Baker")
print(p1.name, p1.surname)

Здесь при вызове класса в круглых скобках передаются значения, которые будут присвоены параметрам метода __init__(). Первый его параметр – self – ссылка на сам только что созданный объект.

Теперь, если мы попытаемся создать объект, не передав ничего в конструктор, то будет возбуждено исключение, и объект не будет создан:

>>> p1 = Person()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 2 required positional arguments: 'n' and 's'

Однако бывает, что надо допустить создание объекта, даже если никакие данные в конструктор не передаются. В таком случае параметрам конструктора класса задаются значения по умолчанию:

class Rectangle:
    def __init__(self, w = 0.5, h = 1):
        self.width = w
        self.height = h
    def square(self):
        return self.width * self.height
 
rec1 = Rectangle(5, 2)
rec2 = Rectangle()
rec3 = Rectangle(3)
rec4 = Rectangle(h = 4)
print(rec1.square())
print(rec2.square())
print(rec3.square())
print(rec4.square())

Вывод:

10
0.5
3
2.0

Если класс вызывается без значений в скобках, то для параметров будут использованы их значения по умолчанию. Однако поля width и height будут у всех объектов.

Кроме того, конструктору вовсе не обязательно принимать какие-либо параметры, не считая self. Значения полям могут назначаться как угодно. Также не обязательно, чтобы в конструкторе происходила установка атрибутов объекта. Там может быть, например, код, который порождает создание объектов других классов.

В других языка программирования, например в Java, классы могут содержать несколько конструкторов, которые между собой отличаются количеством параметром, а также, возможно, их типом. При создании объекта срабатывает тот конструктор, количество и типы параметров которого совпали с количеством и типами переданных в конструктор аргументов.

В Python создать несколько методов __init__() в классе можно, однако "рабочим" останется только последний. Он переопределит ранее определенные. Поэтому в Python в классах используется только один конструктор, а изменчивость количества передаваемых аргументов настраивается через назначение значений по-умолчанию.

Практическая работа. Конструктор и деструктор

Помимо конструктора объектов в языках программирования есть обратный ему метод – деструктор. Он вызывается, когда объект не создается, а уничтожается.

В языке программирования Python объект уничтожается, когда исчезают все связанные с ним переменные или им присваивается другое значение, в результате чего связь со старым объектом теряется. Удалить переменную можно с помощью команды языка del.

В классах Python функцию деструктора выполняет метод __del__().

Напишите программу по следующему описанию:

  1. Есть класс Person, конструктор которого принимает три параметра (не учитывая self) – имя, фамилию и квалификацию специалиста. Квалификация имеет значение заданное по умолчанию, равное единице.

  2. У класса Person есть метод, который возвращает строку, включающую в себя всю информацию о сотруднике.

  3. Класс Person содержит деструктор, который выводит на экран фразу "До свидания, мистер …" (вместо троеточия должны выводиться имя и фамилия объекта).

  4. В основной ветке программы создайте три объекта класса Person. Посмотрите информацию о сотрудниках и увольте самое слабое звено.

  5. В конце программы добавьте функцию input(), чтобы скрипт не завершился сам, пока не будет нажат Enter. Иначе вы сразу увидите как удаляются все объекты при завершении работы программы.

В Python деструктор используется редко, так как интерпретатор и без него хорошо убирает "мусор".

Курс с примерами решений практических работ и всеми уроками: android-приложение, pdf-версия.

Комментарии

class Person:
 
    def __init__(self, name, surname, position=1):
        self.name = name
        self.surname = surname
        self.position = position
 
    def display(self):
        return self.name, self.surname, self.position
 
    def __del__(self):
        print "Goodbye Mr. {} {}".format(self.name, self.surname)
 
p1 = Person('big', 'dude', 3)
print p1.display()
 
p2 = Person('small', 'croon', 4)
print p2.display()
 
p3 = Person('neutral', 'guy', 5)
print p3.display()
 
del p2
 
try:
    input("Press Enter and exit")
except SyntaxError:
    exit()

Спасибо, после вашей статьи понял тему про __init__ На остальных ресурсах менее понятно. Сенкс
print ("Спасибо за пост")

class Person:
    def __init__(self, name, lastname, qual=1):
        self.name = name
        self.lastname = lastname
        self.qual = qual
 
    def __repr__(self):
        return "" % (self.name, self.lastname, self.qual)
 
    def info(self):
        print(f"Сотрудник {self.name} {self.lastname} имеет квалификацию {self.qual}")
 
    def __del__(self):
        print(f"До свидания, мистер {self.name} {self.lastname}")
 
def byQual_key(person):
    return person.qual
 
persons = []
persons.append(Person("Иван", "Иванов", 2))
persons.append(Person("Петр", "Петров"))
persons.append(Person("Сидр", "Сидоров", 3))
 
p = sorted(persons, key = byQual_key, reverse=True)
 
for i in p:
    i.info()
 
p[-1].__del__()
 
print("Press ENTER to exit")
input()

Ответ на от Алексей

Для чего использовали i.info()

Ответ на от Нурлыбай

Фраза про увольнение появляется, но физически из списка он не удаляется. При проверке списка после увольнения, он отражается в сотрудниках.

В задании сказано, что квалификация задана в классе Person и равна 1. А потом говорится уволить самое слабое звено. Но они же все имеют квалификацию = 1. ? Зарание спасибо.

Подскажите советом, как правильней организовать список персонажей, что бы не ручками и глазками высматривать "самое слабое звено", а найти программно и его удалить? Решение задачи:
class person:
    def __init__(self, fName, lName, qual=1, gender='M'):
        self.fName=fName
        self.lName=lName
        self.qual=qual
        self.gender='Male' if gender=='M' else 'Female' if gender=='F' else 'WHO ARE YOU?'
 
    def __del__(self):
        return f'Goodbye {str(self)}'
 
    def __repr__(self):
        return f'{self.lName[0].upper()}{self.lName[1:]} {self.fName[0].upper()}'
 
    def getInfo(self):
        return f'Person: [{str(self)}]\n - Qualification: [{self.qual}]\n - Gender: [{self.gender}]'
 
anton=person('anton','ukupnik')
vasya=person('vasya','pupkin',qual=3)
anna=person('anna','ivanova',gender='F', qual=4)
 
print(anton.getInfo())
print(anna.getInfo())
print(vasya.getInfo())
 
print(anton.__del__())
 
input('press enter to exit')

Ответ на от plustilino

Класс дополнил методами: ...
    def __lt__(self, other):
        return self.qual < other.qual
 
    def __gt__(self, other):
        return self.qual > other.qual
...
pList=[person('anton','ukupnik'),
    person('igor','nikolaev'), 
    person('vasya','pupkin',qual=3),
    person('anna','ivanova',gender='F', qual=4)]
 
 
print('remove outsiders:')
for pers in list(filter(lambda x: x.qual==min(pList).qual, pList)):
    pList.remove(pers)
    print(pers.__del__())

Метод __del__() выполняется перед уничтожением объекта, если вызвать его на объекте, то он просто выполнит свой блок.

#!/bin/env python36
class Person:
    def __init__(self, n, s, q = 1):
        self.name = n
        self.surname = s
        self.qualification = int(q)
    def getInfo(self):
       return  self.name, self.surname, self.qualification
    def __del__(self):
        print('Goodbye Mr.', self.name, self.surname)
 
one = Person('Ivan', 'Drago', 2)
two = Person('John', 'Smith', 12)
three = Person('Natalia', 'Lazareva', 3)
four = Person('Simon', 'Bull', 5)
print(one.getInfo())
print(two.getInfo())
print(three.getInfo())
print(four.getInfo())
skill_list = []
for skill in one.qualification, two.qualification, three.qualification, four.qualification:
    skill_list.append(skill)
weak = min(skill_list)
for per in one, two, three, four:
    if per.qualification == weak:
        per.__del__()
input()

А почему нельзя сделать нужные поля в Class A: , вместо __init__ ? Или при создании объекта учитывается только метод __init__, а указанные поля в самом классе не идут в использование(при создании объекта)?

class Person():
 
    def __init__(self, name, surname, kvala = 1):
        self.name = name
        self.surname = surname
        self.kvala = kvala
 
    def vozv(self):
        return self.name, self.surname, self.kvala
 
    def __del__(self):
        print ('Goodbye', self.name, self.surname)
 
Alba = Person("Alba", "Bakker", "13")
Samanta = Person("Samanta", "Bekker", "14")
Lila = Person("Lila", "Arhib", "33")
 
print (Alba.vozv(), Samanta.vozv(), Lila.vozv())
 
a = input()
#Вот что получилось
Есть несколько вопросов: 1) Можно ли как-то вывести все созданные объекты по данному классу, не чередуя их через запятую в print ? 2) Почему у меня после моего Input'а выводится "Goodbye name, surname" по всем трем объектам ?хотя даже команды нету 3) Не понял как использовать деструктор для удаления определенного объекта? Пример: Alba.__del__() - так ?

Ответ на от And

2) потому что при завершении программы удаляются все объекты автоматически, input() тут не причем.

3) можно удалять del Alba.

1) только если вы поместите объекты в список. Хотя возможно есть какой-то специфический вариант нахождения в программе всех объектов одного класса. Мне неизвестно.

Скачал на телефон PDF AByteOfPython. Книга сама по себе хороша, но в силу моего возраста и опыта слишком сложна. Выключил телефон. Открыл этот сайт и сразу всё понял!

import random
 
class Person:
 
    def __init__(self, name, surname, skill = 1):
        self.name = name
        self.surname = surname
        self.skill = skill
 
    def __del__(self):
        print(f"Farewell, Mr. {self}")
 
    def __str__(self):
        return f"{self.name} {self.surname}, skill: {self.skill}"
 
 
def fire_weakest(persons_list):
    min_skill = persons_list[0].skill
    for p in persons_list:
        if p.skill < min_skill:
            min_skill = p.skill
    weakest = filter(lambda person: person.skill == min_skill , persons_list)
    for p in weakest:
        persons_list.remove(p)
        del p
 
 
NAMES = ["Jonh", "Bob", "Tom", "Bob", "Bill", "Harry", "Sam", "Nick", "Dan"]
SURNAMES = ["Jonhson", "Smith", "Davis", "Taylor", "Wilson", "Evans", "Brown"]
PERSONS_NUMBER = 6
 
rnd = random.Random()
 
persons = []
 
for i in range(PERSONS_NUMBER):
    name = NAMES[rnd.randint(0,len(NAMES) - 1)]
    surname = SURNAMES[rnd.randint(0,len(SURNAMES) - 1)]
    skill = rnd.randint(1,10)
    persons.append(Person(name, surname, skill))
 
for p in persons:
    print(p)
 
print("\nFiring the weakest:")
 
fire_weakest(persons)
print("\nAfter weakest fired:")
for p in persons:
    print(p)
 
input()

https://gist.github.com/DNDK/33eec0d5501307e726edcf76ff0a34e7

Решил на основе этой задачи сделать небольшой "терминал". Что-то такое уже писал на C++

Как в этом коде найти учителя с самой низкой квалификацией, а потом повысить ее и уволить этого учителя?
class Teacher:
    def __init__(self, name, subject, experience, qualification):
        self.name=name
        self.subject=subject
        self.experience=experience
        self.qualification=qualification
 
    def information(self):
        return self.name, self.subject, self.experience, self.qualification
 
    def __del__(self):
        print("{}, Вы уволенны!".format(self.name))
 
teacher1 = Teacher('Mark', 'Math', 10, 5)
print (teacher1.information())
 
teacher2 = Teacher('Slava', 'Bio', 9, 4)
print (teacher2.information())
 
teacher3 = Teacher('Kira', 'Ukr', 10, 10)
print (teacher3.information())
 
teacher4 = Teacher('Taras', 'Rus', 9, 8)
print (teacher4.information())
 
teacher5 = Teacher('Vika', 'Ger', 5, 10)
print (teacher5.information())
 
 
 
input(teacher3.name)
input("press enter to exit")

Ответ на от Сергей

В таком варианте кода - проблематично. 

При создании учителей их надо добавить в один общий список, а не присваивать отдельным переменным. Или добавить в список сами переменные. После этого перебрать список в цикле на предмет поиска самого маленького значения свойства qualification. 

 

import random


class Employee:
    def __init__(self, name, last_name, quall=1):
        self.name = name
        self.last_name = last_name
        self.quall = quall

    def info(self):
        return self.name + self.last_name + self.quall

    def __del__(self):
        return print(f"Goodbye Mr.{self.name} {self.last_name}")


person1 = Employee('Ivan', 'Ivanov', random.randint(1, 5))
person2 = Employee('Nikolay', 'Nikolayev')
person3 = Employee('Sergey', 'Sergeyev', random.randint(1, 5))

emps = []
emps.append(person1)
emps.append(person2)
emps.append(person3)

arr = []
arr.append(person1.quall)
arr.append(person2.quall)
arr.append(person3.quall)
weak = arr.index(min(arr))

emps[weak].__del__()

input()

 

class Repson:
    def __init__(self, n, s, q = 1):
        self.name = n
        self.surname = s
        self.qulif = q
    def ret(self):
        return self.name, self.surname, self.qulif
    def __del__(self):                                  # почему сам выбирает слабое звено? и как.
        print('Goodbye Mr.', self.name, self.surname)
 
w1 = Repson("John", "Smith" , 4)
w2 = Repson("Tony", "Soprano",3)
w3 = Repson("Any", "Throath", 5)
print(w1.ret(), w2.ret(), w3.ret())
print("bay bay mr.",max(w1.ret(), w2.ret(), w3.ret())) # какова рожна мин не работает? так как надо
 
input()
#заранее спасибо за ответы!

class person:
    def __init__(self, n, s, q=1):
        self.name = n
        self.surname = s
        self.qual = int(q)
 
    def __del__(self):
        print ('До свидания, мистер {0} {1}'.format(self.name, self.surname))
 
    def get(self):
        print('Сотрудник: {1} {0} квалификация: {2}'.format(self.name, self.surname, self.qual))
        return [self.name, self.surname, self.qual]
 
 
p1 = person('Иван', 'Иванов', 3)
p2 = person('Петр', 'Петров')
p3 = person('Сидор', 'Сидоров', 5)
all = [p1.get(), p2.get(), p3.get()]
 
q = []
for i in range(0,3):
    q.append(all[i][-1])
 
qmin = min(q)
try:
    if p1.qual == qmin:
        del p1
    elif p2.qual == qmin:
        del p2
    elif p3.qual == qmin:
        del p3
finally:
    print('вы уволены(')
    all.pop(q.index(qmin))
 
input('Конец')

class Workers:
    workerlist = []
    allworkers = len(workerlist)
    def __init__(self, n, s, skill = 1):
        self.name = n
        self.surname = s
        self.skill = skill
        Workers.workerlist.append([self.name, self.surname, self.skill])
    def getinfo(self):
        return print(self.name, self.surname, self.skill)
    def lower(lowindx = 0):
        skillslist = []
        for w in Workers.workerlist:
            for i, wrkr in enumerate(w):
                if i == 2:
                    skillslist.append(wrkr)
        lowvalue = str(min(skillslist))
        ffd = "".join([str(i) for i in skillslist])
        lowind =  ffd.find(lowvalue)
        if lowindx != 0:
            return lowind
        return print("Самый слабый работник", Workers.workerlist[lowind])
    def __del__(self):
        del Workers.workerlist[Workers.lower.lowind]
        return print(F"Прощай мистер {self.name} ")
a = Workers('Al', 'B', 5)
b = Workers('Sec', 'Bro')
c = Workers('Thir', 'Crue', 2)
a.getinfo(), b.getinfo(), c.getinfo()
Workers.lower()
try:
    while True:
        print(Workers.workerlist, 'Самый слабый:', Workers.workerlist[Workers.lower(1)])
        D = input(
            'Удалить самого слабого (Введи что угодно для того чтобы удалить, либо нажми Enter чтобы ничего не делать)?')
        if D:
            print(Workers.workerlist[Workers.lower(1)], "был удален из списка работников, но его объект остался")
            del Workers.workerlist[Workers.lower(1)]
        else:
            break
except:
    print('Список работников пуст')
 
input("Нажмите Enter чтобы выйти")

Ответ на от Адам

абсолютно не читаемый код, две первые строки нужно переделать и добавить в конструктор,как это сделать подумайте сами, в классах никто не пишет строчки кода не обособленные функциями. Так же старайтесь делать пробел в строку между логическими блоками,чтобы код был читаемым

class Person:
    def __init__(self, name, surname, pos=1):
        self.name = name
        self.surname = surname
        self.pos = pos
    def info(self):
        return self.name, self.surname, self.pos
    def __del__(self):
        print(f'Прощайте, мистер {self.name} {self.surname}')
 
people = []
people.append(Person("Anatoly","Tolik",3))
people.append(Person("Bazon","Hix",7))
people.append(Person("Sam","Porter",9))
people.append(Person("Sergio","Keker"))
 
position = []
for i in people:
    position.append(list(i.info())[2])
min_position = min(position)
 
for i in people:
    if i.pos == min_position:
        i.__del__()
 
print("Press enter for exit")
input()

До этой главы всё было понятно. Но здесь возникло много непоняток. 1. Что такое - метод перегрузки операторов? И зачем это в этой главе? 2. Разница между этим:
class Person:
    def setName(self, n, s):
        self.name = n
        self.surname = s
и этим:
class Person:
    def __init__(self, n, s):
        self.name = n
        self.surname = s
только в том что в первом случае можно создать так сказать пустой экземпляр, т.е. имя, фамилия не указывать, а во втором случае - это нужно делать обязательно? В каких случаях применяется тот или другой способ?
3. И сразу после идёт предложение:"Кроме того, конструктору вовсе не обязательно принимать какие-либо параметры, не считая self. Значения полям могут назначаться как угодно." Не понятно - так зачем тогда нужен __init__? Так нужно указывать параметры или не нужно?
4.Практическая работа. Если при написании класса не указать метод __del__(), а в далее в теле программы написать del person3, этот объект (person3) удалиться точно так же как? Разница лишь в том что если я напишу __del__('Прощай мистер: ', self.name, self.lastname), то появится сообщение? 5. Просмотрев все примеры, так и не понял - какую роль играет input()? Если его не ставить, то программа просто завещается сама - не показывая - что удалилось. Если поставить input(), то всё то же самое, только нудно сделать ввод в конце. В чём смысл? Мой код:
class Person:
    def __init__(self,f_name,l_name,skill=1):
        self.fname=f_name
        self.lname=l_name
        self.skill=skill
 
    def info(self):
        return self.lname,self.fname,self.skill
 
    def __del__(self):
        print('Досвидания, мистер: ',self.lname,self.fname)
 
 
person1=Person('Ivan', 'Ivanov', 10)
person2=Person('Petr','Petrov',5 )
person3=Person('Vasa','Vasiliev')
 
print(person1.info())
print(person2.info())
print(person3.info())
 
del person3
 
print('\n----------------------------------------------------')
 
print(person1.info())
print(person2.info())
print(person3.info())
 
#### Разумеется по окончании работы программы появится сообщение: name 'person3' is not defined

Ответ на от Xp

Потому что конструктор - один из методов перегрузки операторов. В данном случае "оператора" создания объекта.

Нужен в классе конструктор или нет, зависит от назначения класса. Обычно конструкторы есть. Аргументы могут не передаваться в конструктор, а полям назначаться значения по-умолчанию.

class Person():
    def __init__(self, name, surname, kvalif):
        self.name=name
        self.surname = surname
        self.kvalif=kvalif
 
    def spisok(self):
        print('Cotrydnik ',self.name,' s familiej ',self.surname,'imeet kvalifikaciu ',self.kvalif)
        print('-----------------------------------------------')
 
    def __del__(self):
        print('Do svidanij mister ',self.name,' s familiej ',self.surname,'imeet kvalifikaciu ',self.kvalif)
        print('-----------------------------------------------')
        input('Enter any key')
 
sotr1=Person('Ivan','Ivanov',3)
sotr2=Person('Petr','Petrov',4)
sotr3=Person('Vladimir','Vladimirov',1)
 
sotr1.spisok()
sotr2.spisok()
sotr3.spisok()
a=[sotr1.kvalif,sotr2.kvalif,sotr3.kvalif]
a.sort()
print(a)
while len(a)>0:
    b=a[0]
    print(b)
 
    try:
        if sotr1.kvalif==b:
            a=a[1:]
            del sotr1
    except:
        pass
 
    try:
        if sotr2.kvalif==b:
            a=a[1:]
            del sotr2
    except:
        pass
    try:
        if sotr3.kvalif==b:
            a=a[1:]
            del sotr3
    except:
        pass
Сделал так. Как иначе избежать момент когда обращается к удаленному элементу?

class Person :
  """ Непотрібно присвоювати цей клас жодній з переміних .
      Данні будуть збереженні весь час доки неперезавантажеться  IDE
      Ви вільно можете добавляти дещо більше ніж три поля  в методі -add(self) """ 
  __a = '\t'
  def __new__(cls):
    return super(Person, cls).__new__(cls)
  def __secret(self):
    self.__codRed = False
    self.__kLocal = '101'
    self.key =  input('\t Введіть ключ захисту : ')
    if self.key != self.__kLocal :
      self.key =  input('\t Нехвилюїтесь у Вас є ще одна спроба : ')
      if  self.key != self.__kLocal :
        self.__codRed = True
        return self.__codRed
    return self.__codRed
 
  def add(self):
    #строка коду нижче провірка на секрет
    if Person.__secret(self) == False :
      # в коді нижче  режимі добавлення  
      # ви будете доки ,доки невведете ключеве слово ['save','exit']
      print('\n\n....Поля для добавлення данних про співробітників..')
      Person.__a +=' \n\t' + ' '.join(input('\n\t').split())+' '
      while Person.__a.split(' ')[-2][-4:] not in ['save','exit']:
        Person.__a += '\n\t' +' '.join(input('\t').split(' '))+' '
      Person.__a = ' '.join(Person.__a.split(' ')[:-2])
      print('\t','.'*40)
      print('\tДоступні такі методи - Person().show()')
  def show(self): 
     # вивести дані про всіх співробітників
    if Person.__secret(self) == False :
      print('\n\n\t','.'*50)
      print('\tЦе вся база даних про співробітників вашої установи :')
      print('\t','.'*50)
      print(Person.__a)
      print('\tДоступні такі методи - Person().add()')
 
 
Person().show()

# https://younglinux.info/oopython/init.php
 
class Person:
    def __init__(self, name, surname, skill=1):
        self.name = name
        self.surname = surname
        self.skill = skill
 
    def __str__(self):
        return f'{self.name} {self.surname}, skill level: {self.skill}'
 
    def __del__(self):
        print(f'Good bye, Mr. {self.name} {self.surname}')
 
 
def generate_name(names_list, surnames_list):
    import random
    name = names_list[random.randrange(len(names_list))]
    surname = surnames_list[random.randrange(len(surnames_list))]
    return name, surname
 
 
def find_worst(staff):
    min_skill = min(map(lambda person: person.skill, staff))
    worst = filter(lambda p: p.skill == min_skill, staff)
    return list(worst)
 
def print_staff(staff):
    for p in staff:
        print(p)
 
def main():
    import random
 
    NAMES = ['John', 'Bill', 'Tom', 'Dick', 'Harry', 'Jerry', 'Sam', 'Persy']
    SURNAMES = ['Smith', 'Johnson', 'Martin', 'Brown', 'Jones', 'Miller']
 
    staff = []
    for i in range(3):
        name, surname = generate_name(NAMES, SURNAMES)
        skill = random.randint(1, 9)
        staff.append(Person(name, surname, skill))
 
    print('Current staff:')
    print_staff(staff)
 
    looser = find_worst(staff)[0]
    print(f'\n{looser} is a looser. He\'s to be fired :(')
    staff.remove(looser)
    del(looser)
 
    print('\nRefined staff:')
    print_staff(staff)
 
    input('\nPress a key...')
 
 
if __name__ == '__main__':
    main()

Ну тут без комментариев, задание выполнил, суть усвоил.
print(end='\n'*3)
class Person:
	def __init__(self,n,s,q):
		self.name=n
		self.surname=s
		self.qualification=q
	def inf_employee(self):
		print('Имя сотрудника: {}.'.format(self.name))
		print(end='\n')
		print('Фамилия сотрудника:{}.'.format(self.surname))
		print(end='\n')
		print('Квалификация сотрудника:{}.'.format(self.qualification))
	def __del__(self):
		print(end='\n')
		print('Прощайте мистер {0} {1}.'.format(self.name,self.surname))
 
B=Person('Elliot','Alderson','engineer cyber security')
B.inf_employee()
del B
print(end='\n')
print('Конец программы.')
b=input()

class Person:
    def __init__(self, name, surname, quality = 1):
        self.name = name
        self.surname = surname
        self.quality = quality
 
    def inform(self):
        info = "Name - " + self.name + ", Surname - " + self.surname + ", Quality - " + str(self.quality)
        return info
 
    def __del__(self):
        print("Good bye, mister", self.name, self.surname)
 
 
workers = []
person = ()
persons = []
 
workers.append(Person("Jim", "Porter", 10))
workers.append(Person("John", "Smith", 50))
workers.append(Person("Bill", "Clinton", 100))
 
for worker in workers:
    print(worker.inform())
    person = (worker.quality, worker.name, worker.surname)
    persons.append(person)
 
persons.sort()
looser = persons[0]
 
for worker in workers:    
    if worker.surname == looser[2] and worker.name == looser[1]:
        worker.__del__()
 
input()

#ооп урок 2
#определяем класс
class Person:
	#конструктор
	def __init__(self, name, surname, qual=1):
		self.name = name
		self.surname = surname
		self.qual = qual
	#запрос информации
	def info(self):
		print("{} {}, квалификация {}".format(self.name, self.surname, self.qual))
	#деструктор
	def __del__(self):
		print("До свидания, мистер {} {}".format(self.name, self.surname))
#скрипт
#создаем три экземпляра Person
first_emp = Person("John", "Silver")
second_emp = Person("Pew", "Unknown", 0.3)
third_emp = Person("Billy", "Bones", 0.8)
#выводим инфо о них
first_emp.info()
second_emp.info()
third_emp.info()
#увольняем одного из них
del second_emp
input()

from random import randint
 
class voin:
    hp = 15
    dmg = 1
    def battle(self, vrag):
        vrag.hp -= self.dmg
        print(vrag.dmg, 'хп нанесено', vrag.hp, 'хп осталось',)
 
Hero = voin()
Goblin = voin()
 
while Hero.hp > 0 or Goblin.hp > 0:
    ataka = randint(1, 2)
    if ataka == 1:
        print('ГГ ударил Гоблина')
        Hero.battle(Goblin)
    elif ataka == 2:
        print('Гоблин ударил ГГ')
        Goblin.battle(Hero)
 
if Goblin.hp <= 0:
    print('ГГ убивает Гоблина')
elif Hero.hp <= 0:
    print('Гоблин съедает ГГ')