[21/01/26 작성]
Module
직접 작성한 모듈 import 하기 (__init__.py 파일이 있을 때와 없을 때).
- __init__.py
- 파이썬 패키지를 읽을 때, 어떤 처리를 수행 혹은 패키지 내부의 모듈들을 한꺼번에 가져오고 싶을 때 사용.
- 패키지를 읽어 들일 때, __init__.py를 가장 먼저 실행함. 따라서 관련된 초기화 처리 등을 할 수 있음.
- __init__.py 에서는 __all__이라는 이름의 리스트를 직접 생성하는데, 이 리스트에 지정한 모듈들이 from <패키지> import * 를 할 때, 전부 읽어 들여짐.
- 파이썬 3.3 이전 버전에서는 __init__.py 파일이 무조건 있어야 패키지로 작동했지만 (PEP420), 이후 버전에는 없어도 폴더 내부에 파이썬 파일이 들어 있기만 하면 패티지로 작동함. 그러나 하위 버전 호환성을 위해 __init__.py 사용하는 것을 권장함.
1. __init__.py 파일이 없을 때

2. __init__.py는 있는데, __all__ 리스트를 선언하지 않았을 때

3. __init__.py 있고, __all__ 리스트를 선언하였을 때

import 를 하면 내부적으로 어떤 준비 과정을 거치는가?
크게 2가지 설명 방식이 있는데, 연관성을 아직 잘 모르겠어서 두 가지 모두 정리.
파이썬 import 구문은 다음의 세 단계를 거침.
가. 모듈 파일 찾기
나. byte 코드로 컴파일
다. 정의한 객체를 구축하기 위해 모듈 코드를 실행
가. 모듈 파일 찾기
python은 크게 세가지 구역에서 다음의 순서 로 module/package 들을 찾음.
sys.modules -> built-in modules -> sys.path
sys.modules
python이 module이나 package를 찾기 위해 우선적으로 살피는 영역으로 dictionary 형태로 되어 있음. python을 실행하고 한 번 이상 import가 되었다면, 다시 모듈을 찾지 않고, 곧바로 sys.modules를 확인하여 module이나 package를 사용함. 한 번 이상 사용되었거나 이미 내장 되어 있는 module이나 패키지만 존재하므로, 새롭게 import 되는 것들은 없다고 보면 됨.

built-in modules
파이썬에서 공식으로 제공하는 라이브러리. 설치하자마자 깔리는 것들이고, 쉽게 찾을 수 있음. sys.modules를 print() 하면 어떤 것이 built-in modules 인지 쉽게 확인할 수 있음.
sys.path
파이썬이 module이나 package를 찾을 때, 가장 마지막으로 확인하는 부분. pip로 새롭게 설치한 패키지도 이 곳을 통해 찾게 되며, 새롭게 작성한 패키지나 모듈을 사용하고자 할 때, 이 곳에 path를 등록해서 찾게끔 설정됨. 해당 변수는 list의 형태로 구성되어 있음.

만약 해당하는 모듈이 없다면, ModuleNotFoundError 발생.
나. byte 코드로 컴파일
module.py 파일을 바이트 코드 상태로 컴파일 함.
- 파이썬에서 컴파일: 소스 코드를 저수준의, 플랫폼 독립적인 코드로 변환하는 것.
- 이 과정을 거치고 나면, .pyc 파일이 생성됨.
- .pyc 파일은 파이썬 3.2 버전 이전에는 .py 파일과 같은 경로에 생성되고, 3.2 이후 버전에서는 __pycache__ 디렉토리 아래에 생성됨.
- .pyc 파일은 무조건 생성되는 것이 아니라, .py 파일이 다른 스크립트에 의해 import 되었을 경우에만 생성됨.
- 만약 소스코드가 변경되면, 자동으로 새 .pyc로 갱신.

다. 정의한 객체를 구축하기 위해 모듈 코드를 실행
모듈의 바이트 코드 실행.
- 파일에 있는 모든 명령들이 위에서 아래로 차례로 실행. 이 단계에서 이름에 행해진 모든 할당은 결과 모듈 객체의 속성을 생성함.
(다른 설명) 모듈 객체를 local namespace에 연결.
- local namespace에서 모듈 객체를 만들고, 이를 초기화함.
정보 은닉 (private, protected, public)
1. public
- 클래스의 외부에서 속성, 메소드에 접근 가능 (사용 가능)
- 파이썬에서의 모든 속성, 메소드는 기본적으로 public
2. _protected
- 해당 클래스와 그것의 하위 클래스에서만 접근 가능
- 파이썬에서는 해당 속성의 앞에 _ (single underscore)를 붙여서 해결
- 실제 runtime에서의 제약사항은 아니고, 실제 클래스를 사용하는 사용자에게 경고 형태로만 제공
- 단지 경고의 의미
3. __private
- 해당 클래스의 외부에서는 접근 불가능
- 파이썬에서는 해당 속성의 앞에 __ (double underscore)를 붙여서 private 속성으로 설정
- 해당 속성의 경우 클래스의 외부에서 접근할 경우 에러 발생
- 맹글링을 적용하고 싶은 변수/함수명 앞에 언더바(_) 2개를 붙여서 적용할 수 있음.
* name mangling (Name Decoration) *
프로그램에서 함수를 선언하거나 전역 변수 등을 선언 했을 때, 실제 생성되는 함수는 컴파일 단계에서 일정한 규칙을 가지고 변경됨. 이를 네임 맹글링 이라고 함.
C/C++ 에서의 name mangling
- 컴파일러는 각 코드 파일을 컴파일하면서, 함수 이름들을 변경함. 이는 각 파일마다 존재할 수 있는 동일한 함수명들을 링커 (Linker)가 구분하기 위함.
- 컴파일러는 함수에 대해서 함수의 이름, 파라미커, 콜링 컨벤션, 네임 스페이스 등을 사용하여 심볼 이름을 만들어 내는데, 이는 컴파일러마다 규칙이 다를 수 있음.
python 에서의 name mangling
- 파이썬이 함수/변수의 이름을 짓이겨서 다른 이름으로 바꿔버리는 것.
e.g.
class TestClass():
def __init__(self):
self.name = "곽두팔"
self.gender = "male"
self.__age = 32
man = TestClass()
print(man.name)
print(man.gender)
print(man.__age) # AttributeError 발생
클래스 내에 멤버변수 name, gender를 만들고 맹글링을 적용한 변수 __age를 선언함.
이후 man 변수에 인스턴스를 저장하고, 멤버 출력.
실행하면 name, gender는 잘 출력되지만, __age에서 AttributeError가 발생. => __age는 어떻게 접근할 수 있을까?
dir 함수로 까보면, 마지막에 gender, name이 보이고, 바로 첫 인덱스에 _TestClass__age 라는 이름이 보임.
요게 __age 임. 즉, 언어바 2개로 맹글링을 적용한 변수/함수는 _클래스명__변수/함수명 형태로 이름이 변경된다는 사실을 알 수 있음.
print(dir(man))
['_TestClass__age', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gender', 'name']
맹글링은 다음 2가지 상황에서 사용할 수 있음.
1. 클래스의 속성값을 외부에서 접근하기 힘들게 할 때 (private 화)
2. 하위 클래스가 상위 클래스의 속성을 오버라이딩 하는 것을 막을 때.
1. 클래스의 속성값을 외부에서 접근하기 힘들게 할 때
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 30
self.hobby = "인형놀이"
man = TestClass()
print(man.name, man.age, man.hobby)
# 출력 결과
왕춘삼 47 인형놀이
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 47
self.__hobby = "인형놀이"
man = TestClass()
print(man.name, man.age, man.__hobby)
# AttributeError: 'TestClass' object has no attribute '__hobby'
맹글링 적용시 속성의 이름이 변경되기 때문에 외부에서는 더 이상 해당 속성 이름으로 접근할 수 없게 됨.
어느 정도 private 의 성격을 띄게 된 것.
그러나, dir 함수를 써 보면 알 수 있지만, 이는 완벽한 private는 아님.
dir() 함수를 통해 '_TestClass__hobby'라는 요소를 확인할 수 있고, 저 요소가 바로 맹글링이 적용된 hobby 속성.
즉, 파이썬에서 맹글링을 적용한 속성은 _클래스명__속성명 의 형태로 이름이 바뀌는 것이고, 이는 외부의 접근을 조금 어렵게 할 뿐, 값을 완벽하게 보호해 주는 것은 아님!
2. 하위 클래스가 상위 클래스의 속성을 오버라이딩 하는 것을 막을 때
클래스가 확장되면서, 크기가 커지면 발생할 수 있는 문제인 속성 이름간의 충돌을 막고자 할 때, 특히 오버라이딩을 막고자 할 때, 맹글링을 적용시킬 수 있음.
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 30
self.hobby = "인형놀이"
class TestClass2(TestClass):
def __init__(self):
super().__init__()
self.name = "양팔두"
self.age = 23
self.hobby = "벽 보기"
man = TestClass2()
print(man.name, man.age, man.hobby)
#출력 결과
양팔두 23 벽 보기
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 30
self.__hobby = "인형놀이"
class TestClass2(TestClass):
def __init__(self):
super().__init__()
self.name = "양팔두"
self.age = 23
self.__hobby = "벽 보기"
man = TestClass2()
print(man.name, man.age, man.__hobby)
# AttributeError: 'TestClass2' object has no attribute '__hobby'
오버라이딩을 막고 싶은 속성에 맹글링을 적용시키면 AttributeError가 발생함.
이름이 바뀌었기 때문에 __hobby 속성을 애초에 가지고 있지 않은 것으로 취급.
* 오버라이드 (재정의): 부모에 정의되어 있는 함수를 자식에서 다시 정의하는 것
[혼공파] Chapter 8
프라이빗 변수와 게터/세터
private(비공개) & pulbic(공개)
private 멤버: 클래스 안에서만 접근가능한 멤버
public 멤버: 클래스 안과 밖에서 모두 접근가능한 멤버
- 메서드에서도 public, private 속성 적용이 가능함.
private을 사용할 때: __변수명
- 사실 정확하게 말하면, 파이썬에는 public과 private 이란 개념이 없지만, 이와 같이 변수의 이름을 가지고 그것과 비슷한 기능을 표현할 수 있음.


- cTest 객체에는 __test_var라는 변수가 없다고 함, 이와 같이 private 과 비슷한 효과를 볼 수 있음.
(책 내용) 파이썬은 클래스 내부의 변수를 외부에서 사용하는 것을 막고 싶을 때, 인스턴스 변수 이름을 __변수이름 형태로 선언(언더바 2개).
=> private 변수에 접근하고 싶을 때, getter & setter 사용.
getter & setter (데코레이터)
파이썬 클래스에서 메서드를 통하여 속성의 값을 가져오거나, 저장하는 경우가 있음. 이 때 값을 가져오는 메서드를 getter, 값을 저장하는 메서드를 setter라고 함.
CODE 1
def __init__(self):
self.__age = 0
def get_age(self): # getter
return self.__age
def set_age(self, value): # setter
self.__age = value
james = Person()
james.set_age(20)
print(james.get_age())
OUTPUT 1
20
CODE 2 (getter, setter)
class Person:
def __init__(self):
self.__age = 0
@property
def age(self): # getter
return self.__age
@age.setter
def age(self, value): # setter
self.__age = value
james = Person()
james.age = 20 # 인스턴스.속성 형식으로 접근하여 값 저장
print(james.age) # 인스턴스.속성 형식으로 값을 가져옴
OUTPUT 2
20
- getter와 setter 메서드의 이름은 모두 age. 또한 getter에는 @property가 붙어있고, setter에는 @age.setter가 붙어있음. 즉, 값을 가져오는 메서드에는 @property 데코레이터를 붙이고, 값을 저장하는 메서드에는 @메서드이름.setter 데코레이터를 붙임.
- @property와 @age.setter를 붙이면, james.age 처럼 메서드를 속성처럼 사용할 수 있음. 값을 저장할 때, 메서드에 바로 값을 할당하면 되고, 값을 가져올 때도 메서드에 바로 접근하면 됨.
클래스 상속 (상속클래스 & 서브 클래스)
< Chapter 08 에서 정리한 내용 >
상속 (inheritance) & super()
- 프로그래밍 언어는 기반이 되는 것은 부모 (parent)라고 부르고, 이를 기반으로 생성한 것을 자식 (child)라고 부름. 부모가 자식에게 자신의 기반을 물려주는 기능을 '상속'이라고 함.
- 클래스의 상속 기능을 사용하면, 부모 클래스에서 만들어둔 기능(메서드)과 속성(변수)을 물려받을 수 있음.

상속

기능을 물려주는 클래스: base class (기반 클래스), parent class (부모 클래스), superclass (슈퍼 클래스)
상속을 받아 새롭게 만드는 클래스: derived class (파생 클래스), child class (자식 클래스), subclass (서브 클래스)
[21/01/27 작성]
Python Interface
- In python, the interface concept is not explicitly available, like available in other languages e.g. JAVA
- In python, an interface is an abstract class which contains only abstract method but not a single concrete method.
- 파이썬에서 인터페이스란, 추상 메소드만 포함하고, 구체적인 메소드는 포함하지 않는 추상 클래스.
- www.youtube.com/watch?v=l51kEMJ4u2Q
추상 클래스 (Abstract Class)
파이썬에서 인터페이스란, 추상 클래스인가?
- 추상 클래스: 메서드의 목록만 가진 클래스. 상속 받는 클래스에서 메서드 구현을 강제하기 위해 사용됨.
추상 클래스를 만들려면,
- import 로 abc 모듈을 가져와야 함. (abc는 abstract base class의 약자)
- 클래스의 () (괄호) 안에 metaclass = ABCMeta를 지정
- 메서드를 만들 때 위에 @abstractmethod를 붙여서 추상 메서드로 지정함.
from abc import *
class 추상클래스이름(metaclass=ABCMeta):
@abstractmethod
def 메서드이름(self):
코드
- 만약 import abc로 모듈을 가져왔다면, abc.ABCMeta, @abc.abstractmethod로 사용해야 함.
e.g. 학생 추상 클래스 StudentBase를 만들고, 이 추상 클래스를 상속 받아 학생 클래스 Student를 만듦.

- 추상 클래스 StudentBase에서는 추상 메서드로 study와 go_to_school을 정의했는데, StudentBase를 상속받은 Student 클래스에서는 study 메소드만 구현하고, go_to_school 메서드는 구현하지 않았기 때문에 에러 발생.

- 모든 추상 메서드를 구현하니, 실행이 잘 됨.
- 추상 클래스는 파생 클래스가 반드시 구현해야 하는 메서드를 정해줄 수 있음.
- 참고로, 추상 클래스의 추상 메서드를 모두 구현했는지 확인하는 시점을 파생 클래스가 인스턴스를 만들 때. 따라서 james = Student() 에서 확인.
추상 클래스는 인스턴스로 만들 수 없음.
- 따라서 추상 메서드를 만들 때, 내부에 pass 만 넣어서 빈 메서드로 만듦. 왜냐하면 추상 클래스는 인스턴스를 만들 수 없으니, 추상 메서드도 호출할 일이 없기 때문.
추상 클래스는 인스턴스로 만들 때는 사용하지 않으며, 오로지 상속에만 사용.
또한 파생 클래스에서 반드시 구현해야 할 메서드를 정해 줄 때 사용함.
여기서 말하는 interface는 python interface와는 다른 것 같음.
Public and Internal Interface
- public interface: 문서화 된 모든 interface, 하위 호환성 보장이 적용됨.
- internal interface: 문서화되지 않은 모든 interface
Python Interpreter
기본적으로 우리가 말하는 파이썬은 C로 구현되어 있음. 이 구현체를 다른 구현체와 구분할 때, 이를 CPython이라고 함.
파이썬의 기본 인터프리터인 CPython은 파이썬을 중간 바이트코드로 컴파일하고, 이 바이트코드가 가상 머신에 의해 인터프리트 되는 방식.
이 외에도 C언어로 변환하고 컴파일하는 방법으로 구현한 Cython (CPython과는 다른 것), Java로 구현한 Jython, .NET Framework로 구현한 IronPython 등이 있음. Cython은 빠르지만, 나머지는 굉장히 느리다고 알려져 있음.
파이썬을 파이썬으로 구현한 PyPy 라는 구현체 존재. Pypy 는 다른 구현체에 비해 훨씬 빠름.
CPython
- C로 작성된 파이썬 구현의 레퍼런스. 파이썬 코드를 가상 머신에 의해 해석되는 중간 바이트 코드로 컴파일.
- 파이썬 패키지와 C 언어의 확장 모듈 간의 최고 레벨의 호환성 제공.
- C언어 확장 기능을 쓰는 패키지를 사용하려면 CPython이 유일한 구현 방법.
PyPy
- 파이썬 언어의 정적 타입으로만 구현된 파이썬 인터프리터. 통칭 RPython.
- 해당 인터프리터는 just-in-time 컴파일러와 복수의 백엔드 (C, CLI, JVM)를 지원한다는 것.
- PyPy의 목표는 파이썬의 리퍼런스 구현 방법인, CPython과 최대한의 호환성을 유지하는 동시에, 성능을 향상시키는 것.
- 벤치마크에서 PyPy는 CPython 보다 5배 빠름.
- PyPy는 파이썬 2.7 지원, PyPy3는 파이썬3 지원.
Jython
- 파이썬 코드를 자바 바이트코드로 만들어 JVM(자바 가상 머신)에서 실행시키는 파이썬 구현.
- 자바 클래스를 파이썬 모듈처럼 불러와서 사용할 수 있음.
- 자바 코드 베이스를 끌어다 쓸 필요가 있거나, 파이썬 코드를 JVM 에서 돌릴 필요가 있다면 유용.
- Jython은 파이썬 2.7까지 지원.
IronPython
- IronPython은 닷넷 프레임워크를 위한 파이썬 구현.
- 파이썬과 닷넷 프레임워크 라이브러리 둘 다 쓸 수 있고, 파이썬 코드를 닷넷 프레임워크 다른 언어로 바꿀 수 있음.
- Python Tools for Visual Studeio 는 IronPython을 직접 비쥬얼 스튜디오 개발 환경으로 통합할 수 있음.
- 이는 Windows 개발자들에게 좋음.
- 파이썬 2.7 지원.
PythonNet
- Python for .NET 은 순정 버젼의 파이썬 설치본과 닷넷 공통 언어 런타임 (CLR) 을 말끔하게 통합시켜주는 패키지.
- 이는 위의 IronPython이 취한 방식을 역으로 접근한 것, 보다 상호 보완적임.
- Mono와 함께 사용하면 pythonnet OS X와 리눅스처럼 비-Windows 운영체제에 설치된 순정 버젼의 파이썬을 닷넷 프레임 워크 안에서 수행될 수 있도록 해 줌. IronPython과 함께 사용해도 충돌되지 않음.
- 파이썬 2.3 버전부터 2.7 버전까지 지원.
[21/02/04 작성]
클래스 사용의 장, 단점
1. 객체지향언어의 장점
- 재사용성: 상속을 통해 프로그래밍 시 코드의 재사용을 높일 수 있음.
- 한 프로그램 내에서 하위 클래스들이 상위 클래스의 속성을 표현한 코드를 제사용하며, 새로운 프로그램 개발 시 기존 프로그램이 갖고 있는 클래스 상속 구조에서 많은 클래스들을 소프트웨어 IC로 재사용 가능.
- 생선성 향상: 잘 설계된 클래스를 만들어서 독립적인 객체를 사용함으로써 개발의 생산성을 향상시킬 수 있음.
- 자연적인 모델링: 우리 일상생활의 모습의 구조가 객체에 자연스럽게 녹아들어 있기 때문에(추상화), 생각하고 있는 것을 그대로 자연스럽게 구현할 수 있음.
- 유지보수의 우수성: 프로그램 수정 시, 추가, 수정을 하더라도 캡슐화를 통해 주변 영향이 적기 때문에 유지 보수가 쉬워서 경제적.
- 캡슐화(encapsulation): 데이터와 코드의 형태를 외부로부터 알 수 없게 하고, 데이터의 구조와 역할, 기능을 하나의 캡슐 형태로 만드는 방법. 즉, 데이터와 알고리즘을 하나로 묶는 것.
- 기존의 기능을 수정하거나, 새로운 기능을 추가하더라도 캡슐화와 그 함수의 세부 정보가 은폐되어 있어 주변에 미치는 영향을 최소화함.
2. 객체지향언어의 단점
- 개발 속도가 느림: 객체가 처리하려는 것에 대한 정확한 이해가 필요하기에 설계단계부터 많은 시간이 소모됨.
- 실행속도가 느림: 객체지향언어는 대체적으로 실행속도가 느림.
'Python Basic > 혼공파' 카테고리의 다른 글
[혼공파] Chapter 08 클래스 (0) | 2021.01.21 |
---|---|
[혼공파] Chapter 07 모듈 (0) | 2021.01.20 |
[혼공파] Chapter 06 예외 처리 (0) | 2021.01.13 |
[혼공파] Chapter 05 ③함수 고급 (0) | 2021.01.12 |
[혼공파] Chapter 05 ②함수의 활용 (0) | 2021.01.12 |