728x90
728x90
728x90
  • 문제
  • 해설
    • import sys
      
      earth, sun, moon = tuple([int(x) for x in sys.stdin.readline().split()])
      total = 15 * 28 * 19
      
      
      def mod(value, base):
          if value == 0:
              return base
          else:
              return value
      
      
      for i in range(1, total + 1, 1):
          if (earth, sun, moon) == (mod(i % 15, 15), mod(i % 28, 28), mod(i % 19, 19)):
              print(i)
              break
  • 포인트
    • 중국인의 나머지 정리를 통해, 해가 15 * 28 * 19 내에 유일하다는 점을 파악
    • BruteForce
    • 해를 찾을 때 까지만 반복
728x90

'Algorithm-Problems > 백준' 카테고리의 다른 글

[백준][1707] 이분 그래프  (0) 2022.02.09
[백준][1697] 숨바꼭질  (0) 2022.02.06
[백준][1260] DFS와 BFS  (0) 2022.02.06
[백준][1182] 부분수열의 합  (0) 2022.02.06
[백준][10971] 외판원순회2  (0) 2022.02.06
728x90

1260 DFS와BFS

  • 문제
  • 해설
    • import sys
      import queue
      
      sys.setrecursionlimit(99999)
      
      vertex_count, edge_count, start_vertex = [int(x) for x in sys.stdin.readline().strip().split()]
      edges = [list(map(int, x.strip().split())) for x in sys.stdin.readlines()]
      
      adj_dict = dict()
      chk_dict = dict()
      
      for edge in edges:
          vertex_1, vertex_2 = edge
          if vertex_1 not in adj_dict:
              adj_dict[vertex_1] = [vertex_2]
          else:
              adj_dict[vertex_1].append(vertex_2)
          if vertex_2 not in adj_dict:
              adj_dict[vertex_2] = [vertex_1]
          else:
              adj_dict[vertex_2].append(vertex_1)
      
      for vertex in adj_dict:
          chk_dict[vertex] = False
          adj_dict[vertex] = sorted(list(set(adj_dict[vertex])))
      
      sorted_vertex = sorted(list(chk_dict.keys()))
      chk_dict_bfs = chk_dict.copy()
      dfs_ans = []
      bfs_ans = []
      queue_for_bfs = queue.Queue()
      
      
      def dfs(vertex):
          chk_dict[vertex] = True
          dfs_ans.append(vertex)
          for k in adj_dict[vertex]:
              if not chk_dict[k]:
                  dfs(k)
      
      
      def bfs(vertex):
          chk_dict_bfs[vertex] = True
          bfs_ans.append(vertex)
          for k in adj_dict[vertex]:
              if not chk_dict_bfs[k]:
                  chk_dict_bfs[k] = True
                  queue_for_bfs.put(k)
          if queue_for_bfs.qsize():
              bfs(queue_for_bfs.get())
      
      
      if start_vertex in adj_dict.keys():
          dfs(start_vertex)
          bfs(start_vertex)
          print(' '.join([str(x) for x in dfs_ans]))
          print(' '.join([str(x) for x in bfs_ans]))
      else:
          print(start_vertex)
          print(start_vertex)
  • 포인트
    • BFS와 DFS를 구현
728x90

'Algorithm-Problems > 백준' 카테고리의 다른 글

[백준][1707] 이분 그래프  (0) 2022.02.09
[백준][1697] 숨바꼭질  (0) 2022.02.06
[백준][1476] 날짜 계산  (0) 2022.02.06
[백준][1182] 부분수열의 합  (0) 2022.02.06
[백준][10971] 외판원순회2  (0) 2022.02.06
728x90
  • 문제
  • 해설
    • import sys
      
      int_cnt, target_sum = [int(x) for x in sys.stdin.readline().split()]
      
      given_seq = [int(x) for x in sys.stdin.readline().split()]
      
      
      def go(seq, cur_sum, cur_ind, used_inds):
          res = 0
      
          # 정답
          if cur_sum == target_sum and cur_ind == len(seq) and used_inds:
              return 1
      
          # 불가능
          if cur_ind == len(seq):
              return 0
      
          if cur_ind < len(seq):
              # 현재 idx를 사용한 경우
              res += go(seq, cur_sum + seq[cur_ind], cur_ind + 1, used_inds + [cur_ind])
              # 현재 idx를 사용하지 않은 경우
              res += go(seq, cur_sum, cur_ind + 1, used_inds)
      
          return res
      
      
      print(go(given_seq, 0, 0, []))
  • 포인트
    • BruteForce임을 눈치챈다.
    • 첫 원소가 포함될 때 안될 때, 각 경우마다 두번째 원소가 포함될 떄 안될 때, ... 재귀 구현
728x90

'Algorithm-Problems > 백준' 카테고리의 다른 글

[백준][1707] 이분 그래프  (0) 2022.02.09
[백준][1697] 숨바꼭질  (0) 2022.02.06
[백준][1476] 날짜 계산  (0) 2022.02.06
[백준][1260] DFS와 BFS  (0) 2022.02.06
[백준][10971] 외판원순회2  (0) 2022.02.06
728x90
  • 문제
  • 해설
    • import sys
      
      N = int(sys.stdin.readline())
      matrix = [list(map(int, x.strip().split())) for x in sys.stdin.readlines()]
      base_idx = [x for x in range(N)]
      
      
      def next_permutation(list):
          last_asc_idx = 0
          for i in range(len(list) - 1):
              if list[i] < list[i + 1]:
                  last_asc_idx = i
      
          val_at_last_asc_idx = list[last_asc_idx]
          last_idx_larger_than_val_at_last_asc_idx = 0
          for j in range(last_asc_idx + 1, len(list), 1):
              if val_at_last_asc_idx < list[j]:
                  last_idx_larger_than_val_at_last_asc_idx = j
      
          if last_asc_idx == 0 and last_idx_larger_than_val_at_last_asc_idx == 0:
              return False
          else:
              list[last_asc_idx], list[last_idx_larger_than_val_at_last_asc_idx] = \
                  list[last_idx_larger_than_val_at_last_asc_idx], list[last_asc_idx]
              last_idx_larger_than_val_at_last_asc_idx = len(list) - 1
              while (last_asc_idx + 1 < last_idx_larger_than_val_at_last_asc_idx):
                  list[last_asc_idx + 1], list[last_idx_larger_than_val_at_last_asc_idx] = \
                      list[last_idx_larger_than_val_at_last_asc_idx], list[last_asc_idx + 1]
                  last_asc_idx += 1;
                  last_idx_larger_than_val_at_last_asc_idx -= 1
              return True
      
      
      def factorial(k):
          if k == 0 or k == 1:
              return 1
          else:
              res = k
              for i in range(1, k, 1):
                  res *= i
              return res
      
      
      total_available_count = factorial(N - 1)
      
      res = []
      for j in range(total_available_count):
          cost = 0
          out_inner_loop = False
      
          # 마지막 도시에서 처음 도시로 가지 못하는 경우 발견
          if matrix[base_idx[N - 1]][base_idx[0]] == 0:
              # 다음 이동 경로 체크
              next_permutation(base_idx)
              continue
          else:
              cost += matrix[base_idx[N - 1]][base_idx[0]]
      
          for i in range(N - 1):
              # 이동이 불가능한 도시의 경우
              if matrix[base_idx[i]][base_idx[i + 1]] == 0:
                  out_inner_loop = True
                  break
              else:
                  cost += matrix[base_idx[i]][base_idx[i + 1]]
          if out_inner_loop:
              # 다음 이동 경로 체크
              next_permutation(base_idx)
              continue
      
          # 가능한 경우가 처음 나왔을 때
          if len(res) == 0:
              res.append(cost)
      
          # 가능한 경우를 이전과 비교  
          else:
              if cost < res[0]:
                  res[0] = cost
      
          # 다음 이동 경로 체크
          next_permutation(base_idx)
      
      print(res[0])
  • 포인트
    • BruteForce임을 알아채야한다.
    • next permutation을 구현할 수 있어야한다.
728x90

'Algorithm-Problems > 백준' 카테고리의 다른 글

[백준][1707] 이분 그래프  (0) 2022.02.09
[백준][1697] 숨바꼭질  (0) 2022.02.06
[백준][1476] 날짜 계산  (0) 2022.02.06
[백준][1260] DFS와 BFS  (0) 2022.02.06
[백준][1182] 부분수열의 합  (0) 2022.02.06
728x90
  • git init
    • 로컬 working directory 내에 repository를 생성(.git)
  • git config
    • git config user.name $userName
      • 현재 유저의 현재 프로젝트 내에서 user name 설정
    • git config user.email $userEmail
      • 현재 유저의 현재 프로젝트 내에서 user email 설정
    • git config alias.$alias $command
      • 현재 유저의 현재 프로젝트 내에서 git command alias 설정
  • git add
    • git add $fileName
      • 파일을 staged로 만든다.
    • git add $directoryName
      • 디렉터리 내 전체(파일포함)를 staged로 만든다.
    • git add .
      • 현재 디렉터리 내 전체(파일포함)를 staged로 만든다.
  • git reset
    • git reset $fileName
      • 파일을 staged에서 unstaged로 돌려놓는다.
    • git reset --{soft, mixed, hard} $commitId
      • 현재 브랜치가 가리키는 커밋을 바꾼다.
        • soft는 커밋만
        • mixed는 커밋+staging area
        • hard는 커밋 + staging area + working directory
    • git reset --{soft, mixed, hard} {HEAD^, HEAD~N, HEAD@{N}}
      • HEAD^는 브랜치가 직전 commitId를 가리키게 한다.
      • HEAD~N은 브랜치가 N번째 이전 commitId를 가리키게 한다.
      • HEAD@{N}은 git reflog를 통해 나온 HEAD가 가리킨 commit 위치정보로, 그 때의 commitId로 브랜치가 가리키게 한다.
  • git status
    • 현재 깃이 추적하고 있는 파일들의 상태보기
  • git commit
    • 현재 작업 내역을 커밋 땀, 커밋 메시지 작성하는 게 editor로 열리고 작성, -m 옵션 안주고 사용함으로써 좀 더 긴 커밋메시지 작성에 유용함
    • git commit -m $commitMessage
      • staging area에 있는 내역으로 커밋메시지와 함께 커밋따기
    • git commit --amend
      • 현재 변경 내역을 직전 커밋에 update하기
  • git help
    • git help $gitCommand
      • git 커맨드 설명서 보기
  • git push
    • 로컬 저장소를 원격 저장소에 반영하기
    • git push $remoteRepositoryName $localBranchName:$remoteBranchName
      • 로컬 브랜치를 원격 저장소의 브랜치에 반영, 브랜치가 없으면 생성하며 반영?
    • git push -u $remoteRepositoryName $localBranchName
      • 로컬 브랜치를 원격 저장소에 반영, 원격 저장소에 해당 브랜치가 없으면 생성하며 반영
      • -u 옵션 으로 tracking connection이 되어, 이후 그냥 push만 해도 됨, 이는 브랜치 단위로 설정해줘야 함
  • git pull
    • 원격 저장소를 로컬 저장소에 반영하기
    • 단위는 브랜치 단위임
  • git clone
    • git clone $projectGitFileAddress
      • 원격 프로젝트를 로컬에 가져오기
  • git log
    • 커밋 히스토리 보기
    • git log --pretty=oneline
      • 커밋 히스토리를 예쁘게 보기(커밋아이디와 커밋메시지만 보여줌)
    • git log --pretty=oneline --all
      • 모든 브랜치의 커밋 히스토리를 보여줌
    • git log --pretty=oneline --all --graph
      • 모든 브랜치의 커밋 히스토리를 브랜치 단위로 나눠 보여줌
  • git show
    • git show $commitId
      • 커밋이 담고 있는 변경내역 확인하기
    • git show $tagName
      • 태그와 연결된 커밋을 찾아준다.
  • git diff
    • git diff $prevCommitId $laterCommitId
      • 두 커밋 비교하기
    • git diff $branchName1 $branchName2
      • 두 브랜치 비교하기
  • git tag
    • git tag $tagName $commitId
      • 커밋아이디에 태그부여하기
    • git tag -d $tagName
      • 태그 삭제하기
  • git branch
    • git branch $newBranchName
      • 새 브랜치를 만든다.
    • git branch -d $branchName
      • 브랜치를 삭제한다.
  • git checkout
    • git checkout $branchName
      • HEAD를 branchName으로 이동시킨다.
    • git checkout -b $newBranchName
      • 새 브랜치를 만들고, HEAD를 새 브랜치에 이동시킨다.
    • git checout $commitId
      • HEAD가 commitId를 가리키게 한다.(Detached HEAD)
        • 이는 특정 커밋으로부터 새 브랜치를 만들 때 주로 사용한다.
  • git merge
    • git merge $branchName
      • 현재 HEAD가 가리키는 브랜치에 branchName을 merge한다.
    • git merge --abort
      • merge하다가 conflict가 났는데, conflict를 잡아서 커밋하기보다는, merge 자체를 취소하고 싶을 때 사용한다.
  • git fetch
    • remote repository 내 브랜치의 이력만 가져옴(pull = fetch + merge)
  • git blame
    • git blame $fileName
      • 특정 파일을 각 라인마다 commitId, user, date가 나타난다.
  • git revert
    • git revert $commitId
      • 특정 커밋만 되돌리고 다시 커밋(revert commit)하기
    • git revert $commitId0..$commitIdN
      • commitId0 이후 부터 commitIdN까지 변경내역을 revert한 커밋을 역순으로 revert commit하기
  • git reflog
    • 이 때까지 HEAD가 가리켜온 commitId 내역을 최신부터 과거 순으로 나열함, git reset으로 과거로 갔다가 최신 commitId를 알고 싶을 때 사용
  • git rebase
    • git rebase $branchName
      • branchName의 브랜치를 base로 지정해서 두 브랜치를 합치는 방식
  • git stash
    • 최근 커밋 이후로 작업했던 내용을 stack 데이터 구조로 local repository에 저장하고, working directory는 최근 커밋 내용으로 변경(임시 저장하는 용도로 사용)
      • branchA에서 stash한 것을 branchB에서 적용 가능
    • git stash list
      • 임시 저장 리스트
    • git stash apply
      • 임시 저장된 것 중 가장 최신 저장 내역을 반영
      • git stash apply STASH@{N}
        • 특정 stash를 반영
    • git stash drop
      • 임시 저장된 것 중 가장 최신 저장 내역 삭제
      • git stash drop STASH@{N}
        • 특정 stash 삭제
    • git stash pop
      • 임시 저장된 것 중 가장 최신 저장 내역 apply and then drop
      • git stash pop STASH@{N}
        • 임시 저장된 것 중 특정 stash을 apply and then drop
  • git cherry-pick
    • git cherry-pick $commitId
      • 다른 브랜치의 특정 커밋을 현재 브랜치에 가져와서 merge
    • git cherry-pick $commitId1 $commitId2
      • 다른 브랜치의 특정 커밋(s)을 현재 브랜치에 가져와서 merge
    • git chrrey-pick $commitId1..$commitIdN
      • 다른 브랜치의 특정 커밋(s)을 현재 브랜치에 가져와서 merge
728x90
728x90

HelloCodeit

  • 테스트 디렉터리 작성
    • index.html
      <!DOCTYPE html>
      <html lang="ko">
      <head>
          <meta charset="UTF-8">
          <title>Codeit Javascript</title>
      </head>
      <body>
          <script src='./index.js'></script>
      </body>
      </html>​
    • index.js
      console.log('Hello Codeit!')
  • chrome으로 index.html을 열고 개발자 도구에서 console에서 “Hello Codeit!”을 확인 가능
  • 세미콜론
    • JS에서는 한줄에 하나의 명령이면 자동으로 ;을 붙인다.
    • 한줄에 여러 명령이면 ;으로 명령 구분이 필요하다.
    • 세미콜론으로 명령을 구분해주는 게 좋다.
  • 주석 처리(comment)
    • 한줄 주석 //
    • 블럭 주석 /* */

자료형

  • number
    • 사칙연산
      // 나머지
      console.log(7 % 3);
      
      // 몫
      console.log(Math.trunc(4/3))
      
      // 거듭제곱이 곱셈보다 우선순위가 높음
      console.log((3 + 27) * 12 ** (5 % 3)); // 30 * 12 ** 2 = 30 * 144 = 4320
  • string
    • ‘’, “”,`` 모두 가능
    • +로 concatenate 가능
    • escaping은 \으로 가능
    • backtick(`)으로 감싸서 내부 특수문자(”, ‘)을 사용하는게 가독성이 더 좋음
    • +연산에서 피연산자가 하나라도 문자열이면 나머지 모두 문자열로 바꿈(auto cast)
  • boolean
    • 값이 같은 지는 ==, 다른 지는 !=
      • ===, !== 은 값과 자료형 모두 비교함
    • true, false를 사용
    • and 연산은 &&
    • or 연산은 ||
    • not 연산은 !
  • function
  • typeof 연산자(function이 아니라 연산자임)
    • 뒤에 오는 변수의 type명을 string으로 반환함
      let t = true;
      let f1 = '';
      let f2 = 0;
      let nan = NaN; // NaN도 type은 number임
      console.log(typeof (8 - 3)); // number
      console.log(Number(t)); // true를 Number로 변환하면 1이 나옴
      console.log(Boolean(f1)); // false, empty string은 false
      console.log(Boolean(f2)); // false, zero number은 false
      console.log(Boolean(nan)); // false, NaN은 false
  • 형 변환(Type conversion)
    • String, Number Boolean 쓰면 됨
      console.log(Number('10') + Number('5')); // 15​
    • 자동 형변환
      // 요약하면, 연산은 모두 숫자로 자동 형변환하여 계산한다.
      // 다만, +은 둘 중 하나라도 문자열이 있으면 문자열로 형변환하여 계산한다.
      console.log(4 + '2'); // 42, 문자열 연결이 숫자 더하기 보다 더 우선순위 있다.
      console.log('4' * 1); // 4
      console.log(4 + 2);
      console.log(4 - true);
      console.log(4 * false);
      console.log(4 / '2');
      console.log('4' ** true);
      console.log(4 % 'two'); // NaN, NaN은 어떤 값과 연산해도 NaN
      
      console.log(2 < '3'); // 2 < 3, true
      console.log(2 > true); // 2 > 1, true
      console.log('2' <= false); // 2 <= 0, false
      console.log('two' >= 1); // false, NaN이 떠서 비교불가능하면 false를 반환
      
      console.log(1 === '1'); // false, type이 달라서 false
      console.log(1 == '1'); // true, 숫자로 형변환하고 값비교
      console.log(1 === true); // false, type이 달라서 false
      console.log(1 == true); // true, 숫자로 형변환하고 값비교​
    • +을 사용해서 String→Number 형변환 가능
      let a = +'10'; console.log(typeof a); console.log(a);​

추상화

  • 뽑을 추, 코끼리 상
    • 여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용을 추상이라 한다.
  • 개발에서는 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것
  • 방향
    • 목적을 명확히
    • 불필요한 것들은 숨기기
    • 핵심만 드러내기

변수선언

let espressoPrice; // create a variable
espressoPrice = 3000; // assignment

let espressoPrice = 3000;
  • 반드시 지켜야하는 작명 가이드
    • [a-zA-Z], _, $로 시작해야한다. 두번 째 글자부터는 숫자도 가능
    • 대소문자가 구분됨
    • reserved keyword는 사용 불가
  • 지키면 좋은 작명 가이드
    • 의미 없는 변수명을 쓰지 않는다.
      • e.g. let a, b, c, d;
    • 너무 추상적인 이름을 쓰지 않는다.
      • e.g. let name;
      • 다양한 이름이 존재하기 때문
    • 모든 변수는 camelCase로 작성한다.

함수선언

  • function keyword를 사용한다
    function funcName(param1, param2) { cmd1; cmd2; };
    
    // 보통은  { 이후 줄바꿈 함
    function funcName(param1, param2) {
    	cmd1;
    	cmd2;
    };
    
    // 함수호출
    funcName()
    
    // 문자열이 존재하면 모두 문자열을 auto cast
    function teraToGiga(x) {
      console.log(x + 'TB는')
      console.log(x * 1024 + 'GB 입니다.')
    };​

템플릿 문자열

let year = 2018;
let month = 3;
let day = 11;

function getTwice(number) {
	return 2 * number
}

// backtick으로 str을 나타내고, ${variable}로 template string 가능
console.log(`생년월일은 ${year}년 ${month}월 ${day}일 입니다.`);
console.log(`${myNumber}의 두 배는 ${getTwice(myNumber)}입니다.`);

null과 undefined

  • 둘 다 값이 없는 거지만...
  • null
    • 의도적으로 값이 없다는 것을 표현하는 값
  • undefined
    • 선언했지만 값이 없다는 것을 가리킴
    • undefined가 떠도 동작에 문제는 없음, 하지만 의도적으로 값을 할당하지 않은 것이라면 null을 썼어야 가독성이 좋음
    • return문이 없는 함수의 결과는 undefined
    • optional parameter를 갖는 function의 그 optional parameter에 아무값도 넣어주지않으면 해당 parameter는 function 내에서 undefined
  • null, undefined를 써도 되지만, 아직 값을 주진 않았지만 자료형이 명확하다면
    • 0, ‘’ 등의 값을 초깃값으로 써주는 게 좋다.
  • 비교하면
    console.log(null == undefined); // true
    console.log(null === undefined); // false
    console.log(undefined === undefined); // true
    console.log(null === null);  // true​

Default value를 갖는 parameter

// default value를 갖는 parameter는 뒤에 위치하게 작성한다.
function introduce(name, age, nationality = '한국') {
	console.log(`제 이름은 ${name}입니다.`)
	console.log(`나이는 ${age}살 입니다.`)
	console.log(`국적은 ${nationality}입니다.`)
}

변수의 scope

// Scope: 범위, 영역
let y = 4;

function myFunction() {  // 블록문 (block statement)
    let x = 3;  // 블록문 내에 선언한 변수를 지역 변수(Local variable)이라 한다.
    console.log(x);  // 로컬 변수는 블록문 안에서만 유효하다.
    console.log(y);  // 글로벌 변수는 블록문 밖에서 정의했어도 블록문 안에서 사용 가능
}

myFunction();
console.log(x);  // ReferenceError: x is not defined
console.log(y);  // 실행안됨, 위의 error로
// Scope: 범위, 영역
let x = 5;

function myFunction() {  // 블록문 (block statement)
    let x = 3;  // 블록문 내에 선언한 변수를 지역 변수(Local variable)이라 한다.
    console.log(x);  // 블록문안에서 변수의 값을 찾는 것은 로컬 변수부터 찾아서 3을 출력
}

myFunction();
console.log(x);  // 글로벌 변수 x를 출력, 5

상수

  • const 라는 키워드로 변수를 선언하면 된다.
    • 선언과 동시에 값을 할당해주어야 한다.
    • 이후 할당문으로 다시 할당하면 error가 발생한다.
    • 대문자와 _으로 작명하는게 관례
      • 예시
        • MY_NUMBER
        • PI
  • 다음은 오류를 발생시킴
    const X = 1500;
    
    function myFunction() {
      X = 1500 * 1.5;  // 글로벌 변수 X에 재할당하는 부분이라 error 발생
      console.log(X);
    }
    
    myFunction();
    console.log(X);​

if statement

/*
if (조건1) {
	동작1
} else if (조건2) {
	동작2
} else { 
  동작3
}
*/

let temperature = 0;
if (temperature <= 0) {
	console.log('물이 업니다.')
}

switch statement

/*
switch (비교할_값) {
	case 조건값_1:  // ===로 비교함, 즉 값과 type 둘 다 같아야 함
		동작부분1;
		break;
	case 조건값_2:
		동작부분2;
		break;
	default:  // 생략가능
		동작부분3;
}
*/

for loop statement

/*
for (초기화부분; 조건부분; 추가동작부분) {
	동작부분
}
*/

// 초기화부분은 loop 시작시 한 번 실행, 생략가능하지만 세미콜론은 생략 불가
// 조건부분이 true이면 동작부분을 시행
// 동작부분 이후 추가동작부분이 시행됨, 생략가능하고 이부분은 동작부분에서 해결해도됨
// 초기화부분에서 생성한 변수는 for statement의 로컬 변수

// 예시
for (let i=1; i <= 10; i++) {
	console.log('코드잇 최고!')
}

console.log(i)  // ReferenceError: i is not defined.
// 만약 i를 for loop 이전에 let i = 3; 이 있으면 여기서 3을 출력함
// 코드잇 최고!을 10번 출력하는 것에는 변함없음

while statement

/*
while (조건부분) {
	동작부분
}
*/

// 초기화부분이 따로 없기 떄문에 while문 이전에 global 초기화변수 필요
// 추가동작부분이 따로 없이 때문에 동작부분에서 보통 해결
// for문은 초기화부분에서 사용한 변수가 로컬변수다 보니까 statement가 끝나면 사용 안함
// while문은 global변수를 사용해서 statement가 끝나고도 사용

break와 continue

// break는 switch, for, while statement를 탈출
// continue는 이하 명령을 실행하지 않고 다음 단계로 이동

객체(object)와 속성(property)

// object의 생성
{
	brandName: '코드잇',
	bornYear: 2017,
	isVeryNice: true,
	worstCourse: null
}
// 각 key와 value가 존재하고 (key, value) 쌍을 property라 한다.
// key를 property name, value를 property value라 한다.

// property name은 string 타입이다. '을 생략해도 JavaScript가 알아서 문자열로 사용
// property name작성 시 '을 사용하지 않는다면 주의사항
	// 첫 글자는 반드시 문자, 밑줄(_), $중 하나로 시작
	// 띄어쓰기 사용 금지
	// 하이픈(-) 금지
// '을 사용한다면 위의 문제 없이 사용 가능

// property value는 모든 자료형이 가능, 심지어 object도 가능

// object를 typeof 연산자의 결과를 보면 object가 나온다.

객체 데이터 접근하기

// 점 표기법
// objectName.propertyName
console.log(objectSample.bornYear);
// '를 생략한 propertyName에 접근이 안되는 단점을 갖는다.

// 대괄호 표기법
// objectName['propertyName']
let propertyName = 'born' + ' Year';
console.log(objectSample[propertyName]);
// 장점은 propertyName을 가리키는 변수를 사용할 수 있고, 유연한 propertyName 사용가능

// object안의 object 접근은 위의 두 가지를 반복
console.log(codeit.bestCourse.title);
console.log(codeit['bestCourse']['title']);
console.log(codeit.bestCourse['title']);

// propertyName이 없는 경우에 접근하면
// undefined값을 반환한다. not error raised

객체 다루기

// codeit이 object라 했을 때

// property value 변경 혹은 property 추가
codeit.name = 'codeit';

// property 삭제
delete codeit.worstCourse;

// property name으로 property 존재 확인
'propertyName' in codeit;

// 없는 property name으로 조회 시 undefined가 나오는 걸 통해 
// property name으로 object안에 존재하는 지 확인하려고 할 때
// 실제로 property name이 object에 없었을 경우 
codeit.propertyName in codeit;  // false
codeit.propertyName !== undefined;  // false
// property name으로 object에 존재하지만
// property value가 undefined였다면(이러면 안되지만)
codeit.propertyName in codeit;  // true
codeit.propertyName !== undefined;  // false

// 따라서, property name의 object 내 존재 확인은 'in'을 권장한다.

메소드(method)

/*
property value에는 function도 들어갈 수 있다.
이러한 function을 method라 한다.
*/

let greetings = {
	sayHello: function(name) {
		console.log(`Hello ${name}!`);
	},
	sayHi: function() {
		console.log('Hi!');
	}
}

let name = 'codeit';
greetings.sayHello(name);
greetings['sayHello'](name);
// 사실 console.log()도 console이라는 object에 존재하는 method를 실행한 셈

/*
왜 function을 그냥 쓰면 되지 왜 메소드를 사용하는 것인가?
어떤 object냐에 따라 함수 이름이 중복됐으나 다른 기능을 적용할 수 있기 때문
좀 더 object에 집중해서 함수 동작을 정의할 수 있다.
*/
let rectAngle = {
	width: 30,
	height: 50,
	getArea: function () {
		return rectAngle.width * rectAngle.height
	}
}

let triAngle = {
	width: 15,
	height: 40,
	getArea: function() {
		return triAngle.width * triAngle.height / 2;
	}
}

for...in 반복문

/*
object의 property에 대해 for문

for (변수 in 객체) {
	동작부분
}

변수는 property name이 온다.
*/

let codeit = {
	name: '코드잇',
	bornYear: 2017,
	isVeryNice: true,
	worstCourse: null,
	bestCourse: '자바스크립트 프로그래밍 기초'
}

for (let k in codeit) {
	console.log(k);
	console.log(codeit[k]);
}

/*
주의사항
-property name을 숫자를 사용하면 object 생성 후에는 어쨌든 문자열로 형변환되어 사용됨
	-따라서 property를 가져와 사용할 때는 문자열로 가져와야한다.
-for..in을 쓸 때, property가 나올 순서에 대해
	-정수형 property name을 사용했다면, 해당 정수형부터 오름차순해서 나온다.
	-이외 나머지 자료형에 대해서는 기입한 순서대로 나온다.
*/

Date객체

/*
console객체처럼 JavaScript의 내장 객체(Standard built-in objects)가 존재
그 중 Date 객체에 대해 알아보자.
*/

// Date객체 생성
let myDate = new Date();
console.log(myDate);  // 객체가 생성된 datetime이 출력됨

// Date객체 생성 with UTC plus 1000 milliseconds
let myDate1 = new Date(1000);  // 1970년 1월 1일 00:00:00 UTC + 1초
console.log(myDate1)

// Date객체 생성 YYYY-MM-DD
let myDate2 = new Date('2017-01-01');
console.log(myDate2)

// Date객체 생성 YYYY-MM-DDThh:mm:ss
let myDate3 = new Date('2017-01-01T23:59:59')
console.log(myDate3)

// Date객체 생성 with multiple arguments, YYYY, MM, DD, hh, mm, ss, ms
// MM(month)는 시작이 0부터임
// required : YYYY, MM
// 나머지 생략하면 DD는 1, 그 외는 0으로 입력됨
let myDate4 = new Date(2017, 0, 1, 23, 59, 59);
console.log(myDate4);

// Date객체로부터 time stamp 가져오기(1970-01-01T00:00:00 UTC부터 흐른 milliseconds)
console.log(myDate4.getTime());

// Date객체로부터 여러 정보 가져오기
// 주의할 점은 Day는 요일을 가리키며, 0부터 시작함
console.log(myDate4.getFullYear());  // 2017
console.log(myDate4.getMonth());  // 0
console.log(myDate4.getDate());  // 1
console.log(myDate4.getDay());  // 0, 즉 일요일
console.log(myDate4.getHours());  // 23
console.log(myDate4.getMinutes());  // 59
console.log(myDate4.getSeconds());  // 59
console.log(myDate4.getMilliseconds());  // 0

// Date객체 수정하기
let myDate = new Date(2017, 4, 18, 19, 11, 16);
myDate.setFullYear(year, [month], [date])
myDate.setMonth(month, [date])
myDate.setDate(date);
myDate.setHours(hour, [min], [sec], [ms]);
myDate.setMinutes(min, [sec], [ms]);
myDate.setSeconds(sec, [ms]);
myDate.setMilliseconds(ms);
myDate.setTime(milliseconds);  // 1970년 1월 1일 00:00:00 UTC 기준 2 milliseconds 지난 datetime

// Date객체로부터 Locale에 맞는 date/time 가져오기
myDate.toLocaleDateString();  // 사용자 브라우저 locale에 맞는 date를 가져옴
myDate.toLocaleTimeString();  // 사용자 브라우저 locale에 맞는 time를 가져옴
myDate.toLocaleString();  // 사용자 브라우저 locale에 맞는 datetime을 가져옴

// 똑똑한 Date객체, 범위를 벗어나는 값을 설정하면 날짜 수정
let myDate = new Date(1988, 0, 32);  // 1988년 1월 32일은 없음, 1988년 2월 1일로 설정됨

// 호출한 순간의 datetime이 필요하다면 Date.now() 사용
Date.now();  // 호출한 시점의 datetime이 나옴

// Date객체의 형변환
let myDate = new Date(2017, 4, 18);
console.log(typeof myDate);  // object
console.log(String(myDate)); // Thu May 18 2017 00:00:00 GMT+0900 (Korean Standard Time)
console.log(Number(myDate)); // 1495033200000
console.log(myDate.getTime() === Number(myDate));  true
console.log(Boolean(myDate)); // true

// Date객체끼리의 사칙연산
let myDate1 = new Date(2017, 4, 18);
let myDate2 = new Date(2017, 4, 19);

let timeDiff = myDate2 - myDate1;
console.log(timeDiff); // 86400000 (ms)
console.log(timeDiff / 1000); // 86400 (sec)
console.log(timeDiff / 1000 / 60) // 1440 (min)
console.log(timeDiff / 1000 / 60 / 60) // 24 (hour)
console.log(timeDiff / 1000 / 60 / 60 / 24) // 1 (date)

배열

// 배열의 생성
let courseRanking = [
	'자바스크립트 프로그래밍 기초',
	'Git으로 배우는 버전 관리',
	'컴퓨터 개론'
]

// 배열의 element에는 자료형 제한이 없다.

// index로 가져오기(indexing)
// 0부터 시작
console.log(courseRanking[0]); // 자바스크립트 프로그래밍 기초

// 순서가 있는 경우 배열 사용

// for..in 문 사용 시, 변수는 배열의 index를 가리킨다.
let dataType = ['number', 'string', 'boolean', 'null', 'undefined', 'object'];

for (let idx in dataType) {  // idx는 0, 1, 2, ..., 5
  console.log(dataType[idx]);
}

// 배열도 object type
console.log(typeof dataType);  // object

배열의 원소 추가 및 수정

let dataType = ['number', 'string', 'boolean', 'null', 'undefined', 'object'];

// 배열에 element 추가 혹은 수정
dataType[0] = 'numeric';  // 수정
dataType[6] = 'etc';  // 추가
dataType[10] = 'temp';  // 이 경우 index 7, 8, 9에는 undefined가 들어감

console.log(dataType);
/*
[
  'numeric',
  'string',
  'boolean',
  'null',
  'undefined',
  'object',
  'etc',
  <3 empty items>,
  'temp'
]
*/

배열의 메소드-length

let dataType = ['number', 'string', 'boolean', 'null', 'undefined', 'object'];

console.log(dataType.length);  // 6
console.log(dataType['length']);  // 6
console.log(dataType[dataType.length - 1]);  // last element, 'object'

배열의 메소드-splice

// delete를 이용한 element 삭제
// 이 경우 element value 자체는 없어지지만, 배열에 해당 index 위치에 undefined가 남음
delete dataType[10];  

// splice를 이용한 element 삭제
dataType.splice($startIndex, $deleteCount);
// index=1부터 1개만 삭제하려면
dataType.splice(1, 1);
// index=1부터 이후 전체를 삭제하려면
dataType.splice(1);
// index=1부터 1개를 삭제하고 그 자리에 n개의 element를 추가하기
dataType.splice(1, 1, 'added1', 'added2');
// index=1자리에 삭제는 하지말고 element 추가하기
dataType.splice(1, 0, 'added3');
// index=2자리에 원소를 바꾸기(삭제하고 추가하는)
dataType.splice(2, 1, 'added4');

배열의 메소드-shift, pop, unshift, push

let memebers = ['쿤갈레', 'Zerrad66', '우리생각해써', '흙토끼', 'End Miracle'];
console.log(memebers);

// 배열의 첫 요소 삭제
members.shift();
console.log(members);

// 배열의 마지막 요소 삭제
members.pop();
console.log(members);

// 배열의 첫 요소로 값 추가
members.unshift('NiceCodeit');
console.log(members);

// 배열의 마지막 요소로 값 추가
members.push('HiCodeit');
console.log(members);

/*
배열의 양 끝부분을 다루는 경우는 splice보다 위의 메소드를 사용하는게 간결하게 가능
*/

배열에서 value로 index찾기-indexOf, lastIndexOf

let brands = ['Google', 'Kakao', 'Naver', 'Kakao'];

/*
indexOf
- 배열에 value가 존재하면 first index를 반환
- 배열에 value가 없으면 -1을 반환
lastIndexOf
- 배열이 value가 존재하면 last index를 반환
- 배열에 value가 없으면 -1을 반환
*/

console.log(brands.indexOf('Kakao'));  // 1
console.log(brands.indexOf('Daum'));  // -1

console.log(brands.lastIndexOf('Kakao'));  // 3
console.log(brands.lastIndexOf('Daum'));  // -1

배열에 value의 존재성-inclues

let brands = ['Google', 'Kakao', 'Naver', 'Kakao'];
console.log(brands.includes('Kakao'));  // true
console.log(brands.includes('Daum'));  // false

배열 뒤집기-reverse

let brands = ['Google', 'Kakao', 'Naver', 'Kakao'];
console.log(brands);  // **["Google", "Kakao", "Naver", "Kakao"]**
brands.reverse();
console.log(brands);  // ["Kakao", "Naver", "Kakao", "Google"]

배열의 메소드 레퍼런스

Array - JavaScript | MDN (mozilla.org)

배열의 value로 loop 돌기 - for..of

/*
for (변수 of 배열) {  // 변수는 배열의 value가 나옴
	동작부분
}
*/
let influencer = ['a', 'b', 'c', 'd'];

for (let element of influencer) {
	console.log(element);
}

// for..in문은 배열에 작성하지 않는 것을 권장
// 이는 동작부분에서 배열의 property를 수정할 가능성이 존재하기 때문
// for..in은 객체에 사용할 것을 권장
// for..of를 배열에 사용하기

다차원 배열

let twoDimensional = [[1, 2], [3, 4, 5], ['a']];  // 꼭 element의 길이가 같을 필요 없음

console.log(twoDimensional[0][1]);

다양한 숫자표기법

// 지수표기법
console.log(25e5 === 2500000);
console.log(-6.1e3 === -6100);
console.log(16e-3 === 0.016);
console.log(-9.1e-3 === -0.0091);

// 16진법
let hex1 = 0xff;  //  16진법(Hexademical의 x를 따와서 쓴 것)
let hex2 = 0xFF;  // 대소문사 구분 없음

// 8진법
let octal = 0o377;

// 2진법
let binary = 0b11111111;

console.log(hex1);  // 255
console.log(hex2);  // 255
console.log(octal);  // 255
console.log(binary);  // 255

숫자 메소드

// JavaScript에서 숫자도 객체

// toFixed
// 출력값은 string임, 따라서 숫자로 사용하려면 Number로 casting해줘야함
// toFixed(0~100), 입력한 자리수 까지 보여줌, 그 이하는 반올림
let myNumber = 1.3591;
console.log(myNumber.toFixed(3));  // 1.359
// 입력한 자리수가 실제 숫자의 자리수보다 크면, 초과분에 0을 채워넣음
console.log(myNumber.toFixed(5));  // 1.35910

// toString
// 입력한 값의 진법으로 바꾸고, String type결과를 반환한다.
// toString(2~36)
let myNumber1 = 255;
console.log(myNumber1.toString(2));  // 11111111
console.log(255..toString(8));  // 377
console.log((255).toString(8));  // 377
// 정수에 바로 .을 쓰면 property찾는지, 소수점 표기인지 헷갈려함
// 이 경우, .을 두 번 쓰면 된다. 혹은 ()로 한번 감싸면 된다.

Math객체

// 절댓값
console.log(Math.abs(-10));  // 10

// 최댓값
console.log(Math.max(2, -1, 4, 5, 0));  // 5

// 최솟값
console.log(Math.min(2, -1, 4, 5, 0));  // -1

// 거듭제곱
console.log(Math.pow(2, 3));  // 8

// 제곱근
console.log(Math.sqrt(26));  // 5.0990195135927845

// 반올림
console.log(Math.round(2.49));  // 2

// 버림과 올림
console.log(Math.floor(2.9));  // 2
console.log(Math.ceil(2.1));  // 3

// [0,1) random
console.log(Math.random());

소수점 오류

let sum = 0.1 + 0.2;
console.log(sum);  // 0.300000000000004?

// 필요한 자리수만큼 반올림하기
console.log(Number(sum.toFixed(1)));
console.log(+sum.toFixed(1));
console.log(Math.round(sum * 10) / 10);

문자열 메소드

let myString = 'Hi Codeit';

// 문자열 길이
console.log(myString.length);  // 9

// 요소 접근
console.log(myString[3]);  // C
console.log(myString.charAt(3));  // C

// 요소 탐색
console.log(myString.indexOf('i'));  // 1
console.log(myString.lastIndexOf('i'));  // 7
console.log(myString.indexOf('z'));  // -1

// 대소문자 변환
console.log(myString.toUpperCase());  // HI CODEIT
console.log(myString.toLowerCase());  // hi codeit

// 양 끝 공백 제거
console.log(myString.trim());  // Hi Codeit

// 부분 문자열 접근 slice(start, [end(not inclusive)])
// 두번째 인자가 개수가 아니라 endIndex를 넣어야함!!!
console.log(myString.slice(0, 2));  // 'Hi'
console.log(myString.slice(3));  // Codeit
console.log(myString.slice());  // Hi Codeit

문자열과 배열의 차이점은?

// 배열은 mutable
// 문자열은 immutable
let myString = 'Codeit';
myString[0] = 'B'; // error가 발생 안함! 그렇다고 myString의 첫 character가 바뀐 것도 아님
console.log(myString);  // 'Codeit'

기본형과 참조형

/*
Number, String, Boolean, null, undefined는 기본형(Primitive type)
Object는 참조형(Reference type)
*/

// 기본형에 대한 예시
let x = 3;
let y = x;
console.log(x);  // 3
console.log(y);  // 3
y = 5;
console.log(x);  // 3
console.log(y);  // 5

// 참조형에 대한 예시
let x = {'name': 'Codeit'};  // x는 우측 객체의 주소를 가리킴
let y = x;  // y는 x가 가진 주소를 가리킴, 따라서 x, y 모두 주소를 가리킴
console.log(x);  // {'name': 'Codeit'}
console.log(y);  // {'name': 'Codeit'}
y.birth = 2017;
console.log(x);  // {'name': 'Codeit', 'birth':2017}
console.log(y);  // {'name': 'Codeit', 'birth':2017}

// 배열도 객체니까 참조형
// 우측이 기본형인지 참조형인지가 중요

// 예시
let x = {
  numbers: [1, 2, 3, 4],
  title: 'Codeit',
};
let y = x.numbers;
let z = x.title;
 
x.numbers.unshift(5);
x.title = 'Hello';

console.log(y);  // [5, 1, 2, 3, 4]
console.log(z);  // 'Codeit'

참조형 복사하기

// 참조형을 복사하기(Reference type copy)

// 배열
let numbers1 = [1, 2, 3];
let numbers2 = numbers1;  // 참조형
let numbers3 = numbers1.slice();

// 객체
let course1 = {
	'title': '파이썬 프로그래밍 기초',
	'language': 'Python',
	'prerequisites': [101, 102]
}

let course2 = Object.assign({}, course1);

course2.title = '알고리즘의 정석';
course2.prerequisites.push(103);

console.log(course1);
console.log(course2);
/*
{
  title: '파이썬 프로그래밍 기초',
  language: 'Python',
  prerequisites: [ 101, 102, 103 ]  << 원하지 않은 변경, 
}
{
  title: '알고리즘의 정석',
  language: 'Python',
  prerequisites: [ 101, 102, 103 ]
}
*/
// 따라서 아래의 함수를 만들어 사용하자.
function cloneObject(object) {
	if (object === null || typeof object !== 'object') {
		return object
	}

	let temp;
	if (Array.isArray(object)) {
		temp = [];
	} else {
		temp = {};
	}
	
	for (let key of Object.keys(object)) {
		temp[key] = cloneObject(object[key])
	}
	
	return temp;
}

const, 변수와 상수 사이

// let과 const의 차이는 "재할당" 가능 여부
// const로 변수 선언을 함으로서 재할당이 이후에 없음을 보여주는게 
// 유지보수 측면에서 좋다. 따라서, 재할당이 안될 const로 최대한 선언해주는 것이 좋다.
// const로 선언하여도 객체의 주소를 바라본다면(참조형), 객체를 수정하는 것은 가능
// 이는 모든 언어에서도 권장함, 최대한 재할당없게 const쓰고, 재할당이 필요하면 let 사용
const x = {'name': 'Codeit'};
x.birth = 2017;  // x가 가리키는 참조 주솟값은 유지되니까, 가능함
728x90
728x90
  • sigmoid_cross_entropy_with_logits
    • sigmoid and then cross entropy
    • scalar를 반환함
  • weighted_cross_entropy_with_logits
    • sigmoid and then cross entropy plus positive weight
    • positive weight란, cross entropy에서 positive label에 부여한 weight로
      • 1보다 크게주면 학습 중 positive인 것에 대한 loss를 가중치를 주어 positive인 것은 일단 잘 맞추게 하는 방식, 즉 recall을 올리는 방식
      • 1보다 작게주면 그 반대로, precision을 올리는 방식
  • softmax_cross_entropy_with_logits
    • softmax and then cross entropy
    • label이 꼭 one-hot일 필욘 없음, 확률 분포여도 사용 가능(즉, 0이상이고 전체 합이 1)
  • sparse_softmax_cross_entropy_with_logits
    • softmax and then cross entropy
    • label이 one-hot이 아닌 index integer를 받음, 그 외는 softmax_cross_entropy_with_logits와 같음
728x90
728x90
  • import 타임이란 것을 체험?해보자.
# registration.py
# BEGIN REGISTRATION

registry = []  # <1>

def register(func):  # <2>
    print('running register(%s)' % func)  # <3>
    registry.append(func)  # <4>
    return func  # <5>

@register  # <6>
def f1():
    print('running f1()')

@register
def f2():
    print('running f2()')

def f3():  # <7>
    print('running f3()')

def main():  # <8>
    print('running main()')
    print('registry ->', registry)
    f1()
    f2()
    f3()

if __name__=='__main__':
    main()  # <9>

# END REGISTRATION

"""
$ python3 registration.py
running register(<function f1 at 0x100631bf8>)  # running main보다 먼저 실행
running register(<function f2 at 0x100631c80>)  # running main보다 먼저 실행
running main()
registry -> [<function f1 at 0x100631bf8>, <function f2 at 0x100631c80>]
running f1()
running f2()
running f3()
"""

 

# registration.py를 실행하지 않고 import하면
>>> import registration
running register(<function f1 at 0x10063b1e0>)  # decorator의 실행이 확인됨
running register(<function f2 at 0x10063b268>)

즉, decorator는 모듈이 import되자마자 실행되지만, decorated function은 명시적으로 호출될 때만 실행됨을 알 수 있다. 이 예제는 파이썬 개발자가 "import time"과 "runtime"이라고 부르는 것의 차이를 명확히 보여준다.

  • 참고
    • 위처럼 decorator와 decorated function이 한 모듈에 정의되어 있는 것은 일반적이지 않다. 대개 다른 모듈에 정의하여 사용함
    • 위처럼 decorator가 decorated function을 그대로 반환하는 것은 일반적이지 않다. 대개 내부함수를 정의해서 반환한다.
    • 그대로 반환하는 부분은 유용하지 않지만, registry.append 부분처럼 웹 프레임워크에서 "함수를 어떤 중앙의 레지스트리에 추가"하는 형태로 사용한다.
  • 이와 마찬가지로
    • class가 포함된 module을 import할 때 class variable이 실행됨
      • 이는 singleton을 아주 쉽게 구현할 때 사용
    • function을 정의할 때 default value를 mutable한 것으로 설정하면 안되는 이유가
      • function을 import할 때, default value 객체를 만든다.
      • 이후 function을 call을 할 때, import할 때 만들어진 default value를 계속 활용한다.
      • 근데, 이 default value가 mutable이었으면 기대한 바와 다르게 프로그래밍 될 수 있다.
        def test_function(a, b=[]):
            b.append(a)
            print(b)
        
        if __name__ == '__main__':
            test_function(3)  # [3], expected
            test_function(4)  # [3, 4], unexpected​
728x90
728x90

수명 주기 동안 결코 변하지 않는 해시값을 갖고 있고(__hash__() 메서드가 필요) 다른 객체와 비교할 수 있으면(__eq__() 메서드가 필요), 객체를 해시가능하다고 한다. 동일(==)하다고 판단되는 객체는 반드시 해시값이 동일해야 한다.

  • 모든 불변형은 해시가능하다.
    • 조금 틀린 말이다. tuple의 경우 불변형이지만, 해시불가능한 객체를 참조할 때는 튜플 그 자체도 해시불가능해진다.
  • 사용자 정의 자료형은 기본적으로 해시가능하다. 그 이유는 __hash__() 가 id() 를 이용하여 구하므로 모든 객체가 서로 다르기 때문
  • 파이썬 dictionary의 경우 hashtable, open addressing 방식으로 구현되어 있다. dict.get("key")로 조회를 하는 경우 다음 순서를 따른다.
    • "key"의 hash값으로 먼저 조회
    • hash값이 hashtable에 존재하더라도 그 hash값을 가지는 원소의 "key"를 비교한다. hash와 key값 비교(==)가 완료된 것의 value를 반환한다.
  • 따라서 아래의 예제가 이해된다.즉, key는 가변적이고 hash값은 dictionary 객체가 생성될 때의 값을 사용한다는 것을 알기.
  • class MyList(list):
        # 임의로 수명주기 동안 변하지 않는 hash가 아니라
        # 수명주기 동안에도 변하는 hash를 준 예제
        def __hash__(self):
            return sum(self)
    
    
    my_list = MyList([1, 2, 3])
    
    my_dict = {my_list: 'a'}
    
    print(my_dict.get(my_list))  # a
    
    my_list[2] = 4  # __hash__() becomes 7
    print(next(iter(my_dict)))  # [1, 2, 4], 즉 key가 변경
    
    print(my_dict.get(MyList([1, 2, 3])))  
    # None, hash값은 같지만 key비교가 안맞아서 조회 불가 
    
    print(my_dict.get(MyList([1, 2, 4])))  
    # None, dictionary 객체가 생성될 때의 hash값(6)과 안맞아서 조회 불가
    # 이 부분이 중요, 같은 key값을 넣었지만, dictionary(hashtable)이 보유한 hash는 6이라서 안된 점
    # 즉, line:14에서 key변경을 해도 dictionary는 보유한 hash를 업데이트 하지 않음(6으로 고정)
    
    my_list[0] = 0  # __hash_() is 6 again, but for different elements
    print(next(iter(my_dict)))  # [0, 2, 4], 즉 key가 변경
    
    print(my_dict.get(my_list))  
    # 'a', hash값비교(6==6), key값비교(MyList([0,2,4])==MyList([0,2,4]))돼서 조회가능
    • 따라서,
      • hash메소드는 객체 수명 주기 동안 불변한 값으로 정의하라는 지침이 있는 이유를 알 수 있다.
      • dictionary key는 왜 hashable만 받게 해둔 것인지를 알 수 있다.
728x90
728x90
  • Amazon CloudWatch는 DevOps 엔지니어, 개발자, SRE(사이트 안정성 엔지니어) 및 IT 관리자를 위해 구축된 모니터링 및 관찰 기능 서비스입니다. CloudWatch는 애플리케이션을 모니터링하고, 시스템 전반의 성능 변경 사항에 대응하며, 리소스 사용률을 최적화하고, 운영 상태에 대한 통합된 보기를 확보하는 데 필요한 데이터와 실행 가능한 통찰력을 제공합니다.
  • AWS 서비스 전체에 대한 모니터링(내용), 퍼포먼스 체크가 주 기능
  • 주요 기능
    • 로그
      • AWS 내외의 로그를 모아 보관하고 사용자에게 전달
      • EC2, Autoscaling Groups, ELB, Route53, CloudFront, EBS, Storage Gateway 등
      • "누가 사용했냐"가 아니라 "어떻게 사용됐냐", "어떤 성능으로 무슨 일이 일어났냐" 등이 주 관심
      • 주요 서비스의 출력 결과 기록 (Lambda 등), 즉 내용이 중요
      • 사용자가 직접 로그 그룹을 만들어 외부로부터 로그를 적제 가능
        • 온프레미스 로그를 저장 및 사용
      • 로그를 쿼리 형식으로 분석 가능한 Insight 활용 가능
    • 경보
      • 로그를 기반으로 지표를 생성해서 특정 지표 조건에 따라 경보 발생
        • 경보는 다른 서비스(SNS 등) 호출 가능
        • CPU 사용량이 일정 수준 이상이라면...
        • 호출 Lambda에 에러가 발생한다면...
        • Autoscaling도 내부적으로 CloudWatch를 이용해 동작함
    • 이벤트
      • 일정 주기 혹은 AWS의 여러 이벤트를 감지해 다른 AWS 서비스(SNS, Lambda 등)을 호출하는 규칙을 이벤트라 한다.
          • 매시 정각마다 하루에 쌓인 로그를 분석위해 Lambda→S3→Athena...
          • 여러 이벤트 속의 규칙을 정의하여 그 이벤트가 감지되면 다른 서비스를 호출이 가능
          •  
            • EC2가 리붓되면 lambda 통해서 슬랙으로 이벤트 받아보기 가능
      • AWS EventBridge의 기능과 동일, EventBridge는 이벤트를 전문적으로 다루기 위해 CloudWatch에서 파생된 서비스
  • 기타 기능
    • 기타 로그를 위한 대시보드 기능

 

출처

AWS : CloudWatch vs Cloudtrail 정리 - YouTube

 

728x90

'Cloud > AWS' 카테고리의 다른 글

[AWS] Auto Scaling  (0) 2022.01.24

+ Recent posts