Wydaje się, że to „podkreślanie” zdarza się często i zastanawiałem się, czy to wymaganie w języku Python, czy tylko kwestia konwencji?
Ponadto, czy ktoś mógłby nazwać i wyjaśnić, które funkcje mają podkreślenia i dlaczego ( __init__
na przykład)?
Wydaje się, że to „podkreślanie” zdarza się często i zastanawiałem się, czy to wymaganie w języku Python, czy tylko kwestia konwencji?
Ponadto, czy ktoś mógłby nazwać i wyjaśnić, które funkcje mają podkreślenia i dlaczego ( __init__
na przykład)?
Odpowiedzi:
Z Python PEP 8 - Przewodnik po stylu dla kodu Python :
Opisowy: Style nazewnictwa
Rozpoznawane są następujące specjalne formularze wykorzystujące wiodące lub końcowe podkreślenia (można je ogólnie połączyć z dowolną konwencją przypadków):
_single_leading_underscore
: słaby wskaźnik „do użytku wewnętrznego”. Na przykładfrom M import *
Nie importuje obiektów, których nazwa zaczyna się znakiem podkreślenia.
single_trailing_underscore_
: używane zgodnie z konwencją w celu uniknięcia konfliktów ze słowem kluczowym Python, np
Tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore
: podczas nazywania atrybutu klasy wywołuje zniekształcenie nazwy (wewnątrz klasy FooBar__boo
staje się_FooBar__boo
; patrz poniżej).
__double_leading_and_trailing_underscore__
: „magiczne” obiekty lub atrybuty, które znajdują się w kontrolowanych przez użytkownika przestrzeniach nazw. Na przykład__init__
,__import__
albo__file__
. Nigdy nie wymyślaj takich nazw; używaj ich tylko zgodnie z dokumentacją.
Zauważ, że nazwy z podwójnymi wiodącymi i końcowymi podkreśleniami są zasadniczo zarezerwowane dla samego Pythona: „Nigdy nie wymyślaj takich nazw, używaj ich tylko zgodnie z dokumentacją”.
__double_leading_underscore
jest nadal publiczny , zmieniono nazwę zmiennej, aby uniknąć kolizji.
Inni respondenci słusznie opisują podwójne wiodące i końcowe znaki podkreślające jako konwencję nazewnictwa dla metod „specjalnych” lub „magicznych”.
Chociaż można wywoływać te metody bezpośrednio ( [10, 20].__len__()
na przykład), obecność znaków podkreślenia jest wskazówką, że metody te mają być wywoływane pośrednio ( len([10, 20])
na przykład). Większość operatorów Pythona ma powiązaną metodę „magiczną” (na przykład a[x]
jest to zwykły sposób wywoływania a.__getitem__(x)
).
Nazwy otoczone podwójnymi podkreśleniami są „specjalne” dla Pythona. Są one wymienione w Python Language Reference, sekcja 3, „Model danych” .
Właściwie używam nazw metod _, gdy muszę rozróżniać nazwy klas nadrzędnych i podrzędnych. Przeczytałem kilka kodów, które wykorzystały ten sposób tworzenia klas rodzic-dziecko. Jako przykład mogę podać ten kod:
class ThreadableMixin:
def start_worker(self):
threading.Thread(target=self.worker).start()
def worker(self):
try:
self._worker()
except tornado.web.HTTPError, e:
self.set_status(e.status_code)
except:
logging.error("_worker problem", exc_info=True)
self.set_status(500)
tornado.ioloop.IOLoop.instance().add_callback(self.async_callback(self.results))
...
i dziecko, które ma metodę _worker
class Handler(tornado.web.RequestHandler, ThreadableMixin):
def _worker(self):
self.res = self.render_string("template.html",
title = _("Title"),
data = self.application.db.query("select ... where object_id=%s", self.object_id)
)
...
Konwencja ta jest stosowana do specjalnych zmiennych lub metod (tak zwana „metoda magiczna”), takich jak __init__
i __len__
. Te metody zapewniają specjalne funkcje składniowe lub specjalne rzeczy.
Na przykład __file__
wskazuje lokalizację pliku Python, __eq__
jest wykonywany, gdya == b
wyrażenia.
Użytkownik może oczywiście stworzyć niestandardową metodę specjalną, co jest bardzo rzadkim przypadkiem, ale często może zmodyfikować niektóre wbudowane metody specjalne (np. Powinieneś zainicjować klasę, __init__
która zostanie wykonana na początku, gdy wystąpi klasa jest tworzone).
class A:
def __init__(self, a): # use special method '__init__' for initializing
self.a = a
def __custom__(self): # custom special method. you might almost do not use it
pass
Dodano przykład, aby zrozumieć użycie __ w pythonie. Oto lista wszystkich __
https://docs.python.org/3/genindex-all.html#_
Niektóre klasy identyfikatorów (oprócz słów kluczowych) mają specjalne znaczenie. Każde użycie * nazw w jakimkolwiek innym kontekście, które nie następuje po jawnie udokumentowanym użyciu, może zostać złamane bez ostrzeżenia
Ograniczenie dostępu za pomocą __
"""
Identifiers:
- Contain only (A-z, 0-9, and _ )
- Start with a lowercase letter or _.
- Single leading _ : private
- Double leading __ : strong private
- Start & End __ : Language defined Special Name of Object/ Method
- Class names start with an uppercase letter.
-
"""
class BankAccount(object):
def __init__(self, name, money, password):
self.name = name # Public
self._money = money # Private : Package Level
self.__password = password # Super Private
def earn_money(self, amount):
self._money += amount
print("Salary Received: ", amount, " Updated Balance is: ", self._money)
def withdraw_money(self, amount):
self._money -= amount
print("Money Withdraw: ", amount, " Updated Balance is: ", self._money)
def show_balance(self):
print(" Current Balance is: ", self._money)
account = BankAccount("Hitesh", 1000, "PWD") # Object Initalization
# Method Call
account.earn_money(100)
# Show Balance
print(account.show_balance())
print("PUBLIC ACCESS:", account.name) # Public Access
# account._money is accessible because it is only hidden by convention
print("PROTECTED ACCESS:", account._money) # Protected Access
# account.__password will throw error but account._BankAccount__password will not
# because __password is super private
print("PRIVATE ACCESS:", account._BankAccount__password)
# Method Call
account.withdraw_money(200)
# Show Balance
print(account.show_balance())
# account._money is accessible because it is only hidden by convention
print(account._money) # Protected Access