По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие
наши статьи:
Полученную от маршрутизаторов «соседей» и других устройств в рамках сети роутер хранит в нескольких таблицах. Существует 3 типа таблиц:
Таблица соседей:
Хранит информацию от устройств подключенных напрямую. Вся собранная от соседей информация добавляется в таблицу соседей и включает наименования интерфейсов и соответствующих адресов. По умолчанию, “Hello” пакеты отправляются с интерфейсов каждые 5 секунд, чтобы быть уверенным, что сосед работает. Каждый EIGRP маршрутизатор хранит свой собственный экземпляр такой таблицы. Таким образом:
Каждый маршрутизатор имеет четкое представление о напрямую подключенных устройствах.
Каждый роутер располагает топологией сети в рамках своего ближайшего окружения.
Топологическая таблица:
Представляет собой набор из таблиц других EIGRP устройств полученных от соседей. Данная таблица представляет из себя список сетей назначения и соответствующих метрик. Выглядит данная таблица вот так:
При условии доступность устройств Successor и Feasible Successor они так же присутствуют в таблице для каждой из сетей. Каждый из пунктов маркируется буков A или P, что означает активное или пассивное состояние. Пассивное состояние говорит о том, что роутер знает маршрут к пункту назначения, в то время как активный означает, что топология изменилась и маршрутизатор обновляет данные для данного маршрута. Подчеркнем следующие позиции:
Для каждой из сетей назначения маршрутизатор хранит маршрут через Feasible Successor, т.е маршрут, который считается вторым по приоритету после маршрута через Successor.
Таблица маршрутизации:
Данная таблица представляет собой карту из всех известных маршрутов. Данная таблица строится на основании данных, полученных из топологической таблицы. Можно сказать, что указанные выше таблицы используются для количественной характеристики маршрутов, а таблица маршрутизации дает нам качественную характеристику. Что важно:
Только один маршрут через Successor попадает в таблицу маршрутизации и используется для отправки пакетов (в случае доступности).
Если маршрут через Successor оказывается недоступным, в таблицу маршрутизации из топологической таблицы копируется маршрут через Feasible Successor и используется в качестве альтернативного.
Что такое Successor?
Существует два главных типа устройств в сетях EIGRP. Оба устройства гарантируют отсутствие петель в сети:
Successor: Устройство, которое обеспечивает самую короткую дистанцию маршрута на пути пакета в сеть назначения. Другими словами, это устройство обеспечивает наилучший маршрут в сеть назначения.
Feasible Successor: Это устройство обеспечивает второй по приоритету маршрут в сеть назначения после маршрута Successor – устройства.
Типы пакетов EIGRP
EIGRP использует 5 типов пакетов:
Hello/ACKs пакеты: Это мультикаст пакеты, используемые для обнаружения и отслеживания состояния соседских устройств в сети. Любой Hello пакет должен получить подтверждение, или другими словами ответ – то есть ACK сообщение. Хочется отметить, что ACK пакет является юникастовым.
Updates: Надежные юникастовые пакеты, который содержат обновления маршрутной информации для построения/перестроения таблицы маршрутизации.
Queries: Мультикаст пакеты, которые отправляет устройство при переходе в активное состояние. Если пакет отправляется в качестве ответа, то он будет юникастовым.
Replies: Это надежные юникаст пакеты отправленные в ответ на queries пакеты. Данные пакет говорит получателю о том, что устройство Feasible Successor доступно и не должно переходить в активный режим.
Requests: Ненадежные мультикаст или юникаст пакеты, используемые для сбора информации от соседних устройств.
В следующей статье мы расскажем о сходимости EIGRP сетей.
Сегодня мы расскажем вам, как настроить программный RAID 0 в Windows Server 2016 Core. В интернете полно информации о настройке чередующегося тома (а именно так именуется RAID0) через графический интерфейс. Мы этим заниматься не будем. Мы создадим чередующийся том через консоль.
Для примера возьмем, установленную на Hyper-V виртуальную машину Windows Server 2016 Core.
Предварительно нам необходимо создать два новых жестких диска, которые мы будем переводить в Raid0.
Не включаем виртуальную машину. Нажимаем правой кнопкой мыши на нашей машине. В раскрывшемся меню выбираем пункт Параметры:
В открывшемся окне кликаем по пункту Установка оборудования и выбираем пункт SCSi-контроллер.
Нажимаем Добавить и в следующем окне выбираем пункт Жесткий диск и нажимаем Добавить
В следующем окне из раскрывающегося списка Расположение выбираем номер, который не используется другими устройствами.
После этого, под пунктом Виртуальный жесткий диск нажимаем кнопку Создать
Откроется окно Приступая к работе. Здесь просто приветственное окно и нажимаем Далее.
В окне Выбор формата диска устанавливаете переключатель на нужный вам формат диска. Мы выбрали формат VHDX. Нажимаем Далее.
В окне Выбор типа диска устанавливаете переключатель в необходимый тип диска. На выбор три типа: Фиксированного размера, Динамически расширяемый, Разностный.
И опять нажимаем кнопку Далее и перед нами откроется окно выбора имени диска и его местоположения. Задайте диску имя и укажите место, где он будет располагаться.
Нажимаем Далее. Откроется окно Настройки диска. Здесь необходимо задать объем жесткого диска. Мы установили 40 Gb. Нажимаем кнопку Далее.
Откроется окно Завершение настройки виртуального жесткого диска. Нажимаем Готово и в последнем окне нажимаем ОК.
Аналогичным образом создается второй виртуальный жесткий диск. После того, как создали два диска, включаем нашу виртуальную машину. Входим под учетной записью Администратор’а.Вводим команду Diskpart:
Выбираем Диск 1 командой select disk 1:
Переводим его в режим online: Вводим команду online disk:
Делаем диск динамическим командой convert dynamic:
Может появиться ошибка, что диск защищен от записи. Эта проблема решается вводом команды
Attribute disk clear readonly
И повторно пытаемся сделать диск динамическим. Просматриваем заново наши диски командой list disk
Звездочки напротив диска означают, что диск динамический.
Аналогичные операции проводим и для диска 2. Все команды для диска 2 отображены на рисунке ниже.
Далее, не меняя диск, вводим команду: create volume stripe disk=1,2. Данная команда создает чередующийся том.
Для просмотра результатов выполнения команды вводим команду list volume.
Из рисунка выше видно, что создан новый том (ТОМ3), который является Raid 0 (ЧЕРЕДУЮЩИЙСЯ).
Теперь нам осталось присвоить литеру нашему новому тому.
Для этого вводим команду assign letter=Y и проверяем командой list volume.
Теперь нам надо отформатировать новый том, что бы можно было его использовать для сохранения информации.
Выходим из режима Diskpart командой exit
Для форматирования диска вводим команду следующего типа: format Y: /q /FS:NTFS. После чего система запросит подтверждения выполняемого действия и предупредит, что все данные будут уничтожены. Вводим yes. Начнется процесс форматирования.
P.S. Иногда возникает необходимость установить букву диска, которая уже присвоена другому, например приводу DVD дисков. Для изменения литеры необходимо выполнить ряд команд:
Зайти в diskpart;
Просмотреть тома командой list volume;
Выделить нужный том, на котором необходимо сменить букву- select volume 0;
Удалить присвоенную букву командой remove letter=Y;
Присвоить новую букву- assign letter=V;
Хотите работать с объектно-ориентированным проектированием в Python? Начните уже сегодня, изучив метод Python под названием
__init__
.
В этом руководстве мы пробежимся по основам классов и объектов Python, после чего посмотрим, что же такое метод
__init__
.
После прочтения вы сможете ответить на такие вопросы, как:
Что такое переменные экземпляра класса и атрибуты класса?
Каким образом метод
__init__
инициализирует атрибуты класса?
Как можно установить для атрибутов значения по умолчанию?
Как можно использовать методы класса в качестве конструкторов для создания объектов?
Давайте начнем.
Классы и объекты Python
Классы – это основа объектно-ориентированного программирования в Python. Мы можем создать класс и определить
атрибуты
и
методы
для того, чтобы связать
данные
и соответствующие
функции
.
После того, как вы создадите класс, вы можете использовать его как макет (или шаблон) для создания объектов (экземпляров класса).
Время примеров! Давайте создадим класс
Employee
, где у каждого объекта класса есть следующие атрибуты:
full_name
: полное имя сотрудника в формате
firstName lastName
emp_id
: идентификатор сотрудника
department
: отдел, в котором работает сотрудник
experience
: опыт, который имеет сотрудник (количество лет)
Что это значит?
Каждый отдельный сотрудник – это экземпляр или объект класса
Employee
, и у каждого объекта есть свои значения для атрибутов
full_name
,
emp_id
,
department
и
experience
.
Эти атрибуты также называются
переменными экземпляра
. Дальше мы будем использовать оба термина (атрибуты и переменные экземпляра), так как они взаимозаменяемы.
Атрибуты мы добавим чуть позже. А пока мы создадим класс
Employee
:
class Employee:
pass
Ключевое слово
pass
(которое мы используем в качестве заполнителя) помогает избежать возникновения ошибок при запуске сценария.
Несмотря на то, что такая версия класса
Employee
мало чем может нам помочь, она все же является допустимым классом. Итак, теперь мы можем создавать объекты класса
Employee
:
employee_1 = Employee()
print(employee_1)
#Output: <__main__.Employee object at 0x00FEE7F0>
Кроме того, мы можем добавить атрибуты и инициализировать их значения:
employee_1.full_name = 'Amy Bell'
employee_1.department = 'HR'
Однако при таком подходе довольно часто возникают ошибки, и по сути он считается неэффективным. Кроме того, в данном случае вы не сможете использовать класс в качестве шаблона для создания объектов. И вот здесь на помощь приходит метод
__init__
.
Роль метода __init__ в классе Python
Когда мы создаем экземпляр класса, у нас должна быть возможность инициализировать переменные этого экземпляра, и в этом нам помогает метод
__init__
. Метод
__init__
вызывается каждый раз, когда создается новый объект класса, для того, чтобы инициализировать значения переменных экземпляра.
Если вы когда-нибудь работали с таким языком, как С++, то вы заметите, что метод
__init__
работает по аналогии с конструкторами.
Определение метода __init__
Давайте добавим метод
__init__
в класс
Employee
:
class Employee:
def __init__(self, full_name,emp_id,department,experience):
self.full_name = full_name
self.emp_id = emp_id
self.department = department
self.experience = experience
Параметр
self
- это экземпляр класса, а
self.attribute
присваивает атрибутам экземпляра класса значения, указанные справа.
И теперь мы можем создавать вот такие объекты:
employee_2 = Employee('Bella Joy','M007','Marketing',3)
print(employee_2)
# Output: <__main__.Employee object at 0x017F88B0>
Когда мы попытаемся распечатать объекты, которые обозначают сотрудников, мы не получим никакой полезной информации, кроме класса, к которому они принадлежат. Давайте добавим метод
__repr__
, который будет задавать способ вывода информации для класса:
def __repr__(self):
return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."
Добавим метод
__repr__
в класс
Employee
и получим:
class Employee:
def __init__(self, full_name,emp_id,department,experience):
self.full_name = full_name
self.emp_id = emp_id
self.department = department
self.experience = experience
def __repr__(self):
return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."
Теперь вывод объектов класса
Employee
стал более полезным с точки зрения информации, которую он содержит:
print(employee_2)
# Output: Bella Joy,M007 from Marketing with 3 years of experience.
Некоторые соглашения
Прежде чем двигаться дальше, обратите внимание на несколько замечаний:
Мы использовали
self
в качестве первого параметра в методе
__init__
, чтобы сделать ссылку на сам экземпляр класса, а для инициализации различных атрибутов мы использовали
self.attribute_name
. Рекомендуется использовать именно параметр
self
(впрочем, вы можете использовать любое другое имя).
Когда мы определяли метод
__init__
, мы устанавливали имена параметров так, чтобы они соответствовали именам атрибутов. При таком подходе читать код гораздо проще.
Как добавить значения по умолчанию для атрибутов
В нашем примере до сих пор нет атрибутов, нам нужно их добавить. Под успешным созданием объекта понимается то, что мы должны передать в конструктор значения для всех полей.
Давайте попробует создать экземпляр класса
Employee
, но при этом мы не будем передавать ему значение для атрибута
experience
:
employee_3 = Employee('Jake Lee','E001','Engineering')
Вы получите ошибку:
Traceback (most recent call last):
File "main.py", line 22, in
employee_3 = Employee('Jake Lee','E001','Engineering')
TypeError: __init__() missing 1 required positional argument: 'experience'
Но если вы хотите, чтобы не все атрибуты были обязательными, определяя метод
__init__
, вы можете указать для них значения по умолчанию.
В данном случае мы указали для атрибута
experience
значение по умолчанию
0
:
class Employee:
def __init__(self, full_name,emp_id,department,experience=0):
self.full_name = full_name
self.emp_id = emp_id
self.department = department
self.experience = experience
def __repr__(self):
return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."
Мы смогли создать объект
employee_3
, не указывая значение для атрибута
experience
; значение по умолчанию для этого атрибута – 0.
employee_3 = Employee('Jake Lee','E001','Engineering')
print(employee_3.experience)
# Output: 0
Альтернативные конструкторы классов, которые используют методы класса
Пока мы только разобрали, как можно определить метод
__init__
и как можно установить значения по умолчанию для атрибутов (если это необходимо). Кроме того, мы знаем, что мы должны передать значения в конструктор для всех необходимых атрибутов.
Однако бывают такие ситуации, когда значения этих переменных экземпляра класса (или атрибутов) могут иметь совсем иную структуру данных, например, кортеж, словарь или строка JSON.
Так что же нам делать?
Давайте приведем пример. Представим, что у нас есть значения для переменных экземпляра класса, но они хранятся в словаре Python:
dict_fanny = {'name':'Fanny Walker','id':'H203','dept':'HR','exp':2}
Мы можем обратиться к словарю и получить все атрибуты следующим образом:
name = dict_fanny['name']
id = dict_fanny['id']
dept = dict_fanny['dept']
exp = dict_fanny['exp']
После чего вы можете создать объект, передав все эти значения в конструктор класса:
employee_4 = Employee(name, id, dept, exp)
print(employee_4)
# Output: Fanny Walker,H203 from HR with 2 years of experience.
Не забывайте, что вы должны проделать все это для каждого нового объекта, который вы создаете. Конечно, этот подход нельзя назвать эффективным, и мы безусловно можем сделать лучше.
Но как?
В Python в качестве конструкторов для создания объектов класса мы можем использовать
методы класса
. Для того, чтобы создать метод класса, воспользуемся декоратором
@classmethod
.
Давайте определим метод, который проанализирует словарь, получит значения для переменных экземпляра класса и воспользуется ими для того, чтобы создать объекты класса
Employee
.
@classmethod
def from_dict(cls,data_dict):
full_name = data_dict['name']
emp_id = data_dict['id']
department = data_dict['dept']
experience = data_dict['exp']
return cls(full_name, emp_id, department, experience)
Теперь, когда нам нужно будет создать объекты с помощью данных, которые хранятся в словаре, мы можем использовать метод класса
from_dict()
.
?
Обратите внимание, что в методе класса мы используем не
self
, а
cls
. Здесь все по аналогии: параметр
self
используется для ссылки на экземпляр класса, а
cls
– для ссылки на класс. Кроме того, помните о том, что методы класса привязаны к классу, а не к объектам.
Именно поэтому, когда для создания объектов мы вызываем метод класса
from_dict()
, мы делаем это в классе
Employee
:
И теперь, если у нас есть словарь для каждого из n сотрудников, то для того, чтобы создать экземпляры класса, мы можем воспользоваться методом класса
from_dict()
в качестве конструктора. При этом нам не нужно будет извлекать из словаря значения для переменных экземпляра.
Замечание касательно переменных класса
Здесь мы определили метод класса, который привязан к классу, а не к отдельным экземплярам. Так же как у нас могут быть методы класса, у нас могут быть и переменные класса.
Подобно методам класса,
переменные класса
также привязаны к классу, а не к экземпляру. Когда атрибут принимает некое фиксированное значение (не зависимо от экземпляра класса), мы можем определить его как переменную класса.
Часто задаваемые вопросы
1. Для чего нужен метод __init__ в Python?
Определив в классе метод
__init__
, вы сможете инициализировать атрибуты и переменные класса для всех экземпляров класса. Метод
__init__
необходимо вызывать каждый раз, когда вы создаете новый экземпляр.
2. Может ли быть несколько методов __init__ в классе Python?
В чем состоит цель наличия нескольких методов
__init__
? Возможность иметь несколько конструкторов для создания экземпляров класса. Однако вы не можете определить несколько методов
__init__
. Если вы попытаетесь определить несколько методов
__init__
, то каждый последующий будет переопределять предыдущий. И тем не менее, вы можете воспользоваться декоратором
@classmethod
для того, чтобы определить методы класса. Эти методы класса можно использовать в качестве конструкторов для создания экземпляров класса.
3. Что будет, если вы не определите метод __init__ в классе?
Если вы не определите метод
__init__
, вы в любом случае сможете создавать экземпляры класса. Но в таком случае вам придется самостоятельно добавлять переменные экземпляров и присваивать им значения. Вы не сможете передать значения для переменных экземпляра через конструктор. Это не только может привести к возникновению ошибок, но и в принципе противоречит цели наличия классов как шаблонов, с помощью которых мы можем создавать экземпляры классов.
4. Можно ли установить значения по умолчанию для аргументов в методе __init__?
Да, при определении метода
__init__
вы можете указать значения по умолчанию для одного или нескольких атрибутов. Таким образом, вы можете сделать эти атрибуты необязательными. В случае, если вы не передадите значение для этих атрибутов в конструкторе, то они примут соответствующие значения по умолчанию.
5. Можно ли менять значение атрибута вне метода __init__?
Да, вы всегда можете поменять значение атрибута вне метода
__init__
. Кроме того, после того, как вы создадите отдельный экземпляр, вы можете динамически добавлять в нему новые атрибуты.
Заключение
В этом руководстве мы разобрали, как можно использовать метод
__init__
для инициализации значений переменных экземпляра класса. Но несмотря на то, что это просто, это может оказаться довольно рутинно, так как вы без конца будете повторять одни и те же действия, особенно если у вас много атрибутов.
Если вам интересно, то вы можете изучить, что такое классы данных (dataclasses). В Python 3.7 и более поздних версиях для создания классов данных, в которых хранятся данные, вы можете использовать модуль
dataclasses
. Его можно использовать как дополнение к методу
__init__
и других часто используемых методов; у этого модуля есть большое количество интересных функций: подсказки при вводе кода, задание более сложных значений по умолчанию и оптимизация.
