В 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 очень много. Несколько полезных ссылок, где можно почитать про конкретный метод: