루나의 TIL 기술 블로그

자바스크립트 - 시계, 언어 변경

|

포트폴리오페이지에 간단한 자바스크립트 기능(시계, 언어변경)을 추가하기로 했다.
한국과 독일의 시간을 넣고 시간에 따라 사진이 낮/밤으로 바뀌도록 했고 언어는 세 가지가 바뀔 수 있도록 했다.
포트폴리오 링크

시계

포폴에 반영된 시계

  • html
<!-- 한국 시계-->
<div class="layer-intro" id="pic-kr">
    <h2 class="clock-kr"></h2>
</div>
<!-- 독일 시계-->
<div class="layer-intro" id="pic-de">
    <h2 class="clock-de"></h2>
</div>

상관없는 부분은 생략했다.

  • css
/* 도시 사진을 클래스마다 넣는다 */
.seoul-day {
  background-image: url(../images/seoul_day.jpeg);
  background-size: cover;
}
.seoul-night {
  background-image: url(../images/seoul_night.jpeg);
  background-size: cover;
  background-color: rgba(34, 49, 63, 0.6);
}
.berlin-day {
  background-image: url(../images/berlin_day.jpeg);
  background-size: cover;
  color: #333;
  background-color: rgba(34, 49, 63, 0.6);
}
.berlin-night {
  background-image: url(../images/berlin_night.jpeg);
  background-size: cover;
}
  • javascript
// clock-kr 클래스를 clock_kr 변수에 저장
var clock_kr = document.querySelector(".clock-kr");
var clock_de = document.querySelector(".clock-de");

function getTime() {
  // 자바스크립트에서 현재 시간 받아서 상수 curr에 저장 
  const curr = new Date();
  // 표준시간 UTC 구하기
  const utc = curr.getTime() + curr.getTimezoneOffset() * 60 * 1000;

  // UTC to KST 한국 (UTC + 9시간)
  const KR_TIME_DIFF = 9 * 60 * 60 * 1000;
  const kr_curr = new Date(utc + KR_TIME_DIFF);

  // UTC to CET 독일 (UTC + 1시간)
  const DE_TIME_DIFF = 1 * 60 * 60 * 1000;
  const de_curr = new Date(utc + DE_TIME_DIFF);

  // 시, 분 변수 저장
  let kr_hr = kr_curr.getHours();
  let kr_mm = kr_curr.getMinutes();
  let de_hr = de_curr.getHours();
  let de_mm = de_curr.getMinutes();

  //am, pm 표시
  var kr_ampm = kr_hr >= 12 ? "pm" : "am";
  var de_ampm = de_hr >= 12 ? "pm" : "am";

  // 10이하 숫자일때 보기 좋게 숫자 앞에 0 추가
  clock_kr.innerHTML =
    `${kr_hr < 10 ? `0${kr_hr}` : kr_hr}:${kr_mm < 10 ? `0${kr_mm}` : kr_mm}` +
    " " +
    kr_ampm;
  clock_de.innerHTML =
    `${de_hr < 10 ? `0${de_hr}` : de_hr}:${de_mm < 10 ? `0${de_mm}` : de_mm}` +
    " " +
    de_ampm;

  // 시간별로 사진 바꾸기
  // pic-kr 아이디를 obj_kr 변수에 저장
  var obj_kr = document.getElementById("pic-kr");
  var obj_de = document.getElementById("pic-de");
  // 7시 초과 18시 미만일 때 obj_kr 변수의 클래스를 seoul-day로 바꿈
  if (kr_hr > 7 && kr_hr < 18) {
    obj_kr.setAttribute("class", "seoul-day");
  } else {
    obj_kr.setAttribute("class", "seoul-night");
  }
  if (de_hr > 7 && de_hr < 18) {
    obj_de.setAttribute("class", "berlin-day");
  } else {
    obj_de.setAttribute("class", "berlin-night");
  }
}
// 1초마다 함수를 업데이트
setInterval(getTime, 1000);

언어 변경

포폴에 반영된 시계 포폴에 반영된 시계2

  • html
<li>
  <a>
    <!-- 이 부분이 왜인지 꼭 필요하던데 숨길 수가 없어서 css로 숨겼다 -->
    <p id="language">
      <span data-lang="now_sys_lang"></span>
      <span id="locale"></span>
    </p>
    <!-- 각 언어별 버튼 -->
    <span id="btn-ko" class="nav-lang">KR</span>
    <span id="btn-en" class="nav-lang">EN</span>
    <span id="btn-de" class="nav-lang">DE</span>
  </a>
</li>
  • css
/* 비활성화 일때 버튼 클래스 */
.nav-lang {
  border: grey 2px solid;
  border-radius: 4px;
  padding: 5px 10px;
  color: grey
}
/* 활성화 일때 버튼 클래스 */
.active {
  border: #1ecba7 2px solid;
  color:#1ecba7
}
/* 마우스 올렸을 때 버튼 색 변화 */
#btn-en:hover{
  border: #1ecba7 2px solid;
  color:#1ecba7
}
#btn-ko:hover{
  border: #1ecba7 2px solid;
  color:#1ecba7
}
#btn-de:hover{
  border: #1ecba7 2px solid;
  color:#1ecba7
}
#language{
  display:none;
} 
  • javascript

다국어지원 자바스크립트는 아래 블로그 글에서 복사해왔다.
http://yoonbumtae.com/?p=2469

// 언어별 JSON 파일
const lang = {
  en: {
    seoul: "Seoul",
    berlin: "Berlin",
    intro: "Introduction",
    intro_txt:
      "Luna is a foodie, film lover studying to become a useful developer. 2021 new year's resolution is to run regularly and polish on rusty piano skill. she majored in food science and worked as UX designer at K7music for a year and half.",
    title: "My Skills",
    content:
      "Luna is motivated to make software that improves people's life by combining the art of programming and intuitive design.",
    now_sys_lang: "EN",
    skill_a: "Proficiency with web markup and design, including HTML5, CSS3",
    skill_b:
      "Has solid working knowledge of server-side CSS pre-processing, such as LESS and SASS",
    skill_c: "Has basic understanding of client-side scripting and JavaScript",
    skill_d:
      "Experience with a variety of JS frameworks including React and Angular",
    contactme: "Feel free to contact me for your next project",
    portfolio: "Portfolio",
  },
  ko: {
    seoul: "서울",
    berlin: "베를린",
    intro: "자기소개",
    intro_txt:
      "맛있는 것과 재미있는 영화를 가장 좋아하는 30대 학생입니다. 올해에는 규칙적인 조깅과 피아노 실력향상을 목표로 하고있습니다. 식품영양을 전공했고 국비지원 자바 프론트엔드 과정을 들은 뒤에 독일의 인디음악회사에서 UX디자이너로 1년반정도 일했습니다. 앞으로 4개월간 잘 부탁드립니다!",
    title: "스킬",
    content:
      "사람들의 삶을 개선할 수 있는 소프트웨어를 만들고 싶습니다. 언어교육에 관심있습니다.",
    now_sys_lang: "KO",
    skill_a: "HTML, CSS를 포함한 웹디자인과 마크업에 능숙합니다",
    skill_b: "SCSS, LESS등 CSS전처리기를 이용해서 일한 경험이 있습니다",
    skill_c:
      "클라이언트측 스크립트 언어에 대한 지식이 있고 기본적인 자바스크립트를 활용할 수 있습니다",
    skill_d:
      "React, Angular 프레임워크로 서비스를 제공하는 환경에서 일했습니다",
    contactme: "궁금한 점이 있으면 언제든지 연락주세요",
    portfolio: "포트폴리오",
  },
  de: {
    seoul: "Seoul",
    berlin: "Berlin",
    intro: "Einführung",
    intro_txt:
      "Luna ist eine Feinschmeckerin und Filmliebhaberin, die studiert, um eine nützliche Entwicklerin zu werden. Der Vorsatz für das neue Jahr 2021 ist es, regelmäßig zu laufen und an rostigen Klavierkünsten zu polieren. sie studierte Lebensmittelwissenschaften und arbeitete eineinhalb Jahre als UX-Designerin bei K7music.",
    title: "Fahigkeit",
    content:
      "Luna ist motiviert, Software zu entwickeln, die das Leben der Menschen verbessert.",
    now_sys_lang: "DE",
    skill_a: "Kenntnisse in Web-Markup und -Design, einschließlich HTML5, CSS3",
    skill_b:
      "Hat solide Kenntnisse der serverseitigen CSS-Vorverarbeitung wie LESS und SASS",
    skill_c:
      "Hat grundlegende Kenntnisse in clientseitigem Scripting und JavaScript",
    skill_d:
      "Erfahrung mit einer Vielzahl von JS-Frameworks einschließlich React und Angular",
    contactme: "Kontaktieren Sie mich gerne für Ihr nächstes Projekt",
    portfolio: "Portfolio",
  },
};

// 아래부분 4가지는 복사해다 붙여넣기 했는데 무슨 뜻인지 아직 잘 모르겠다.
// 현재 브라우저의 언어 가져오기
function getLanguage() {
  return navigator.language || navigator.userLanguage;
}

// 언어별 적용
function init(localeStr) {
  document.getElementById("locale").textContent = localeStr;
}

// 초기 작업
const currentLang = getLanguage();
init(currentLang);
render(currentLang.substr(0, 2));

// 언어별 렌더링
function render(locale) {
  const $lang = document.querySelectorAll("[data-lang]");
  $lang.forEach((el) => {
    const code = el.dataset.lang;
    el.textContent = lang[locale][code];
  });
}

// 버튼 이벤트
document.getElementById("btn-en").addEventListener("click", (e) => {
  render("en");
});
document.getElementById("btn-ko").addEventListener("click", (e) => {
  render("ko");
});
document.getElementById("btn-de").addEventListener("click", (e) => {
  render("de");
});

// 버튼 활성화 - 비활성화일 때 클릭하면 활성화
$(".nav-lang").on("click", function () {
// nav-lang 클래스가 클릭되면 함수실행
  $(".nav-lang").removeClass("active");
  // nav-lang 클래스 모두(버튼3개)에서 active 클래스 삭제 
  $(this).addClass("active");
  // 클릭된 버튼 클래스에 active클래스 추가
});

주요 포인트 및 생각해볼 점

css - 템플릿에서 사진에 회색이 옅게 깔려있는게 예뻤는데 복사해서 만든 요소에는 적용되지 않는다. 넣으려고 해봤는데 모르겠다.
js - 언어 변경하는데 사용된 함수를 꼭 다시 공부해봐야겠다.
포트폴리오 페이지는 나중에 이런 느낌으로 다시 만들고 싶다.
에이버리임 포트폴리오

질문

js - 사진이 로딩되는데 1초정도 걸려서 어색하다. 고치려면 어떻게 해야할까?

코데카데미 파이썬 기초과정 요약 - 매개변수(Parameter)와 인수(Argument)

|

매개변수와 인수 (Parameters and Arguments)

매개변수(parameter)는 함수의 정의 안에 있는 변수를 말한다
인수(argument)는 함수를 호출할 때 패스되는 값이다

매개변수와 인수

들어가는건 매개변수 나오는건 인수! 함수의 인수는 파이썬에서 꼭 필요하다.
두 개의 매개변수를 정의하고 함수에 두 개의 인수를 패스하는게 표준함수의 정의이다.

키워드 인수 (Keyword Arguments)

키워드 인수는 말 그대로 인수에 이름(키워드)을 붙이는 기능인데 키워드=값 형식으로 사용한다.

파이썬에서 함수를 호출할 때, 우리는 매개변수를 함수 정의할 때 썼던 순서 그대로 나열해야되는데 키워드 인수를 사용하면 그렇지 않아도 된다.

함수가 선택적인 디폴트 인수를 많이 갖고 있을 때나 매개변수의 순서를 알기 어려울 때 키워드 인수를 사용하는 것이 유용한다.

다음과 같은 함수가 선택적인 디폴트 인수를 많이 가지고 있는 함수이다.

# 디폴트 인수들을 많이 가진 함수를 정의해보자
def log_message(logging_style="shout", message="", font="Times", date=None):
  #로그_메세지() 함수를 정의했고 이 함수는 0에서 4개까지의 인수를 가질 수 있다
  if logging_style == 'shout':
    # 메세지를 대문자로 바꾸자
    message = message.upper()
  print(message, date)
 
# 키워드 인수 2개로 함수를 호출해보자
log_message(message="Hello from the past", date="November 20, 1693")
# 4개의 인수가 어떤 순서로 정의될 지 확실하지 않기 때문에 우리는 함수를 호출하기 위해서 매개변수 이름을 쓸 수 있다

함수를 호출하면서message=”Hello from the past” 구문을 사용한 점에 주의하자.
여기서 이 키워드 message는 우리가 인수를 패스하고자하는 매개변수의 이름이어야한다.

인수의 위치

인수의 위치와 순서

디폴트 인수 (Default Arguments)

인수값을 넣지 않고 호출했을 때 출력되는 인수이다.

디폴트 인수

변형 가능한 객체를 디폴트 인수로 사용하지 않는다

디폴트 인수를 갖고 함수를 만들 때, 빈 리스트를 쓰고싶겠지만 그렇게하면 안 된다.
파이썬에서 어떤 객체들은 변형가능하지 않아서 기본 인수로 사용하기 좋다.

int, float를 비롯한 숫자들은 변형될 수 없다. 산술 연산은 새 숫자를 반환하는 것이다.
튜플도 변형 불가능한 리스트에 속한다.
문자열도 변형 불가하다 - 문자열을 업데이트하는 작업들도 새 문자열을 반환하고 있는 것이다.

  • 빈 리스트 대신 None 을 보초로 사용하자
def update_order(new_item, current_order=None): 
  #current_order=[]대신 =None을 넣고
  if current_order is None: #None이라면
    current_order=[] #빈 리스트를 만들어주는 방법을 사용하자
  current_order.append(new_item)
  return current_order

None

None은 파이썬에서 특별한 값이다. 유일무이하고 (두 개의 다른 None이란 없다!) 변형불가하다 (None을 업데이트하거나 새 속성을 부여할 수 없다)
None 은 거짓으로 취급되서 if문에 넣으면 거짓을 반환한다. None은 유일무이하기 때문에 어떤 것이 None인지 테스트하고 싶을 때는 is 키워드를 사용한다.

# session_id을 none으로 정의한다
session_id = None
 
if session_id is None:
  print("session ID is None!")
  # 이걸 실행하면 "session ID is None!" 가 출력된다
 
# session_id에다가 뭔가를 할당할 수 있다
if active_session:
  session_id = active_session.id
 
# 하지만 active_session이 없다면, 우리는 개인정보를 보내지 않는다
if session_id is not None:
  send_sensitive_data(session_id)

함수가 아무것도 반환하지 않을때는 무엇을 반환할까? 수수께끼같은 질문이지만 정답은 있다.
반환을 하지 않는 함수는 완료 후 None을 반환한다.

prints_return = print("이 함수는 무엇을 반환할까요?")

print(prints_return)
#결과 : None

# sort_this_list.sort()를 호출하고 list_sort_return에 저장한다
sort_this_list = [14, 631, 4, 51358, 50000000]
list_sort_return = sort_this_list.sort()

print(list_sort_return)
#결과 : None

코데카데미 파이썬 기초과정 요약 - 클래스3 음식점메뉴 TIL

|

클래스 과정의 마지막 리뷰이다.

영어이지만 이 비디오를 보면 문제와 코드를 쓰는 과정을 알 수 있다.

class Menu: #메뉴셋트의 이름, 메뉴 아이템들, 가능시작시간, 제공종료시간
  def __init__(self,name,items,start_time,end_time):
    self.name = name
    self.items = items
    self.start_time = start_time
    self.end_time = end_time

  def __repr__(self): #클래스의 대표가되는 스트링을 반환하는 매직 매쏘드
    return self.name + ' menu availble from ' + str(self.start_time) + '-' + str(self.end_time)
    # 예를 들어 brunch_menu 는 11시부터 16시까지 가능합니다 문자열 반환

  def calculate_bill(self, purchased_items): #음식값 계산
    bill = 0
    for purchased_item in purchased_items: #구매한 아이템들을 쭉 흝으면서
      if purchased_item in self.items: #구매한 아이템이 메뉴 아이템들 중에 있다면?
        bill += self.items[purchased_item] #구매한 아이템의 밸류(가격)를 빌에 추가한다
    return bill

# Brunch Menu
brunch_items = {
  'pancakes': 7.50, 'waffles': 9.00, 'burger': 11.00, 'home fries': 4.50, 'coffee': 1.50, 'espresso': 3.00, 'tea': 1.00, 'mimosa': 10.50, 'orange juice': 3.50
}
brunch_menu = Menu('Brunch', brunch_items, 1100,1600)
#브런치_메뉴는 브런치라는 이름이고 브런치_아이템즈 리스트를 가지고 11시부터 16시까지이다.
print(brunch_menu.calculate_bill(['pancakes', 'home fries', 'coffee']))
#13.5
#브런치_메뉴에서 calculate_bill매쏘드를 써서 (['주문한 메뉴'])의 값을 출력한다.
#왜떔시 변수 이름들을 헷갈리게 만들어놓고는 두 뎁쓰로 나눠서 표현해야했을까?

early_bird_items = {
  'salumeria plate': 8.00, 'salad and breadsticks (serves 2, no refills)': 14.00, 'pizza with quattro formaggi': 9.00, 'duck ragu': 17.50, 'mushroom ravioli (vegan)': 13.50, 'coffee': 1.50, 'espresso': 3.00,
}
early_bird_menu = Menu('Early Bird', early_bird_items, 1500,1800)
print(early_bird_menu.calculate_bill(['mushroom ravioli (vegan)', 'salumeria plate']))
#21.5

dinner = {
  'crostini with eggplant caponata': 13.00, 'ceaser salad': 16.00, 'pizza with quattro formaggi': 11.00, 'duck ragu': 19.50, 'mushroom ravioli (vegan)': 13.50, 'coffee': 2.00, 'espresso': 3.00,
}
kids = {
  'chicken nuggets': 6.50, 'fusilli with wild mushrooms': 12.00, 'apple juice': 3.00
}

#장사가 잘되서 프랜차이즈를 내기로 했다
#설명하는 사람의 말로는 이렇게 상위 클래스를 만들게 되는 것이 이번 연습의 중점이라고 한다

class Franchise:
  def __init__(self, address, menu):
    self.address = address
    self.menus = menus
  def __repr__(self): #프랜차이즈 클래스는 대표 문자열로 주소를 반환한다
    return self.address

  def available_menus(self, time):
    available_menus = []
    for menu in self.menus:
      if time >= menu.start_time and time <= menu.end_time #입력받은 시간이 메뉴의 시작시간의 이후이거나 종료시간 이전일 떄
        #TMI : 이 부분 오류가 났는데 선생님 코드하고 비교해보니까 똑같이 생겼다
        available_menus.append(menu) #메뉴를 가능한 메뉴들 리스트에 넣는다
    return available_menus

menus = [brunch_items, early_bird_items, dinner, kids]
#새 변수 = 클래스(변수가 가지게 할 값) 이 순서는 항상 헷갈려서 세번쯤 틀렸다
flagship_store = Franchise("1232 West End Road", menus)
new_installment = Franchise("12 East Mulberry Street", menus)

print(flagship_store)
#1232 West End Road

flagship_store.available_menus(1200)

#프랜차이즈가 잘 되서 비즈니스로 확장하기로 했다고 한다.

class Business:
  def __init__(self, name, franchises):
    self.name = name
    self.franchises = franchises

basta = Business("Basta Fazoolin' with my Heart", [flagship_store, new_installment])

arepas_items = {
  'arepa pabellon': 7.00, 'pernil arepa': 8.50, 'guayanes arepa': 8.00, 'jamon arepa': 7.50
}
arepas_menu = Menu("Take a Arepa", arepas_items, 1000, 2000)
arepas_place = Franchise('189 Fitzgerald Avenue', [arepas_menu])
arepa = Business("Take a' Arepa", [arepas_place])
print(arepa.menus[0])

파이썬과 자바스크립트 비교 - 백준 10430 나머지

|

파이썬과 자바스크립트의 차이를 살펴보고싶어서 algorithm 백준에서 나머지를 구하는 문제를 살펴보았다.

문제

(A+B)%C는 ((A%C) + (B%C))%C 와 같을까?
(A×B)%C는 ((A%C) × (B%C))%C 와 같을까?
세 수 A, B, C가 주어졌을 때, 위의 네 가지 값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 A, B, C가 순서대로 주어진다. (2 ≤ A, B, C ≤ 10000)

출력

첫째 줄에 (A+B)%C, 둘째 줄에 ((A%C) + (B%C))%C, 셋째 줄에 (A×B)%C, 넷째 줄에 ((A%C) × (B%C))%C를 출력한다.

풀이

  • 파이썬
A,B,C = map(int,input().split())
# 입력받은 값들을 인트형으로 받아서 A, B, C 변수에 나누어 저장한다.
print((A+B)%C, ((A%C)+(B%C))%C, (A*B)%C, ((A%C)*(B%C))%C, sep='\n')
# sep으로 줄바꿈해준다


  • 자바스크립트
const fs = require("fs");
//파일 시스템 모듈을 사용한다
const input = fs.readFileSync("/dev/stdin").toString().split(" ");
//입력받는 값을 문자열로 만들고 공백으로 나눈다.
const A = parseInt(input[0]);
//첫번째 입력받은 값을 A에 저장한다.
const B = parseInt(input[1]);
const C = parseInt(input[2]);
//출력
console.log((A + B) % C);
console.log(((A % C) + (B % C)) % C);
console.log((A * B) % C);
console.log(((A % C) * (B % C)) % C);

주요 포인트 및 생각해볼 점

한 줄짜리 문제라 언어를 비교하기는 어렵지만, 내 생각에는 파이썬을 잘 읽고 잘 쓰려면 생각을 더 해야될 것 같다. algorithm 풀 때는 파이썬이 더 쓰기 편할 것 같다. 아마 웹서비스를 만들때는 자바스크립트가 더 좋지 않을까?

코데카데미 파이썬 기초과정 요약 - 코딩챌린지

|
  • 사용된 알파벳 갯수를 출력하는 함수를 만들어보자

힌트 : 주어진 영어알파벳 리스트를 흝어서 해당 알파벳이 입력된 단어 안에 있는지 보세요

letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

def unique_english_letters(word):
  count = 0
  for letter in letters:
    if letter in word:
      count += 1
  return count

print(unique_english_letters("mississippi"))
# 4
print(unique_english_letters("Apple"))
# 4


이건 답을 보고나서 좀 헷갈렸는데 알파벳 리스트를 사용한 덕분에 중복을 체크할 필요가 없다는 것을 알았다. letters리스트를 쭉 흝으면서 a 가 있나? +0 b가 있나? +0 … s가 있나? +1 t가 있나? +0 이렇게 가기 때문에 word에 같은 알파벳이 중복되서 들어있는걸 판별하는 부분을 안 써도 된다.

주요 포인트 및 생각해볼 점

코드블럭안의 코드를 wrap해서 넘길 수 있는 방법이 없을까? -> 코드를 줄바꿈하자 글 오른쪽 여백에 해당 글의 구성목록을 보여줄 수 없을까?

자바스크립트 기초 - 변수 06.04 TIL

|

var, let, const

var는 변수, let은 변수, const(상수)는 재선언할 수 없는 변수이다.
let과 const는 블록{} 범위이며 var는 함수 범위이다.

어떤 상황에서 어떤 것을 사용하는게 좋을지는 아직 잘 모르겠다.
-> 06.15 let, const, var의 쓰임과 스코프에 관련해서 간결하고 좋은 강의를 발견했다.

설명을 읽던 중 호이스팅과 초기화 관련해서 궁금한 점이 생겨서 자세히 알아보았다.

변수의 3단계 생성과정

변수는 아래와 같이 3단계의 과정을 통해 생성된다.

  1. 선언단계 : 변수를 실행컨텍스트의 변수객체에 등록한다.
  2. 초기화 단계 : 실행 컨텍스트에 등록 된 변수객체에 대한 메모리를 할당한다. 이 단계에서 변수는 undefined로 초기화 된다.
  3. 할당단계 : undefined로 초기화 된 변수에 값을 할당한다.

var 키워드로 변수를 만들 경우, 선언단계와 초기화 단계가 동시에 이뤄진다.
let 키워드는 선언단계와 초기화 단계가 분리되어 진행된다.

let 키워드로 선언된 변수는 hoisting 되어 선언단계가 이뤄지지만
초기화 단계는 실제 let이 사용된 코드에 도착했을 때 이뤄진다.
초기화 단계 이전에 변수에 접근하려하면 reference 에러가 발생한다.

출처 - var, let, const 특징 및 호이스팅

아직은 정확히 어떤 차이인지 잘 모르겠다. 코드를 쓰면서 알아나가지 않을까 생각한다.

참고 - let, const와 블록 레벨 스코프

  • 연습문제 : 칼빈 293도일 때 섭씨와 화씨를 구해보자

      const kelvin = 293; //변하지 않는 상수
      let celsius = kelvin - 273;
      let fahrenheit = celsius * (9/5) + 32;
      t = Math.floor(fahrenheit);
      console.log('The temperature is '+t+' degrees fahrenheit.');
    

코데카데미 파이썬 기초과정 요약 - 상속과 다형성

|

상속과 다형성

클래스라는 것이 코드를 재사용할 수 있도록 디자인되었지만, 이미 있는 클래스와 비슷한 클래스를 더 만들고 싶다면 어떨까?
클래스 안의 원래 있는 요소들을 사용하면서 특정 부분만 다르게 사용하고 싶다면 원래 클래스를 상속하면 된다. 리믹스같은 개념이라고 생각하면 좋다. 원래 노래하고 아주 비슷하지만 뭔가 다르다.- 코데카데미

상속 (Inheritance)

class User:
  is_admin = False
  def __init__(self, username)
    self.username = username
 
class Admin(User): #자식(부모)
  is_admin = True

유저 클래스를 상속해서 하위클래스 어드민을 만들었다. 새 어드민 클래스는 유저 클래스의 모든 생성자를 가지면서 is_admin이라는 것을 새로이 가지고 있다.
종종 상속하는 클래스를 부모라고 하고 하위 클래스를 자식이라고 한다.

다형성 (Polymorphism)

다형성이란 같은 구문이 데이터 타입에 따라 다른 행동을 하는 것을 말한다.

우리가 흔히 더하기라고 알고있는 + 는 파이썬에서 자료형별로 다른 역할을 한다.
예를 들어 int + int 를 하면 int가 나오고 list + list를 하면 해당 list들을 합친 리스트가 나온다.
여기서는 +를 예로 들었지만 어떤 매쏘드도 이렇게 동작할 수 있다.

# 숫자형과 숫자형을 더하면, + 더하기 부호는 숫자형을 반환한다
2 + 4 == 6
 
# float형과 float형을 더하면 +는 float형을 반환한다
3.1 + 2.1 == 5.2
 
# 문자형과 문자형을 더하면, +는 문자형을 반환한다
"Is this " + "addition?" == "Is this addition?"
 
# 리스트형과 리스트형을 더하면, +는 리스트형을 반환한다
[1, 2] + [3, 4] == [1, 2, 3, 4]

예외처리 (Exception)

재고 없음 Exception을 만들어서 적용해보자

class OutOfStock(Exception): 
#Exception을 상속받아 재고없음 클래스를 만든다
  pass #그냥 들여쓰기 에러를 피하기 위해서 적어놓은 것

class CandleShop: #양초가게
  name = "Here's a Hot Tip: Buy Drip Candles" #가게이름
  def __init__(self, stock): #클래스에 재고 속성을 추가
    self.stock = stock
    
  def buy(self, color): #색깔 속성을 가진 구매 매쏘드를 만든다
    if self.stock[color] < 1: #해당 색상의 재고가 1개 미만이면
      raise OutOfStock #재고없음 클래스호출
    self.stock[color] = self.stock[color] - 1 
    #아니면 해당 색상의 재고 1개 빼기

candle_shop = CandleShop({'blue':6,'red':2,'green':0})
candle_shop.buy('blue')

#재고없음이 출력되야한다!
candle_shop.buy('green')

Overriding Methods

유저 클래스에서 쓰이는 edit_message매쏘드를 새 하위클래스 어드민에서 오버라이드해보자.

class Message:
  def __init__(self, sender, recipient, text):
    self.sender = sender
    self.recipient = recipient
    self.text = text

class User:
  def __init__(self, username):
    self.username = username
    
  def edit_message(self, message, new_text):
    if message.sender == self.username: 
    #메세지 전송하는 사람이 해당 유저와 유저네임이 같다면
      message.text = new_text
      #메세지의 텍스트를 new_text에 넣는다
      
class Admin(User):
  def edit_message(self, message, new_text):
    message.text = new_text
    # 유저권한 확인 없이 메세지의 텍스트를 new_text에 넣는다

Super()

오버라이딩도 좋지만 존재하는 매쏘드에 로직을 추가하고 싶을 때, 부모 클래스를 통해서 매쏘드를 호출 해야하는데 그럴 때 super()가 쓰인다.

감자샐러드 클래스를 상속받아서 건포도를 추가한 스페셜감자샐러드를 만들어보자

class PotatoSalad:
  def __init__(self, potatoes, celery, onions):
    self.potatoes = potatoes
    self.celery = celery
    self.onions = onions

class SpecialPotatoSalad(PotatoSalad):
  def __init__(self,potatoes, celery, onions):
    super().__init__(potatoes, celery, onions) 
    self.raisins = 40

인터페이스 (Interface)

다른 클래스에서 온 다른 객체가 같은 동작을 수행하면 같은 인터페이스를 implement했다고 본다.

두 개의 클래스가 같은 이름의 속성들과 매쏘드들을 가지고있을 때 우리는 이 클래스들이 같은 인터페이스를 implement했다고 한다. 파이썬에서 인터페이스는 대게 클래스가 취하는 매쏘드와 인자가 무엇인지를 가리킨다.
다른 프로그래밍언어는 인터페이스가 무엇인가에 대해서 좀 더 정해진 정의를 가지고 있다. 하지만 대게는 다른 클래스에서 온 다른 객체가 같은 동작을 수행하는걸 의미한다. (비록 각 클래스마다 다르게 implement되었어도)

When two classes have the same method names and attributes, we say they implement the same interface. An interface in Python usually refers to the names of the methods and the arguments they take. Other programming languages have more rigid definitions of what an interface is, but it usually hinges on the fact that different objects from different classes can perform the same operation (even if it is implemented differently for each class).

class InsurancePolicy:
  def __init__(self, price_of_item):
    self.price_of_insured_item = price_of_item
    
class VehicleInsurance(InsurancePolicy):
  def get_rate(self):
    return self.price_of_insured_item * .001

class HomeInsurance(InsurancePolicy):
  def get_rate(self):
    return self.price_of_insured_item * .00005

주요 포인트 및 생각해볼 점

super를 사용하면서 쓰임에 대해서 다시 알아봐야겠다.

질문

Polymorphism is an abstract concept that covers a lot of ground, but defining class hierarchies that all implement the same interface is a way of introducing polymorphism to our code.?
다형성은 많은 것을 커버하는 추상적인 개념이지만 모두 같은 인터페이스를 implement한 클래스들로써 위계구조를 정의하는 것이 다형성을 우리의 코드에 소개하는 방법일까? 이게 무슨 뜻일까?

코데카데미 파이썬 기초과정 요약 - 클래스2

|
  • 원의 넓이 구하는 클래스 만들기

    class Circle:
      pi = 3.14
      def __init__(self, diameter):
        print("Creating circle with diameter {d}".format(d=diameter))
        self.radius = diameter/2
      def circumference(self):
        return 2 * self.pi * self.radius
    
    medium_pizza = Circle(12)
    teaching_table = Circle(36)
    round_room = Circle(11460)
    
    print(Circle.circumference(medium_pizza))
    print(Circle.circumference(teaching_table))
    print(Circle.circumference(round_room))
    
  • 학생의 이름, 학년, 점수를 속성으로 가지는 클래스 만들기

    type()함수는 객체를 받아서 해당 객채가 속한 클래스를 반환한다.

    class Student:
      def __init__(self, name, year): 
      #self, name, year가 Student 클래스의 타입이 된다
        self.name = name
        self.year = year
        self.grades = []
    
      def add_grade(self, grade):
        if type(grade) is Grade: 
        #add_grade 매쏘드에서 입력된 grade가 Grade 클래스의 타입인지 확인한다
          self.grades.append(grade)
    
    class Grade:
      minimum_passing = 65
      def __init__(self,score):
        self.score = score
    
    roger = Student("Roger van der Weyden", 10)
    sandro = Student("Sandro Botticelli", 12)
    pieter = Student("Pieter Bruegel the Elder",8)
    pieter.add_grade(Grade(100))
    #100점의 새 Grade를 만들고 .add_grade()매쏘드를 이용해서 피터의 .grades에 추가한다.
    

코데카데미 파이썬 기초과정 요약 - 클래스

|

클래스를 살펴보기에 앞서 클래스 안의 함수를 지칭하는 매쏘드를 살펴보자.

Method

클래스 안에 들어있는 함수를 매쏘드라고 부른다 (그래서 클래스로 만든 객체에서만 호출할 수 있다) 첫번째 파라미터로서 self를 가지고 항상 한 개 이상의 파라미터를 가진다.
  • 클래스 안의 매쏘드
class Orange:
    def __init__(self):
        #생성자로 사용되는 매직매쏘드 init
        print("Orange Created!")

이렇게 두 개의 __ 언더스코어로 둘러쌓인 매쏘드는 매직매쏘드라고 불리고 객체를 생성하는 것같은 특별한 목적을 위해서 사용된다. __new__, __init__ 등이 있다.

Class


The object-oriented programming paradigm also addresses the problems that arise in procedural programming by eliminating global state, but instead of storing state in functions, it is stored in objects. In object-oriented programming, classes define a set of objects that can interact with each other. - ‘the self-taught programmer’ by cory althoff

클래스는 다른 것들과 상호작용할 수 있는 객체들의 모음이다.
클래스라는 것을 나타내기 위해서 첫 글자는 대문자를 사용하는 것이 관례이고 인스턴스화(클래스를 객체로 만드는 과정) 되어야한다.


인스턴스화

  • 다른 색과 무게의 오렌지들을 만들어내는 클래스 오렌지를 만들어보자.

      class Orange:
          def __init__(self, w, c):
              #init이라는 특별 매쏘드는 두 개의 인스탄스변수 weight와 color를 만든다.
              self.weight = w
              self.color = c
              #평소에 선언할 때와는 다르게 정의하는 값이 등호의 뒤에 와있다
              print("Created!")
    

    이렇게 새 객체를 만드는 것을 인스턴스화한다고 한다.

    • 지름 파라미터를 받아서 문자열을 출력하는 클래스 써클을 만들어보자
      class Circle:
      pi = 3.14
      def __init__(self, diameter):
          print("New circle with diameter: {d}".format(d=diameter))
          #"출력하고싶은내용{변수}".format(변수=파라미터)
      teaching_table = Circle(36)
      #결과 : New circle with diameter: 36
    

    전에 배웠던 포맷함수가 사용되었는데 파이썬 3.8부터는 print(f”{var=}”) 이렇게만 써도 된다도 한다. (출처 : https://www.daleseo.com/python-f-strings/)

  • 클래스로부터 인스탄스 변수를 생성하고 해당 객체들에게 변수를 할당하자

      class Store:
      pass
    

    붕어빵틀에 해당하는 클래스 변수 만들기

      alternative_rocks = Store() 
      isabelles_ices = Store()
      #스토어 클래스에서 찍어내는 인스턴스변수들 가게 2곳
      alternative_rocks.store_name = "Alternative Rocks" 
      isabelles_ices.store_name = "Isabelle's Ices"
      #해당 인스턴스변수들에게 가게이름 속성변수를 할당한다. 
      #(assign instance variables to these objects using the same attribute notation that was used for accessing class variables.)
    


궁금한 부분

코데카데미에서 아래 설명을 읽고 있었는데 맨 마지막 줄이 이해가 잘 가지 않았다.

The first dunder method we’re going to use is the init() method (note the two underscores before and after the word “init”). This method is used to initialize a newly created object. It is called every time the class is instantiated.

init 매쏘드는 클래스가 인스턴스화 될때마다 호출된다?
-> 06.03 붕어빵틀을 쓸 때 붕어빵틀을 구성하는 매쏘드를 사용하기때문에 붕어빵을 찍어낼 때(인스턴스화) 매쏘드가 호출된다고 생각한다.

initialize(초기화)와 instantiate(인스턴스화)의 정확한 뜻을 알아보자.

initialize(초기화)

확보된 메모리 영역을 어떤 값으로 채우거나 쓰레기 값을 일정한 값으로 바꾸는 것 - https://blog.naver.com/netgarng88

instantiate(인스턴스화)

인스턴스화는 클래스 내의 객체에 대해 특정한 변형을 정의하고, 이름을 붙인 다음, 그것을 물리적인 어떤 장소에 위치시키는 등의 작업을 통해, 인스턴스를 만드는 것을 의미한다. - http://www.terms.co.kr/instance.htm

인스턴스화2

#인스턴스 생성하기
new_orange = Orange()
#새 인스턴스 변수 이름 = 클래스()

그림을 보니 무슨 개념인지 조금 알 것 같지만 아직은 잘 모르겠다.

‘난 정말 c programming을 공부한 적이 없다구요’를 감수하신 이지유 선생님의 주옥같은 강의에서 초기화의 개념에 대해서 자세한 설명을 들었는데 메모리에 값을 할당하는 과정이 복잡했었다.

파이썬의 init함수에 대해서도 찾아보니 뭔가 복잡한 내용들이 있었는데 실제 코드를 작성하면서 더 공부해보고 나중에 다뤄봐야겠다.

어디로 가고 있는가? 그 곳에 도달하기 위해 오늘 무엇을 했는가? -토머스 헨리 헉슬리

코데카데미 파이썬 기초과정 요약 - 딕셔너리

|

Dictionaries

파이썬에서 딕셔너리(dictionary)란 사전형 데이터를 의미하며, key와 value를 1대1로 대응시킨 형태이다. 이때 하나의 key에는 하나의 value만이 대응된다.


  • 딕셔너리의 키를 반복문을 이용해 출력해보자

      dict = {"a":1,"b":2,"c":3}
      for element in dict:
          # 밸류를 프린트하려면 dict 대신 dict.value()를 사용한다
          print(element)
      #결과 : 딕셔너리의 키를 프린트한다
      "a"
      "b"
      "c"
    


  • 두 리스트를 합쳐서 딕셔너리를 만들어보자 - zip의 사용

      numbers = [1, 2, 3]
      letters = ["A", "B", "C"]
      for pair in zip(numbers, letters):
          # for 만드는 딕셔너리 이름 in zip(요소1, 요소2)
          print(pair)
      #결과
      (1, 'A')
      (2, 'B')
      (3, 'C')
    


    주의: 리스트는 변형가능하기 때문에 키값이 될 수 없다.

      {["apple","orange"] : "fruit"} -> X
      {2: ["apple", "orange"]} -> O
    


  • 응용 : old_dict의 키 a의 value를 new_dict의 키b의 value로 집어넣자

      new_dict["new key"] = old_dict.pop("old key")
    


  • 직업군별 여성 비율이라는 딕셔너리의 키와 밸류를 이용해서 문장을 출력해보자

      pct_w_in_occupation = {"CEO":28, "Engineer":9, "Physician":40, "Lawyer":37}
      for occupation.percentage in ptc_w_in_occupation.items():
          print("Women make up" + str(percentage)+"percentage of"+occupation+"s")
      #결과
      Women make up 28 percentage of CEOs
      Women make up 9 percentage of Engineers
      Women make up 40 percentage of Physicians
      Women make up 37 percentage of Lawyers
    

    Scrabble 단어게임

    스크래블은 영어 알파벳 블럭을 이용해서 단어를 만들어서 알파벳 블럭마다 주어진 점수를 얻는 게임이다.
    스크래블

    letters=["A","B","C"..."y","Z"]
    points = [1,3,6,... 5,10]
    #A는1점, B는 3점...
    letters_to_point = {
      key:value
      for key, value
      in zip(letters,points)
    }
    #두 리스트를 합쳐서 딕셔너리를 만들었다
    letter_to_points[" "]=0
    #알파벳 없이 비어있는 공간은 0점 처리한다. 
    def score_word(word):
      #점수를 계산하는 함수
      print_total = 0
      for letter in word:
          point_total += letters_to_points.get(letter,0)
          #키 letter의 밸류를 point_total에 더하고, 해당 키 letter 가 없으면 기본값 0을 더한다.
      return point_total
    


응용 : 딕셔너리의 키와 새로운 리스트의 밸류를 매칭

my_dict[key_to_add] = value_to_add
#새로 만드는 딕셔너리[키] = 밸류

예를 들어 설명하자면,

list = {'player1':["BLUE","TENNIS"], 'player2':["WHITE","GAME"]}
#플레이어1은 블루, 테니스라는 단어를 만들었고 플레이어2는 화이트, 게임이라는 단어를 만들었다.
point = {}

for player,words in list.item():
    #리스트의 키, 밸류 값들에 
    player_points = 0
    for word in words:
        #그 중 밸류 리스트 안의 각 단어들의 
        player_points += score_word(word)
        #점수를 계산해서 플레이어별 점수에 더한다

points[player] = player_points
#포인츠라는 새 딕셔너리에 리스트의 키값 플레이어를 키로 가져오고 플레이어별 점수리스트를 밸류로 매칭한다. 

print(points)
#결과
{'player1':29, 'player2':32 ... }
  • 플레이어별 새 단어 추가하기

      def add_word(player, word):
          list[player].append(word)
          #리스트의 해당 키값에 밸류값 워드를 추가한다 
      play_word('player1', "CODE")