>>> 1+2+3
6
>>> _
6
>>> _*3
18
>>> _
18
>>> 2 + _
20
>>> _
20
>>> a = _
>>> a
20
>>> _
20
#하나의 값만 무시
a,_,b = (1,2,3)
print(_) #2
print(a,b) #1 3
#여러 개의 값 무시
a,*_,b = (1,2,3,4,5)
print(_) #[2, 3, 4]
print(a,b) #1 5
for _ in range(5):
print(_) #0 1 2 3 4
x = 1_000_000_000
hex = 0xffff_ffff
print(x,hex) #1000000000 4294967295
class Person:
def __init__(self, name, _age):
self.name = name
self._age = _age #_single_leading_underscore
def _get_age(self): #_single_leading_underscore
return self._age
class Employee(Person): #Employee는 Person을 상속받고
def __init__(self, name, _age, salary):
super().__init__(name, _age)
self.salary = salary
def get_salary(self):
return self.salary
employee = Employee("me", 24, 100) #객체 생성
print(employee._age) # _single_leading_underscore를 사용한 변수에 접근
print(employee._get_age()) # _single_leading_underscore를 사용한 메서드에 접근
위 코드에서 객체를 생성하고 '_age'와 '_get_age()'메서드에 외부에서 직접 접근했다.
사용가능하긴 하지만 외부에서 접근할 수 없다는 네이밍 컨벤션을 어긴 것이므로 좋은 습관이 아니다.
두번째 예시를 보자.
#my_module.py
def _private_function():
return "This is a private function"
public_variable = "This is a public variable"
만약 from my_module import *이라고 한다면?
from my_module import *
print(public_variable) # "This is a public variable"
print(_private_function()) #not defiend
프라이빗 함수는 정의되지 않았다는 오류가 발생한다.
이 때 import * 에서는 single leading underscore를 사용한 변수나 함수를 가져오지 않는다.
from M import * does not import objects whose names start with an underscore.
PEP 8 문서 참고
그렇다면 모듈 자체를 임포트해보자.
import my_module
print(my_module.public_variable) # "This is a public variable"
print(my_module._private_function()) # "This is a private function"
함수를 직접적으로 import하지 않고 모듈 전체를 import하여
'my_module._private_function()' 형식으로 호출하여 _private_function() 함수를 호출하였다.
이 경우에는 사용이 가능하다.
def calculate_area(width, height):
return width * height
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return calculate_area(self.width, self.height)
# 키워드 'class'와 충돌을 피하기 위해 'class_'를 사용한 변수 선언
class_ = "Mathematics"
rectangle1 = Rectangle(4, 5)
print(f"Area of rectangle with width {rectangle1.width} and height {rectangle1.height}: {rectangle1.area()}")
print(f"Class: {class_}")
Area of rectangle with width 4 and height 5: 20
Class: Mathematics
_클래스명
을 추가함 MyBaseClass에서 __double_leading_underscore 속성은
_MyBaseClass__double_leading_underscore로 변경됨
class MyBaseClass:
def __init__(self):
self.public_var = "I'm a public variable"
self._single_leading_underscore = "I'm a 'protected' variable"
self.__double_leading_underscore = "I'm a 'private' variable with name mangling"
#_MyBaseClass__double_leading_underscore
def __private_method(self):
print("I'm a 'private' method with name mangling")
class DerivedClass(MyBaseClass):
def __init__(self):
super().__init__()
self.__double_leading_underscore = "I'm another 'private' variable with name mangling in the derived class"
#_DerivedClass__double_leading_underscore
def access_base_private_method(self):
self._MyBaseClass__private_method()
instance = MyBaseClass()
print(instance.public_var)
print(instance._single_leading_underscore)
# print(instance.__double_leading_underscore) # AttributeError
print(instance._MyBaseClass__double_leading_underscore) # Name mangling 접근
derived_instance = DerivedClass()
derived_instance.access_base_private_method()
print(derived_instance._MyBaseClass__double_leading_underscore)
print(derived_instance._DerivedClass__double_leading_underscore)
이 코드에서
__double_leading_underscore
__private_methode()
는 이름 맹글링을 적용하여 클래스 내부에서만 사용하도록 의도된 것을 나타낸다.
그러나 _MyBaseClass__double_leading_underscore 형식으로 접근하는 것이 가능하다.
또
class DerivedClass(MyBaseClass):
def __init__(self):
super().__init__()
self.__double_leading_underscore = "I'm another 'private' variable with name mangling in the derived class"
def access_base_private_method(self):
self._MyBaseClass__private_method()
DerivedClass에서는 조상 클래스의 private메서드를 접근한다.
그런데
MyBaseClass의 __double_leading_underscore
와 DerivedClass의 __double_leading_underscore
는 서로 다른 이름으로 저장되어 있. 따라서 각 클래스에서 정의된 속성이 서로 영향을 주지 않으며, 예기치 않은 속성의 오버라이딩을 방지할 수 있다.
__init__
, __import__
, __file__
class Circle:
def __init__(self, radius):
self.radius = radius
def __str__(self):
return f"Circle with radius {self.radius}"
def __eq__(self, other):
if isinstance(other, Circle):
return self.radius == other.radius
return False
def __add__(self, other):
if isinstance(other, Circle):
return Circle(self.radius + other.radius)
return NotImplemented
circle1 = Circle(5)
circle2 = Circle(5)
circle3 = Circle(7)
# __str__ 메서드를 사용하여 객체를 문자열로 표현
print(circle1) # 출력: Circle with radius 5
# __eq__ 메서드를 사용하여 두 객체의 동일성을 비교
print(circle1 == circle2) # 출력: True
print(circle1 == circle3) # 출력: False
# __add__ 메서드를 사용하여 두 객체를 더함
circle4 = circle1 + circle3
print(circle4) # 출력: Circle with radius 12
Circle with radius 5
True
False
Circle with radius 12
REFERNCE
Python DOCS
Geeksforgeeks
Pep8
Stackoverflow