Конструктор класса – метод __init__
В объектно-ориентированном программировании конструктором класса называют метод, который автоматически вызывается при создании объектов. Его также можно назвать конструктором объектов класса. Имя такого метода обычно регламентируется синтаксисом конкретного языка программирования. Так в Java имя конструктора класса совпадает с именем самого класса. В Python же роль конструктора играет метод __init__ .
В Python наличие пар знаков подчеркивания спереди и сзади в имени метода говорит о том, что он принадлежит к группе методов перегрузки операторов. Если подобные методы определены в классе, то объекты могут участвовать в таких операциях как сложение, вычитание, вызываться как функции и др.
При этом методы перегрузки операторов не надо вызывать по имени. Вызовом для них является сам факт участия объекта в определенной операции. В случае конструктора класса – это операция создания объекта. Так как объект создается в момент вызова класса по имени, то в этот момент вызывается метод __init__ .
Необходимость конструкторов связана с тем, что нередко объекты должны иметь собственные свойства сразу. Пусть имеется класс Person , объекты которого обязательно должны иметь имя и фамилию. Если класс будет описан подобным образом
class Person: def set_name(self, n, s): self.name = n self.surname = s
то создание объекта возможно без полей. Для установки имени и фамилии метод set_name нужно вызывать отдельно:
>>> from test import Person >>> p1 = Person() >>> p1.set_name("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 "", line 1, in 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__ .
Напишите программу по следующему описанию:
- Есть класс Person , конструктор которого принимает три параметра (не учитывая self ) – имя, фамилию и квалификацию специалиста. Квалификация имеет значение заданное по умолчанию, равное единице.
- У класса Person есть метод, который возвращает строку, включающую в себя всю информацию о сотруднике.
- Класс Person содержит деструктор, который выводит на экран фразу «До свидания, мистер …» (вместо троеточия должны выводиться имя и фамилия объекта).
- В основной ветке программы создайте три объекта класса Person . Посмотрите информацию о сотрудниках и увольте самое слабое звено.
- В конце программы добавьте функцию input() , чтобы скрипт не завершился сам, пока не будет нажат Enter . Иначе вы сразу увидите как удаляются все объекты при завершении работы программы.
Курс с примерами решений практических работ:
pdf-версия
X Скрыть Наверх
Объектно-ориентированное программирование на Python
Может ли в одном классе быть несколько конструкторов?
Доброго времени суток. Программируя на питоне, возникла потребность создать несколько конструкторов в одном классе. Может ли кто подсказать, есть ли такая возможность в питоне, и если есть, как правильно это реализовать. Буду особо благодарен, если кто-то сможет скинуть пример.
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
как правильно сделать в одном запросе может быть несколько подзапросов
Народ подскажите как правильно сделать запрос SELECT id,title FROM table (IN SELECT cat.
Несколько пользовательских элементов в одном классе
Вечер добрый, Может кто-то может подсказать, как собрать несколько пользовательских элементов.

Как может быть в классе 2 одинаковых функции?
Открываю рабочий проект и там вижу такие вот строки public abstract class MainMenu .
840 / 478 / 58
Регистрация: 18.09.2012
Сообщений: 1,688
Petrol1342, вам придёться в одном конструкторе в зависимости от параметров делать то или иное. А конкретно, что вы хотите?
Регистрация: 11.09.2013
Сообщений: 22
Класс, который я пытаюсь написать, создает многомерный массив. Требуется, чтобы массив, в зависимости от данных вводимых пользователем заполнялся разными значениями: в первом случае конструктор принимает n — размерность, а далее по порядку пределы изменения индексов; во втором случае конструктор принимает размерность, а далее по порядку символьные переменные, которые этот массив заполнят. Эта конструкция взята из матлаба, там это все реализовано. Собственно, пытаемся сделать это теперь в питоне
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
можешь в __init__ сделать условие
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
>>> class A: . def __init__(self, *args): . a1 = args[0] . rest = args[1:] . if type(a1) == int: . self.type = 1 . self.n = a1 . self.pred = rest . elif type(a1) == tuple: . self.type = 2 . self.i, self.j = a1 . self.chars = rest . . def print(self): . if self.type == 1: . print(self.n, self.pred) . elif self.type == 2: . print(self.i, self.j, self.chars) . >>> a1 = A(2, (1, 2), (3, 4)) >>> a2 = A((2, 3), 'a', 'b') >>> >>> a1.print() 2 ((1, 2), (3, 4)) >>> a2.print() 2 3 ('a', 'b') >>>
Наследование — Python: Введение в ООП
Все классы, которые мы рассматривали до этого, создавались «с нуля». И до тех пор, пока описываемые классами сущности мало похожи друг на друга, создание абсолютно новых классов работает отлично. Но что делать, если мы хотим, чтобы пара классов содержала один и тот же метод — не одноименный, а именно копию?
Конечно же, мы можем при объявлении класса вместо объявления метода по месту поместить в атрибут ссылку на существующую функцию. И это даже сработает! Но когда таковых методов станет несколько, уследить за тем, что и куда копируется, станет очень сложно. К счастью, есть способ лучше!
Языки, реализующие инструментарий для объектно ориентированного программирования, включая использование классов, предоставляют и механизм наследования. Python — один из таких языков. Поэтому классы в Python можно наследовать.
Когда один класс становится наследником другого, то все атрибуты класса-предка (надкласса, superclass) становятся доступны классу-потомку (подклассу, subclass) — наследуются (достаются в наследство).
Что дает наследование
Наследование позволяет выделить общее для нескольких классов поведение и вынести его в отдельную сущность. То есть наследование является средством переиспользования кода (code reuse) — использования существующего кода для решения новых задач!
Наследование позволяет получить новый класс, немного отличающийся от старого. При этом нам не нужно иметь доступ к коду исходного класса, а значит с помощью наследования мы можем адаптировать (использовать повторно) под наши задачи, в том числе и чужие классы!
Как обычно, рассмотрим пример:
# этот класс у нас уже был class Counter: def __init__(self): self.value = 0 def inc(self): self.value += 1 def dec(self): self.value -= 1 # А этот класс - новый. Наследник Counter class NonDecreasingCounter(Counter): # в скобках указан класс-предок def dec(self): pass
Если мы выполним эти объявления классов и посмотрим на поведение экземпляра NonDecreasingCounter , то увидим, что он работает как Counter — имеет те же методы и атрибуты (правда, при вызове метода .dec новый счетчик не изменяет текущее значение):
n = NonDecreasingCounter() n.inc() n.inc() n.value # 2 n.dec() n.value # 2
В объявлении NonDecreasingCounter присутствует метод dec , а вот откуда взялись value и inc ? Они были взяты от предка — класса Counter ! Данный факт даже можно пронаблюдать:
n.dec # > n.inc # >
Метод dec — метод класса NonDecreasingCounter , связанный с конкретным экземпляром NonDecreasingCounter . А вот inc — метод класса Counter , хоть и связанный с все тем же экземпляром класса-потомка.
Здесь вы можете увидеть сходство с взаимоотношениями между классом и его экземпляром: если экземпляр получает свой собственный атрибут, то этот атрибут заменяет атрибут класса. Точно так же объявления в классе-потомке заменяют собой атрибуты класса-предка, если имя используется то же самое — говорят, переопределяют (override).
И, как и в случае с объектом, который может использовать все содержимое класса и заменять только небольшую часть атрибутов (или добавлять новые!), так и потомок по умолчанию получает все атрибуты предка, часть из которых может изменить.
Все будет super()
Представим, что нас в целом устраивает класс Counter из предыдущего примера, но мы хотим при вызове inc увеличивать значение дважды. Мы могли бы заменить в потомке весь метод и прописать внутри нового метода self.value += 2 . Но если бы позже что-то поменялось в исходном классе Counter , то эти изменения не коснулись бы нашего метода.
Получается, что нам внутри метода потомка нужно получить доступ к методу предка. Методу с тем же именем! Если мы просто обратимся к self.inc , то получим ссылку на новый метод, ведь мы его переопределили.
Тут нам на помощь приходит специальная функция super :
class DoubleCounter(Counter): def inc(self): super().inc() super().inc()
Вызов super здесь заменяет обращение к self . При этом вы фактически обращаетесь к «памяти предков»: получаете ссылку на атрибут предка. Более того, в данном случае, super().inc — это связанный с текущим экземпляром метод, то есть полноценная «оригинальная версия» из класса-предка. Если бы вы вдруг решили вручную вызвать метод класса предка, то вам бы пришлось использовать его не связанную версию:
class DoubleCounter(Counter): def inc(self): Counter.inc(self) # явно обращаемся к методу класса предка Counter.inc(self) # и передаем ссылку на экземпляр
Вызов super вместо явного вызова предка хорош не только тем, что автоматически связывает методы. При смене предка (такое бывает) в описании класса super учтет изменения, и вы получите доступ к поведению нового предка. Удобно!
super работает не только с методами, но и с атрибутами классов:
class A: x = 'A' class B(A): x = 'B' def super_x(self): return super().x B().x # 'B' B().super_x() # 'A'
Но важно помнить, что super работает именно с классами. Вы не сможете получить доступ к атрибутам, которые добавляются в объект уже после того, как тот будет создан.
Функция super так названа в честь названия класса-предка: «superclass».
Вызов инициализатора суперкласса с super()
При наследовании классов часто возникает необходимость не только добавить новые атрибуты или методы, но и расширить или изменить инициализацию объекта. В этом случае очень важно корректно вызвать конструктор суперкласса, чтобы все атрибуты и состояние, которые должны быть наследованы, были правильно установлены.
Использование super() в __init__ позволяет нам вызвать конструктор суперкласса, что гарантирует, что весь необходимый код инициализации будет выполнен:
class Counter: def __init__(self): self.value = 0 def inc(self): self.value += 1 def dec(self): self.value -= 1 class NonDecreasingCounter(Counter): def __init__(self): super().__init__() # Вызываем конструктор предка self.non_decreasing = True # Дополнительный атрибут для наследника def dec(self): if self.non_decreasing: print("Уменьшение значения запрещено.") else: super().dec() # Вызываем метод dec предка, если уменьшение разрешено n = NonDecreasingCounter() n.inc() print(n.value) # 1 n.dec() # Уменьшение значения запрещено. print(n.value) # 1 n.non_decreasing = False n.dec() print(n.value) # 0
В этом примере метод __init__ в NonDecreasingCounter вызывает метод __init__ предка Counter с помощью super() . Это гарантирует, что атрибут value инициализируется как в Counter . Класс NonDecreasingCounter добавляет дополнительный атрибут non_decreasing и изменяет поведение метода dec , чтобы контролировать, может ли счетчик уменьшаться. Это демонстрирует, как можно расширить и настроить поведение классов при наследовании.
В контексте множественного наследования использование super() становится еще более важным, так как оно гарантирует, что все конструкторы суперклассов вызываются в правильном порядке. Это предотвращает проблемы с инициализацией и позволяет каждому классу в иерархии наследования вносить свой вклад в конечное состояние объекта.
Наследование и object
В прошлом мы не указывали предка в объявлениях классов, то есть писали так:
class Foo: pass
В Python3 такая запись равнозначна записи class Foo(object): . То есть, если класс-предок не указан, то таковым считается object — самый базовый класс в Python. Сейчас, в эпоху повсеместного использования Python3, указывать или не указывать наследование от object — дело вкуса.
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Класс и объект в Python
Python — это процедурно-ориентированный и одновременно объектно-ориентированный язык программирования.
Процедурно-ориентированный
«Процедурно-ориентированный» подразумевает наличие функций. Программист может создавать функции, которые затем используются в сторонних скриптах.
Объектно-ориентированный
«Объектно-ориентированный» подразумевает наличие классов. Есть возможность создавать классы, представляющие собой прототипы для будущих объектов.
Создание класса в Python
Синтаксис для написания нового класса:
class ClassName: 'Краткое описание класса (необязательно)' # Код .
- Для создания класса пишется ключевое слово class , его имя и двоеточие (:). Первая строчка в теле класса описывает его. (По желанию) получить доступ к этой строке можно с помощью ClassName.__doc__
- В теле класса допускается объявление атрибутов, методов и конструктора.
Атрибут:
Атрибут — это элемент класса. Например, у прямоугольника таких 2: ширина ( width ) и высота ( height ).
Метод:
- Метод класса напоминает классическую функцию, но на самом деле — это функция класса. Для использования ее необходимо вызывать через объект.
- Первый параметр метода всегда self (ключевое слово, которое ссылается на сам класс).
Конструктор:
- Конструктор — уникальный метод класса, который называется __init__ .
- Первый параметр конструктора во всех случаях self (ключевое слово, которое ссылается на сам класс).
- Конструктор нужен для создания объекта.
- Конструктор передает значения аргументов свойствам создаваемого объекта.
- В одном классе всегда только один конструктор.
- Если класс определяется не конструктором, Python предположит, что он наследует конструктор родительского класса.
# Прямоугольник. class Rectangle : 'Это класс Rectangle' # Способ создания объекта (конструктор) def __init__(self, width, height): self.width= width self.height = height def getWidth(self): return self.width def getHeight(self): return self.height # Метод расчета площади. def getArea(self): return self.width * self.height
Создание объекта с помощью класса Rectangle:

# Создаем 2 объекта: r1 & r2 r1 = Rectangle(10,5) r2 = Rectangle(20,11) print("r1.width token punctuation">, r1.width) print("r1.height token punctuation">, r1.height) print("r1.getWidth() token punctuation">, r1.getWidth()) print("r1.getArea() token punctuation">, r1.getArea()) print("-----------------") print("r2.width token punctuation">, r2.width) print("r2.height token punctuation">, r2.height) print("r2.getWidth() token punctuation">, r2.getWidth()) print("r2.getArea() token punctuation">, r2.getArea())

Что происходит при создании объекта с помощью класса?
При создании объекта класса Rectangle запускается конструктор выбранного класса, и атрибутам нового объекта передаются значения аргументов. Как на этом изображении:

Конструктор с аргументами по умолчанию
В других языках программирования конструкторов может быть несколько. В Python — только один. Но этот язык разрешает задавать значение по умолчанию.
Все требуемые аргументы нужно указывать до аргументов со значениями по умолчанию.
class Person: # Параметры возраста и пола имеют значение по умолчанию. def __init__(self, name, age=1, gender="Male"): self.name = name self.age = age self.gender= gender def showInfo(self): print("Name: ", self.name) print("Age: ", self.age) print("Gender: ", self.gender)
from person import Person # Создать объект Person. aimee = Person("Aimee", 21, "Female") aimee.showInfo() print(" --------------- ") # возраст по умолчанию, пол. alice = Person( "Alice" ) alice.showInfo() print(" --------------- ") # Пол по умолчанию. tran = Person("Tran", 37) tran.showInfo()

Сравнение объектов
В Python объект, созданный с помощью конструктора, занимает реальное место в памяти. Это значит, что у него есть точный адрес.
Если объект AA — это просто ссылка на объект BB , то он не будет сущностью, занимающей отдельную ячейку памяти. Вместо этого он лишь ссылается на местоположение BB .

Оператор == нужен, чтобы узнать, ссылаются ли два объекта на одно и то же место в памяти. Он вернет True , если это так. Оператор != вернет True , если сравнить 2 объекта, которые ссылаются на разные места в памяти.
from rectangle import Rectangle r1 = Rectangle(20, 10) r2 = Rectangle(20 , 10) r3 = r1 # Сравните r1 и r2 test1 = r1 == r2 # --> False # Сравните r1 и r3 test2 = r1 == r3 # --> True print ("r1 == r2 ? ", test1) print ("r1 == r3 ? ", test2) print (" -------------- ") print ("r1 != r2 ? ", r1 != r2) print ("r1 != r3 ? ", r1 != r3)

Атрибуты
В Python есть два похожих понятия, которые на самом деле отличаются:
- Атрибуты
- Переменные класса
Стоит разобрать на практике:
class Player: # Переменная класса minAge = 18 maxAge = 50 def __init__(self, name, age): self.name = name self.age = age
Атрибут
Объекты, созданные одним и тем же классом, будут занимать разные места в памяти, а их атрибуты с «одинаковыми именами» — ссылаться на разные адреса. Например:

from player import Player player1 = Player("Tom", 20) player2 = Player("Jerry", 20) print("player1.name token punctuation">, player1.name) print("player1.age token punctuation">, player1.age) print("player2.name token punctuation">, player2.name) print("player2.age token punctuation">, player2.age) print(" ------------ ") print("Assign new value to player1.age = 21 ") # Присвойте новое значение атрибуту возраста player1. player1.age = 21 print("player1.name token punctuation">, player1.name) print("player1.age token punctuation">, player1.age) print("player2.name token punctuation">, player2.name) print("player2.age token punctuation">, player2.age)

Python умеет создавать новые атрибуты для уже существующих объектов. Например, объект player1 и новый атрибут address .
from player import Player player1 = Player("Tom", 20) player2 = Player("Jerry", 20) # Создайте новый атрибут с именем «address» для player1. player1.address = "USA" print("player1.name token punctuation">, player1.name) print("player1.age token punctuation">, player1.age) print("player1.address token punctuation">, player1.address) print(" ------------------- ") print("player2.name token punctuation">, player2.name) print("player2.age token punctuation">, player2.age) # player2 е имеет атрибута 'address' (Error!!) print("player2.address token punctuation">, player2.address)
player1.name = Tom player1.age = 20 player1.address = USA ------------------- player2.name = Jerry player2.age = 20 Traceback (most recent call last): File "C:/Users/gvido/class.py", line 27, in print("player2.address атрибуты-функции"> Атрибуты функции Обычно получать доступ к атрибутам объекта можно с помощью оператора «точка» (например, player1.name). Но Python умеет делать это и с помощью функции.
Функция Описание getattr (obj, name[,default])Возвращает значение атрибута или значение по умолчанию, если первое не было указано hasattr (obj, name)Проверяет атрибут объекта — был ли он передан аргументом «name» setattr (obj, name, value)Задает значение атрибута. Если атрибута не существует, создает его delattr (obj, name)Удаляет атрибут
from player import Player player1 = Player("Tom", 20) # getattr(obj, name[, default]) print("getattr(player1,'name') token punctuation">, getattr(player1,"name")) print("setattr(player1,'age', 21): ") # setattr(obj,name,value) setattr(player1,"age", 21) print("player1.age token punctuation">, player1.age) # Проверка, что player1 имеет атрибут 'address'? hasAddress = hasattr(player1, "address") print("hasattr(player1, 'address') ? ", hasAddress) # Создать атрибут 'address' для объекта 'player1' print("Create attribute 'address' for object 'player1'") setattr(player1, 'address', "USA") print("player1.address token punctuation">, player1.address) # Удалить атрибут 'address'. delattr(player1, "address")
getattr(player1,'name') = Tom setattr(player1,'age', 21): player1.age = 21 hasattr(player1, 'address') ? False Create attribute 'address' for object 'player1' player1.address = USA
Встроенные атрибуты класса
Объекты класса — дочерние элементы по отношению к атрибутам самого языка Python. Таким образом они заимствуют некоторые атрибуты:
Атрибут
Описание
__dict__
Предоставляет данные о классе коротко и доступно, в виде словаря
__doc__
Возвращает строку с описанием класса, или None , если значение не определено
__class__
Возвращает объект, содержащий информацию о классе с массой полезных атрибутов, включая атрибут __name__
__module__
Возвращает имя «модуля» класса или __main__ , если класс определен в выполняемом модуле.
class Customer: 'Это класс Customer' def __init__(self, name, phone, address): self.name = name self.phone = phone self.address = address john = Customer("John",1234567, "USA") print ("john.__dict__ token punctuation">, john.__dict__) print ("john.__doc__ token punctuation">, john.__doc__) print ("john.__class__ token punctuation">, john.__class__) print ("john.__class__.__name__ token punctuation">, john.__class__.__name__) print ("john.__module__ token punctuation">, john.__module__)
john.__dict__ = john.__doc__ = Это класс Customer john.__class__ = john.__class__.__name__ = Customer john.__module__ = __main__
Переменные класса
Переменные класса в Python — это то же самое, что Field в других языках, таких как Java или С#. Получить к ним доступ можно только с помощью имени класса или объекта.
Для получения доступа к переменной класса лучше все-таки использовать имя класса, а не объект. Это поможет не путать «переменную класса» и атрибуты.

У каждой переменной класса есть свой адрес в памяти. И он доступен всем объектам класса.
from player import Player player1 = Player("Tom", 20) player2 = Player("Jerry", 20) # Доступ через имя класса. print ("Player.minAge token punctuation">, Player.minAge) # Доступ через объект. print("player1.minAge token punctuation">, player1.minAge) print("player2.minAge token punctuation">, player2.minAge) print(" ------------ ") print("Assign new value to minAge via class name, and print..") # Новое значение minAge через имя класса Player.minAge = 19 print("Player.minAge token punctuation">, Player.minAge) print("player1.minAge token punctuation">, player1.minAge) print("player2.minAge token punctuation">, player2.minAge)
Player.minAge = 18 player1.minAge = 18 player2.minAge = 18 ------------ Assign new value to minAge via class name, and print.. Player.minAge = 19 player1.minAge = 19 player2.minAge = 19
Составляющие класса или объекта
В Python присутствует функция dir , которая выводит список всех методов, атрибутов и переменных класса или объекта.
from player import Player # Вывести список атрибутов, методов и переменных объекта 'Player' print(dir(Player)) print("\n\n") player1 = Player("Tom", 20) player1.address ="USA" # Вывести список атрибутов, методов и переменных объекта 'player1' print(dir(player1))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'maxAge', 'minAge'] ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'address', 'age', 'maxAge', 'minAge', 'name']