пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
Слишком длинный поисковый запрос.
По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие
наши статьи:
Хотите работать с объектно-ориентированным проектированием в 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__
и других часто используемых методов; у этого модуля есть большое количество интересных функций: подсказки при вводе кода, задание более сложных значений по умолчанию и оптимизация.
При написании некоторых скриптов бывает нужно обратиться какому-либо ресурсу. Это может быть HTTP/HTTPS запрос какой-нибудь HTML странички сайта, FTP запрос на скачивание файла или же, это может быть GET/POST запрос к удалённому ресурсу, для передачи на него какой-либо информации.
Для этих целей в роутерах MikroTik предусмотрен инструмент Fetch, о нём и поговорим.
Инструмент Fetch позволяет настроить отправку HTTP и FTP запросов к сетевому ресурсу, чтобы скопировать с, или же загрузить на него определённые данеые (web-страничка, файл). Поддержка HTTPS включена по умолчанию, проверка сертификатов, предъявляемых сетевыми ресурсами при запросе, не осуществляется. Включить проверку цепочки сертификации можно с помощью опции check-certificate.
Чтобы начать работу с инструментом Fetch, введите команду:
/tool fetch
Далее нужно задавать параметры ресурса, к которому Вы хотите обратиться, метод обращения и данные, которые нужно получить или загрузить на этот ресурс.
Доступны следующие параметры:
address - задаёт IP адрес ресурса, к которому необходимо обратиться;
ascii - включает поддержку ASCII (по умолчанию - no);
check-certificate - включает проверку цепочки сертификации удаленного ресурса;
dst-path - название файла, который нужно скачать и полный путь к нему на удаленном ресурсе;
host - доменное имя ресурса, к которому нужно обратиться. Например - shareit.merionet.ru;
http-method - метод HTTP обращения. Доступны следующие методы: get, post, put, delete. По умолчанию используется get;
http-data - данные, которые нужно отправить на удаленный ресурс, при использовании методов put и post;
http-content-type - идентификатор данных, которые нужно отправить на удаленный ресурс в формате MIME. По умолчанию - application/x-www-form-urlencoded;
keep-result - если данный параметр активирован, то будет создан входной файл;
mode - задаёт протокол, по которому будет осуществляться соединение с удаленным ресурсом. Можно задать http, https, ftp или tftp;
password - задаёт пароль который нужен для аутентификации на удаленном ресурсе. (Используйте только если удаленный ресурс требует аутентификации подключения);
port - порт, по которому будет осуществляться соединение;
src-path - название файла, который нужно загрузить на удаленный ресурс;
upload - если данный параметр активирован, то инструмент fetch будет использоваться именно для загрузки локального файла на удаленный ресурс. При этом требуется, чтобы были указаны src-path и dst-path файла;
url - URL путь к файлу. Может быть использовано вместо address или src-path;
user - имя пользователя, которое нужно ввести для аутентификации на удаленном ресурсе (используйте только если удаленный ресурс требует аутентификации подключения);
Давайте рассмотрим несколько use кейсов, когда Вам может пригодиться инструмент fetch.
Скачивание файла с удаленного ресурса
В статье про защиту роутера MikroTik методом превентивного блокирования адресов из "черных" списков мы уже прибегали к этому методу.
Для этого мы писали такую команду:
/tool fetch address=www.squidblacklist.org host=www.squidblacklist.org mode=http src-path=/downloads/drop.malicious.rsc
В данном случае, мы обращаемся к ресурсу www.squidblacklist.org по протоколу http и скачиваем файл /downloads/drop.malicious.rsc
Допустим, мы имеем дело с FTP сервером, требующим аутентификации, тогда запрос может быть таким:
/tool fetch address=192.168.11.48 src-path=conf.rsc user=admin mode=ftp password=samplepass dst-path=sample.rsc port=21 host="" keep-result=yes
Можно также указать URL, по которому доступен нужный файл для скачивания:
/tool fetch url="https://wiki.merionet.ru/rukovodstvo-administratora-freepbx-na-russkom-yazyke/Rukovodstvo_Administratora_FreePBX_na_russkom_yazyke.pdf" mode=http
Загрузка файлов на удаленный сервер может быть нужна для автоматизации процесса резервного копирования конфигурации роутера
Ниже приведен пример команды для отправки файла с бэкапом по протоколу FTP, на удаленный сервер по адресу 192.168.11.56, который требует аутентификации:
/tool> fetch address=192.168.11.56 src-path=cnfig.rsc user=admin mode=ftp password=samplepass dst-path=backup.rsc upload=yes
Отправление информации на удаленный сервер
С помощью инструмента fetch можно также отправлять информацию на удаленный сервер, используя HTTP запросы. Например, ниже показан пример того, как можно через POST запрос отправить json массив данных на удаленный сервер:
/tool fetch http-method=post http-content-type="application/json" http-data="{ "as": "AS16509 Amazon.com, Inc.", "city": "Boardman", "country": "United States", "countryCode": "US", "isp": "Amazon", "lat": 45.8696, "lon": -119.688, "org": "Amazon", "query": "54.148.84.95", "region": "OR", "regionName": "Oregon", "status": "success", "timezone": "America/Los_Angeles", "zip": "97818" }" url="http://locator.loc/index.php"
Сохранять результат как переменную
В версии RouterOS v6.43, появилась возможность сохранить результат команды fetch в переменную. Это может быть полезно, например, для написания скриптов, которые производят какие-либо действия в зависимости от того, какой был ответ на HTTP запрос.
Например, ниже приведен пример скрипта, который отсылает письмо SERVICE FAILED, если при запросе страницы PHP (check.php) возвратился “0” и SERVICE RUNNING, если запрос был успешно обработан.
{ :local result [/tool fetch url=http://192.168.11.56/check.php as-value output=user]; :if ($result->"status" = "finished") do={ :if ($result->"data" = "0") do={ /tool e-mail send to="mnadmin@mndomain.ru" subject="$[/system identity get name] export" body="$[/system clock get date] SERVICE FAILED; } else={ /tool e-mail send to="mnadmin@mndomain.ru" subject="$[/system identity get name] export" body="$[/system clock get date] SERVICE RUNNING; } } }
Предварительно, нужно чтобы был настроен почтовый сервер - tool e-mail> set server=192.168.1.34 set port=25 from=”mnmikrotik@mndomain.ru”
Кстати, в WinBox нет отдельной реализации инструмента fetch. Однако, мы можем использовать его, когда пишем скрипты через инструмент Scripts. Например, можно туда добавить скрипт, который мы привели выше:
Вопросы безопасности преследовали Интернет вещей (Internet of Things) с самого момента изобретения. Все, от поставщиков до корпоративных пользователей и потребителей, обеспокоены тем, что их модные новые устройства и системы IoT могут быть скомпрометированы. Проблема на самом деле еще хуже, поскольку уязвимые устройства IoT могут быть взломаны и использованы в гигантских ботнетах, которые угрожают даже правильно защищенным сетям.
Но каких именно проблем и уязвимостей следует избегать при создании, развертывании или управлении системами IoT? И, что более важно, что мы можем сделать, чтобы смягчить эти проблемы?
Именно здесь вступает в действие OWASP (Open Web Application Security Project) - проект обеспечения безопасности открытых веб-приложений. По его собственным словам, «Проект Интернета вещей OWASP призван помочь производителям, разработчикам и потребителям лучше понять проблемы безопасности, связанные с Интернетом вещей, и позволяют пользователям в любом контексте принимать более обоснованные решения в области безопасности при создании, развертывании или оценке технологий IoT».
Давайте рассмотрим топ 10 уязвимостей интернета вещей.
1.Слабые, угадываемые или жестко заданные пароли
Использование легко взламываемых, общедоступных или неизменяемых учетных данных, включая бэкдоры во встроенном программном обеспечении или клиентском программном обеспечении, которое предоставляет несанкционированный доступ к развернутым системам.
Эта проблема настолько очевидна, что трудно поверить, что это все еще то, о чем мы должны думать.
2. Небезопасные сетевые сервисы
Ненужные или небезопасные сетевые службы, работающие на самом устройстве, особенно те, которые подключены к Интернету, которые ставят под угрозу конфиденциальность, целостность или подлинность или доступность информации или допускают несанкционированное удаленное управление.
3. Небезопасные экосистемные интерфейсы
Небезопасный веб-интерфейс, API бэкэнда, облачные или мобильные интерфейсы в экосистеме вне устройства, что позволяет компрометировать устройство или связанные с ним компоненты. Общие проблемы включают в себя отсутствие аутентификации или авторизации, отсутствие или слабое шифрование, а также отсутствие фильтрации ввода и вывода.
4. Отсутствие безопасных механизмов обновления
Отсутствие возможности безопасного обновления устройства. Это включает в себя отсутствие проверки прошивки на устройстве, отсутствие безопасной доставки (без шифрования при передаче), отсутствие механизмов предотвращения отката и отсутствие уведомлений об изменениях безопасности из-за обновлений.
Это постоянная проблема для приложений IoT, так как многие производители и предприятия не заботятся о будущем своих устройств и реализаций. Кроме того, это не всегда технологическая проблема. В некоторых случаях физическое расположение устройств IoT делает обновление - и ремонт или замену - серьезной проблемой.
5. Использование небезопасных или устаревших компонентов
Использование устаревших или небезопасных программных компонентов или библиотек, которые могут позволить скомпрометировать устройство. Это включает небезопасную настройку платформ операционной системы и использование сторонних программных или аппаратных компонентов из скомпрометированной цепочки поставок.
6. Недостаточная защита конфиденциальности
Личная информация пользователя, хранящаяся на устройстве или в экосистеме, которая используется небезопасно, ненадлежащим образом или без разрешения.
Очевидно, что с личной информацией нужно обращаться соответствующим образом. Но ключом здесь является «разрешение». Вы почти ничего не делаете с личной информацией, если у вас нет на это разрешения.
7. Небезопасная передача и хранение данных
Отсутствие шифрования или контроля доступа к конфиденциальным данным в любой точке экосистемы, в том числе в состоянии покоя, передачи или во время обработки.
В то время как многие поставщики IoT обращают внимание на безопасное хранение, обеспечение безопасности данных во время передачи слишком часто игнорируется.
8. Ограниченное управление устройством
Отсутствие поддержки безопасности на устройствах, развернутых в производстве, включая управление активами, управление обновлениями, безопасный вывод из эксплуатации, мониторинг систем и возможности реагирования.
Устройства IoT могут быть небольшими, недорогими и развернутыми в большом количестве, но это не означает, что вам не нужно ими управлять. Фактически, это делает управление ими более важным, чем когда-либо. Даже если это не всегда легко, дешево или удобно.
9. Небезопасные настройки по умолчанию
Устройства или системы поставляются с небезопасными настройками по умолчанию или не имеют возможности сделать систему более безопасной, ограничивая операторов от изменения конфигурации.
10. Отсутствие физического доступа
Отсутствие мер по физической защите, позволяющих потенциальным злоумышленникам получать конфиденциальную информацию, которая может помочь в будущей удаленной атаке или получить локальный контроль над устройством.
Что из этого следует?
Интернет вещей уже давно стал частью реальности, и с ним нельзя забывать о безопасности. И вопросы безопасности должны ложиться не только на плечи производителей, но и на плечи администраторов и обычных пользователей.
