- ru
- Language: en
- Documentation version: latest
Подчеркивание в именах
В Python подчеркивание в начале или в конце имени указывает на специальные имена. Чаще всего это всего лишь договоренность, но иногда это действительно влияет на поведение объекта.
Подчеркивание как имя
В Python одно подчеркивание используется для обозначения того, что данные просто выбрасываются.
Например, если из строки line надо получить MAC-адрес, IP-адрес, VLAN и интерфейс и отбросить остальные поля, можно использовать такой вариант:
In [1]: line = '00:09:BB:3D:D6:58 10.1.10.2 86250 dhcp-snooping 10 FastEthernet0/1'
In [2]: mac, ip, _, _, vlan, intf = line.split()
In [3]: print(mac, ip, vlan, intf)
00:09:BB:3D:D6:58 10.1.10.2 10 FastEthernet0/1
Такая запись говорит о том, что нам не нужны третий и четвертый элементы.
Можно сделать так:
In [4]: mac, ip, lease, entry_type, vlan, intf = line.split()
Но тогда может быть непонятно, почему переменные lease и entry_type не используются дальше. Если понятней использовать имена, то лучше назвать переменные именами вроде ignored.
Аналогичный прием может использоваться, когда переменная цикла не нужна:
In [5]: [0 for _ in range(10)]
Out[5]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Подчеркивание в интерпретаторе
В интерпретаторе python и ipython подчеркивание используется для получения результата последнего выражения
In [6]: [0 for _ in range(10)]
Out[6]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
In [7]: _
Out[7]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
In [8]: a = _
In [9]: a
Out[9]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Одно подчеркивание
Одно подчеркивание перед именем
Одно подчеркивание перед именем указывает, что имя используется как внутреннее.
Например, если одно подчеркивание указано в имени функции или метода, это означает, что этот объект является внутренней особенностью реализации и не стоит его использовать напрямую.
Но, кроме того, при импорте вида from module import *
не будут
импортироваться объекты, которые начинаются с подчеркивания.
Например, в файле example.py такие переменные и функции:
db_name = 'dhcp_snooping.db'
_path = '/home/nata/pyneng/'
def func1(arg):
print arg
def _func2(arg):
print arg
Если импортировать все объекты из модуля, то те, которые начинаются с подчеркивания, не будут импортированы:
In [7]: from example import *
In [8]: db_name
Out[8]: 'dhcp_snooping.db'
In [9]: _path
...
NameError: name '_path' is not defined
In [10]: func1(1)
1
In [11]: _func2(1)
...
NameError: name '_func2' is not defined
Одно подчеркивание после имени
Одно подчеркивание после имени используется в том случае, когда имя объекта или параметра пересекается со встроенными именами.
Пример:
In [12]: line = '00:09:BB:3D:D6:58 10.1.10.2 86250 dhcp-snooping 10 FastEthernet0/1'
In [13]: mac, ip, lease, type_, vlan, intf = line.split()
Два подчеркивания
Два подчеркивания перед именем
Два подчеркивания перед именем метода используются не просто как договоренность. Такие имена трансформируются в формат “имя класса + имя метода”. Это позволяет создавать уникальные методы и атрибуты классов.
Такое преобразование выполняется только в том случае, если в конце менее двух подчеркиваний или нет подчеркиваний.
In [14]: class Switch(object):
...: __quantity = 0
...: def __configure(self):
...: pass
...:
In [15]: dir(Switch)
Out[15]:
['_Switch__configure', '_Switch__quantity', ...]
Хотя методы создавались без приставки _Switch
, она была добавлена.
Если создать подкласс, то метод __configure
не перепишет метод
родительского класса Switch:
In [16]: class CiscoSwitch(Switch):
...: __quantity = 0
...: def __configure(self):
...: pass
...:
In [17]: dir(CiscoSwitch)
Out[17]:
['_CiscoSwitch__configure', '_CiscoSwitch__quantity', '_Switch__configure', '_Switch__quantity', ...]
Два подчеркивания перед и после имени
Таким образом обозначаются специальные переменные и методы.
Например, в модуле Python есть такие специальные переменные:
__name__
- эта переменная равна строке__main__
, когда скрипт запускается напрямую, и равна имени модуля, когда импортируется__file__
- эта переменная равна имени скрипта, который был запущен напрямую, и равна полному пути к модулю, когда он импортируется
Переменная __name__
чаще всего используется, чтобы указать, что
определенная часть кода должна выполняться, только когда модуль
выполняется напрямую:
def multiply(a, b):
return a * b
if __name__ == '__main__':
print(multiply(3, 5))
А переменная __file__
может быть полезна в определении текущего пути
к файлу скрипта:
import os
print('__file__', __file__)
print(os.path.abspath(__file__))
Вывод будет таким:
__file__ example2.py
/home/vagrant/repos/tests/example2.py
Кроме того, таким образом в Python обозначаются специальные методы. Эти методы вызываются при использовании функций и операторов Python и позволяют реализовать определенный функционал.
Как правило, такие методы не нужно вызывать напрямую. Но, например, при создании своего класса может понадобиться описать такой метод, чтобы объект поддерживал какие-то операции в Python.
Например, для того, чтобы можно было получить длину объекта, он должен
поддерживать метод __len__
.
Ещё один специальный метод __str__
вызывается, когда используется
оператор print или вызывается функция str(). Если необходимо, чтобы при
этом отображение было в определенном виде, надо создать этот метод в
классе:
In [10]: class Switch(object):
...:
...: def set_name(self, name):
...: self.name = name
...:
...: def __configure(self):
...: pass
...:
...: def __str__(self):
...: return 'Switch {}'.format(self.name)
...:
In [11]: sw1 = Switch()
In [12]: sw1.set_name('sw1')
In [13]: print sw1
Switch sw1
In [14]: str(sw1)
Out[14]: 'Switch sw1'
Таких специальных методов в Python очень много. Несколько полезных ссылок, где можно почитать про конкретный метод: