Today I Learned
Fastcampus에서 진행한 졸업생과의 티타임 시간에 졸업한 개발자분을 만나뵙고 경험들을 들었다. 많은 도움이 됐다.
Network를 대략적으로 살펴봤다. 나는 학교에서 배웠지만 오래되어 다시 한 번 정리하는 게 필요할 것 같다.
Quick Sort의 성능 분석 및 정리해서 posting 했다.
Divide and Conquer Algorithm
Use Recursion
정렬해야할 list, 시작점 start와 끝점 end를 넘겨 받는다. left = start, right = end로 정한다.
양방향의 left와 right를 pivot 방향으로 움직이며 pivot 값과 left, right index의 element 값을 비교한다.
left의 element 값이 pivot 보다 크고, right의 element 값이 pivot보다 작을 때 둘을 교환하고 각 index를 하나씩 이동한다.(left면 +1, right면 -1)
left와 right가 교차되기 전까지 반복하면서 sorting한다.
한 번 교차되면 while문을 빠져나오는데, 이 때 pivot을 기준으로 왼쪽은 pivot보다 작은 값들로, 오른쪽은 pivot보다 큰 값들로만 이루어져있다.
Recursion으로 pivot을 포함하지 않고 왼쪽과 오른쪽을 각각 다시 돌려준다. 이 때 base case는 start가 end와 같아지거나 교차하면 return하는 것이다.
코드를 보는 게 더 이해가 쉬울 것 같다. 그림으로 그려보며 진행하는 게 가장 도움이 된다.
1 | def quickSort(li, start, end): |
1 | import random |
[Quick sort에 관련된 TED edu 영상] What’s the fastest way to alphabetize your bookshelf?
문제는 pivot을 어떻게 결정할 것이냐이다. Pivot이 정렬해야할 list의 모든 값들의 평균치일 때는 n/2번을 비교하는 것으로 가장 좋지만, 예를 들어 최솟값이나 최댓값을 기준으로 pivot이 선택될 경우 n번을 계산해야한다.
pivot을 정렬된 list의 가운데 값으로 결정하는 것이 Best case지만, 정렬을 하기 위해서 pivot을 사용하는 것이므로 실현될 수 없는 이야기이다.
Quick Sort의 Time Complexity는 O(nlogn)으로, average case일 때를 기준으로 한다. Pivot을 random pivot으로 둘 경우 확률적으로 avarage case를 만족한다.
li의 start와 end와 mid를 정렬한 결과의 중간 값을 return한다. Random Pivot을 이용하기 위해 코드를 수정했다.
1 | def getMiddleIndex(li, start, mid, end): |
1 |
|
1 | class Account: |
C++, Java와 같이 클래식한 object-oriented 언어에서는 public, private, protected와 같은 키워드로 class의 member에 대한 접근을 제어한다. Class의 Private member는 class 외부에서 접근이 불가능하며 class 내부에서만 접근될 수 있다.
Class 내의 Public member는 class 외부에서도 접근할 수 있다. 같은 class의 object는 public method를 호출하도록 요구된다. Private instance variable과 public method를 함께 써야지만 데이터 encapsulation의 원칙에 따르는 것이다.
Class의 protected member는 오직 해당 class와 그 class를 상속받은 child class만이 접근할 수 있다. 이는 parent class가 child class에게 특정한 리소스를 상속할 수 있게 한다.
그런데 Python은 instance variable과 method에 대해서 접근 제한을 하는 방식이 따로 없다. Python vaiable이나 method의 이름 앞에 한개 또는 2개의 _(underscore)를 붙여서 protected와 private으로 구분하기로 약속한다.
1 | class Account: |
1 | class Account: |
1 | class Account: |
그런데 웃긴 건, underscore로 name mangling한 private variable을 class 외부에서 접근이 가능하다는 것이다. 다음의 방법을 사용하면 된다.
1 | myAccount = Account('subin', 10000) |
정말 필요하다면 접근할 수 있지만, Python에서는 접근하지 말 것을 권고하고 있다.
참고 자료
Python Class 선언과 instance를 만드는 방법에 대해서 배웠다.
Object-Oriented Programming에 대해서 정리한 내용을 포스팅했다. ✨4 Fundamentals of OOP
Python Access Modifier에 대해서 알고 정리했다.
Network 계층 및 Eathernet과 IP Protocol에 대해서 배웠다.
Quick sort | Divide and Conquer - Python으로 Code를 짰다
추상화란, 복잡한 로직을 가지고 있는 기능에서 그것을 다루기 위해 필요한 최소한의 핵심만을 추출해내는 것을 말한다. 정의만 들으면 어렵다.
TV 전원을 예로 들어 생각해보자. 새로 산 TV의 설명서를 보면 TV를 켜려면 전원 버튼을 누르라고 되어있다. 사용자는 전원 버튼을 누르면 쉽게 TV를 켤 수 있다.
그러나 실제로 TV의 전원 버튼을 누르는 순간 내부 전기회로에서는 복잡한 기능이 실행될 것이다. 사용자는 그것을 알 수 없고, 알 필요도 없다. TV 제작 회사에서 TV에 대한 추상화를 시켜 사용자가 쉽게 TV를 동작시킬 수 있도록 한 것이다.
함수를 보통 function, routine, procedure 라고 부른다. 이 때, procedure 단위로 추상화를 하고 procdural하게 진행하는 프로그램을 절차 지향 프로그램이라고 한다. 그러나 프로그램이 거대해지고, 코드가 길어지자 프로그램을 객체(object)로 추상화하는 방법론이 나왔고 그걸 적용한 게 객체 지향 프로그램이다.
함수 호출 도중에 자기 자신을 다시 호출하는 것
Base case가 필수 (기초, 종료, 탈출 조건)
Base case가 없으면 무한으로 자기 자신을 호출해서 stack overflow가 된다.
Basis
0! = 1! = 1
Induction Step
n! = (n-1) * (n-2) * (n-3) * … 3 * 2 * 1
1 | def factorial(n): |
Basis
fib(0) = fib(1) = 1
Induction Step
fib(n) = fib(n-1) + fib(n-2)
1 | def fib(n): |
1 | f = [-1 for _ in range(100)] |
1 | f2 = [-1 for _ in range(100)] |
1 | def hanoi(n, _from, _by, _to): |
Memory | Performance of fbstring
Memory에 관련된 영상 하나를 보고 Memory 공부를 했다. Performance of fbstring
나는 전공 수업에서 OS를 들으며 배웠던 내용이라, 그 때 배웠던 것들을 처음부터 정리하며 복습 했다.
Process and Thread
어렵고 다룰 게 많은 주제인데 한 번에 후다닥 나가는 느낌이라 아쉬웠다. OS를 복습할 겸 Chapter 별로 정리해 포스팅할 계획을 세웠다.
Process와 Memory 개념 정리
Codewars 5kyu Sum of Pairs 문제를 풀었다. 자꾸 Timeout이 나서 성능을 좋게 만들려고 최대한 노력했다.
1 | const foo = function() { |
1 | function sayHello() { |
함수를 return 값으로 전달 (함수 return)
1 | function sayHello() { |
우선 Parameter와 Argument의 차이를 짚고 가도록 한다.
The names given in the function definition are called Parameters.
The values supplied in the function call are called Arguments.
함수를 호출할 때, 변수의 값을 복사하여 argument로 넘기는 것
1 | #include <stdio.h> |
함수를 호출할 때 변수의 값을 넘기는 것이 아니라, 변수의 주소(변수의 위치)를 복사하여 함수에 넘긴다.
넘겨받은 주소로 실제 변수에 접근하고 값을 변경할 수 있다.
1 | #include <stdio.h> |
주소값을 전달 (참조값을 전달) : 주소값을 알고 있으면 해당 memory 주소에 저장되어있는 값을 참조할 수 있다.
*x가 x를 참조하고 있다 : 가리키고 있다.
이를 이해하기 위해서는 pointer에 대한 이해가 필요하다.
Pointer
1 | int *pnum; |
The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, a new local symbol table is created for that call.
이 문장이 나를 얼마나 헷갈리게 했는지 모른다. 그러니까 Python에서는 function의 argument가 call by value로 넘어오는데, 그 value는 언제나 object의 값이 아닌 object의 reference라는 것이다.
Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list).
정확하게는 call by object reference라는 설명이 더 맞다. 왜냐면 mutable 객체가 넘어올 때에는 call by reference처럼 원본 값을 변경할 수 있기 때문이다.
Update your browser to view this website correctly. Update my browser now