Попробуйте:
<([^\s]+)(\s[^>]*?)?(?<!/)>
Он похож на ваш, но последний >
не должен быть после косой черты, а также принимает h1
.
Имена в классе с лидирующим подчеркиванием просто указывают другим программистам, что атрибут или метод предназначены для того, чтобы быть закрытыми. Однако ничего не делается с самим именем.
Чтобы процитировать PEP-8 :
_single_leading_underscore: слабый индикатор «внутреннего использования». Например.
from M import *
не импортирует объекты, чье имя начинается с символа подчеркивания.Double Underscore (Name Mangling)
Из документов Python :
Любой идентификатор формы
__spam
(по крайней мере два ведущих символа подчеркивания, не более одного подчеркивания подчеркивания) заменяется на текст на_classname__spam
, гдеclassname
- это текущее имя класса с ведущими подчеркивание (ы) раздели. Это манипулирование выполняется без учета синтаксической позиции идентификатора, поэтому его можно использовать для определения переменных класса, класса, переменных, хранящихся в глобальных переменных, и даже переменных, хранящихся в экземплярах. частный для этого класса на экземплярах других классов.И предупреждение с той же страницы:
Назначение имени предназначено, чтобы дать классам простой способ определить «частные» переменные экземпляра и методы без приходится беспокоиться о переменных экземпляра, определяемых производными классами, или обманывать переменные экземпляра кодом вне класса. Обратите внимание, что правила манипуляции предназначены главным образом для предотвращения несчастных случаев; [7]
Пример
>>> class MyClass(): ... def __init__(self): ... self.__superprivate = "Hello" ... self._semiprivate = ", world!" ... >>> mc = MyClass() >>> print mc.__superprivate Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: myClass instance has no attribute '__superprivate' >>> print mc._semiprivate , world! >>> print mc.__dict__ {'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
Получение фактов _ и __ довольно легко; другие ответы выражают их довольно хорошо. Использование намного сложнее определить.
Вот как я это вижу:
_
Следует использовать, чтобы указать, что функция не предназначена для публичного использования, например, для API. Это и ограничение импорта заставляют его вести себя так же, как internal
в c #.
__
Следует использовать, чтобы избежать столкновения имен в иерархии inheritace и избежать latebinding.
==>
Если вы хотите указать, что что-то не для общего пользования, но оно должно действовать как protected
использовать _
. Если вы хотите указать, что что-то не для общего пользования, но оно должно действовать как private
use __
.
Это также цитата, которая мне очень нравится:
Проблема заключается в том, что автор класса может законно думать, что «это имя атрибута / метода должно быть закрытым, доступным только из этого определения класса» и использовать соглашение __private. Но в дальнейшем пользователь этого класса может сделать подкласс, который законно нуждается в доступе к этому имени. Поэтому либо надкласс должен быть изменен (что может быть сложно или невозможно), либо код подкласса должен использовать вручную искаженные имена (что в лучшем случае является уродливым и хрупким).
blockquote>проблема в том, что, на мой взгляд, если нет IDE, которая предупреждает вас, когда вы переопределяете методы, поиск ошибки может занять некоторое время, если вы случайно завершили метод из базового класса.
._variable
является полуприватым и подразумевается только для соглашения
.__variable
часто неправильно считается суперприватом, в то время как фактическое значение просто для предотвращения случайного доступа [1]
.__variable__
обычно зарезервирован для встроенных методов или переменных
Вы можете получить доступ к .__mangled
переменным, если вы отчаянно хотите. Двойное подчеркивание просто намещает или переименовывает переменную в нечто вроде instance._className__mangled
Пример:
class Test(object):
def __init__(self):
self.__a = 'a'
self._b = 'b'
>>> t = Test()
>>> t._b
'b'
t._b доступен, поскольку он скрыт только по соглашению
>>> t.__a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'
t .__ a не найден потому, что он больше не существует из-за namemangling
>>> t._Test__a
'a'
. При доступе к instance._className__variable
вместо имени двойного подчеркивания вы можете получить доступ к скрытое значение
Подчеркивание (_) в Python
Ниже приведены разные места, где _ используется в Python:
Single Underscore:
Double Underscore:
В интерпретаторе:
_ возвращает значение последнего выполненного выражения в Python REPL ]
>>> a = 10
>>> b = 10
>>> _
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_' is not defined
>>> a+b
20
>>> _
20
>>> _ * 2
40
>>> _
40
>>> _ / 2
20
Для игнорирования значений:
Несколько раз мы не хотим, чтобы возвращаемые значения в это время присваивали эти значения wnderscore. Он использовался как переменная throwaway.
# Ignore a value of specific location/index
for _ in rang(10)
print "Test"
# Ignore a value when unpacking
a,b,_,_ = my_method(var1)
После имени
Python имеет свои ключевые слова по умолчанию, которые мы не можем использовать в качестве имени переменной. Чтобы избежать такого конфликта между ключевыми словами и переменной python, мы используем символ подчеркивания после имени
Пример:
>>> class MyClass():
... def __init__(self):
... print "OWK"
>>> def my_defination(var1 = 1, class_ = MyClass):
... print var1
... print class_
>>> my_defination()
1
__main__.MyClass
>>>
Перед именем
Ведущее подчеркивание перед переменной / функцией / имя метода указывает программисту, что оно предназначено только для внутреннего использования, которое может быть изменено всякий раз, когда требуется класс.
Здесь префикс имени by underscore рассматривается как непубличный. Если указать из Import *, все имя начинается с _, то не будет импортироваться.
Python не указывает действительно закрытый, так что это могут быть вызовы непосредственно из других модулей, если они указаны во всех, Мы также называем это слабым Частный
class Prefix:
... def __init__(self):
... self.public = 10
... self._private = 12
>>> test = Prefix()
>>> test.public
10
>>> test._private
12
Python class_file.py
def public_api():
print "public api"
def _private_api():
print "private api"
Вызов файла из REPL
>>> from class_file import *
>>> public_api()
public api
>>> _private_api()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_private_api' is not defined
>>> import class_file
>>> class_file.public_api()
public api
>>> class_file._private_api()
private api
Double Underscore(__)
__ leading_double_underscore
Ведущий двойной подчеркивание говорит интерпретатору python, чтобы переписать имя, чтобы избежать конфликта в подклассе. Интерпретатор изменяет имя переменной с расширением класса и эту функцию, известную как Mangling. testFile.py
class Myclass():
def __init__(self):
self.__variable = 10
Вызов из REPL
>>> import testFile
>>> obj = testFile.Myclass()
>>> obj.__variable
Traceback (most recent call last):
File "", line 1, in
AttributeError: Myclass instance has no attribute '__variable'
nce has no attribute 'Myclass'
>>> obj._Myclass__variable
10
В Mangling интерпретатор python измените имя переменной на ___. Таким образом, множественное время используется как частный член, потому что другой класс не может напрямую обращаться к этой переменной. Основной целью __ является использование переменной / метода только в классе. Если вы хотите использовать его вне класса, вы можете сделать общедоступным api
class Myclass():
def __init__(self):
self.__variable = 10
def func(self)
print self.__variable
Вызов из REPL
>>> import testFile
>>> obj = testFile.Myclass()
>>> obj.func()
10
__ BEFORE_AFTER __
Имя с началом с __ и заканчивается тем же, что и специальные методы в Python. Python предоставляет эти методы для использования в качестве перегрузки оператора в зависимости от пользователя.
Python предоставляет это соглашение для различения определяемой пользователем функции с функцией модуля
class Myclass():
def __add__(self,a,b):
print a*b
. Вызов из REPL
>>> import testFile
>>> obj = testFile.Myclass()
>>> obj.__add__(1,2)
2
>>> obj.__add__(5,2)
10
Одиночное подчеркивание в начале:
У Python нет реальных частных методов, поэтому одно подчеркивание в начале имени метода или атрибута означает, что вы не должны обращаться к этому методу, потому что это не часть API.
class BaseForm(StrAndUnicode):
def _get_errors(self):
"Returns an ErrorDict for the data provided for the form"
if self._errors is None:
self.full_clean()
return self._errors
errors = property(_get_errors)
фрагмент кода, взятый из исходного кода django (django / forms / forms.py). Это означает, что ошибки являются свойством, и это часть модуля, но метод, который это свойство вызывает, _get_errors, является «закрытым», поэтому вы не должны обращаться к нему.
Два подчеркивания в начале:
Это вызывает много путаницы. Его нельзя использовать для создания частного метода. Его следует использовать, чтобы избежать переопределения вашего метода подклассом или доступа к нему случайно. Давайте посмотрим пример:
class A(object):
def __test(self):
print "I'm test method in class A"
def test(self):
self.__test()
a = A()
a.test()
Выход:
$ python test.py
I'm test method in class A
Теперь создайте подкласс B и выполните настройку для метода __test
class B(A):
def __test(self):
print "I'm test method in class B"
b = B()
b.test()
Выход будет be ....
$ python test.py
I'm test method in class A
Как мы видели, A.test () не называл методы B .__ test (), как и следовало ожидать. Но на самом деле это правильное поведение для __. Поэтому, когда вы создаете метод, начинающийся с __, это означает, что вы не хотите, чтобы кто-либо мог его переопределить, он будет доступен только изнутри собственного класса.
Два подчеркивания в начале и в начале в конце:
Когда мы видим такой метод, как __this__
, не называйте его. Потому что это означает, что это метод, который питон звонит, а не вы. Давайте посмотрим:
>>> name = "test string"
>>> name.__len__()
11
>>> len(name)
11
>>> number = 10
>>> number.__add__(40)
50
>>> number + 50
60
Всегда есть оператор или нативная функция, которая вызывает эти магические методы. Иногда это просто вызовы с пинтовыми вызовами в определенных ситуациях. Например, __init__()
вызывается, когда объект создается после вызова __new__()
для сборки экземпляра ...
Давайте возьмем пример ...
class FalseCalculator(object):
def __init__(self, number):
self.number = number
def __add__(self, number):
return self.number - number
def __sub__(self, number):
return self.number + number
number = FalseCalculator(20)
print number + 10 # 10
print number - 20 # 40
Для подробнее Руководство по PEP-8 поможет больше.
Здесь вы найдете более магические методы в python. https://github.com/RafeKettler/magicmethods/blob/master/magicmethods.pdf
Отличные ответы до сих пор, но некоторые лакомые кусочки отсутствуют. Единственное главное подчеркивание - это не совсем только соглашение: если вы используете from foobar import *
, а модуль foobar
не определяет список __all__
, имена, импортированные из модуля, не включают те с лидирующим подчеркиванием. Предположим, что это в основном конвенция, поскольку этот случай является довольно неясным углом; -).
Соглашение с ведущим-подчеркиванием широко используется не только для private , но также и то, что C ++ вызывал protected - например, имена методов, которые полностью предназначены для переопределения подклассами (даже те, которые должны быть переопределены, поскольку в базовом классе они raise NotImplementedError
! -) часто являются именами одного и того же нижнего подчеркивания, указывающие на код с использованием экземпляров этого класса (или подклассов), в котором упомянутые методы не предназначены для прямого вызова.
Например, для создайте поточно-безопасную очередь с другой дисциплиной очередей, чем FIFO, один импортирует Queue, subclasses Queue.Queue и переопределяет такие методы, как _get
и _put
; «клиентский код» никогда не вызывает эти методы («крючок»), а скорее («организующие») общедоступные методы, такие как put
и get
(это известно как шаблон дизайна Template Method ] - см., например, здесь для интересной презентации, основанной на видеоролике моего разговора по этому вопросу, с добавлением кратковременных расшифровки стенограммы).
_var_name
или использовать var_name
+ исключая его из __all__
?
– endolith
30 January 2017 в 16:39
__all__
всякий раз, когда вы хотите сделать модуль from spam import *
дружественным (в том числе и интерактивным интерпретатором). Поэтому большую часть времени ответ как i>.
– abarnert
25 April 2018 в 17:15
«Частные» переменные экземпляра, к которым невозможно получить доступ, кроме как внутри объекта, не существует в Python. Тем не менее, существует соглашение, за которым следует большинство кода Python: имя с префиксом подчеркивания (например, _spam) должно рассматриваться как непубличная часть API (будь то функция, метод или элемент данных) , Он должен рассматриваться как деталь реализации и может быть изменен без предварительного уведомления.
ссылка https://docs.python.org/2/tutorial/classes.html#private-variables-and-class -локальных ссылка
Если вы действительно хотите сделать переменную только для чтения, IMHO лучшим способом было бы использовать свойство () с передачей только getter. С помощью свойства () мы можем иметь полный контроль над данными.
class PrivateVarC(object):
def get_x(self):
pass
def set_x(self, val):
pass
rwvar = property(get_p, set_p)
ronly = property(get_p)
Я понимаю, что ОП задал несколько другой вопрос, но так как я нашел другой вопрос, задающий вопрос о том, как отмечать отмеченные дубликаты частных переменных этот, я думал добавить эту дополнительную информацию здесь.
Вот простой иллюстративный пример того, как свойства двойного подчеркивания могут влиять на унаследованный класс. Итак, со следующей настройкой:
class parent(object):
__default = "parent"
def __init__(self, name=None):
self.default = name or self.__default
@property
def default(self):
return self.__default
@default.setter
def default(self, value):
self.__default = value
class child(parent):
__default = "child"
, если вы затем создадите дочерний экземпляр в REPL python, вы увидите ниже
child_a = child()
child_a.default # 'parent'
child_a._child__default # 'child'
child_a._parent__default # 'parent'
child_b = child("orphan")
## this will show
child_b.default # 'orphan'
child_a._child__default # 'child'
child_a._parent__default # 'orphan'
Это может быть очевидно для некоторых, но он поймал меня на страже в гораздо более сложной среде
__foo__
: это просто соглашение, способ использования системы Python для имен, которые не будут конфликтовать с именами пользователей.
_foo
: это просто соглашение, способ для программиста указать, что переменная является частной (что бы это ни значило в Python).
__foo
: это имеет реальное значение: интерпретатор заменяет это имя на _classname__foo
, чтобы гарантировать, что имя не будет перекрываться с похожим именем в другом классе.
В мире Python нет другой формы подчеркивания.
Нет никакой разницы между классом, переменной, глобальным и т. д. эти соглашения.
__foo
и любопытно. Как он может перекрываться с похожими именами методов с другими классами? Я имею в виду, что вы все равно должны получить к нему доступ, как instance.__foo()
(если он не был переименован интерпретатором), правильно?
– Bibhas Debnath
9 May 2013 в 09:03
from module import *
не импортирует объекты с префиксами с подчеркиванием. Поэтому _foo
- это не просто соглашение.
– dotancohen
13 June 2013 в 14:28
B
подклассы класса A
и оба реализуют foo()
, то B.foo()
переопределяет .foo()
, унаследованный от A
. Экземпляр B
будет иметь доступ только к B.foo()
, кроме как через super(B).foo()
.
– naught101
26 January 2015 в 04:11
Единичные подчеркивания - это соглашение. нет никакой разницы с точкой интерпретатора, если имена начинаются с одного подчеркивания или нет.
Двойные ведущие и завершающие символы подчеркивания используются для встроенных методов, таких как __init__
, __bool__
и т. д.
Двумя ведущими подчеркиваниями без конечных копий являются соглашение тоже, однако, методы класса будут искажены интерпретатором. Для переменных или имен базовых функций разница не существует.
Иногда у вас есть то, что кажется кортежем с ведущим подчеркиванием, как в
def foo(bar):
return _('my_' + bar)
. В этом случае происходит то, что _ () является псевдонимом для функции локализации, которая работает текст, чтобы перевести его на правильный язык и т. д. на основе языка. Например, Sphinx делает это, и вы найдете среди импорта
from sphinx.locale import l_, _
и в sphinx.locale, _ () назначается как псевдоним некоторой функции локализации.
Ваш вопрос хорош, речь идет не только о методах. Функции и объекты в модулях обычно имеют префикс с одним символом подчеркивания и могут быть префиксными двумя.
Но имена __double_underscore, например, не обрабатываются именами в модулях. Случается, что имена, начинающиеся с одного (или более) подчеркивания, не импортируются, если вы импортируете все из модуля (из импорта модуля *), а также имена, указанные в справке (модуль).
__
двойного подчеркивания как имени переменной? какa, __ = foo()
– Clayton 3 December 2015 в 07:24