Sister Nosilv story

4. Python 응용하기

by 노실언니

*1.프로그래밍 시작하기는 컴퓨터개론Course의 1토픽과 정확하게 일치하여 생략

프로그래밍기초Course

  📺플밍기초 in Python📺 - 🎖수료증

  • 프로그래밍 시작하기-Getting started with python - 📺   📝
  • 프로그래밍 핵심개념-Core concept of python programming - 📺   📝
  • 프로그래밍과 데이터-Python programming and data - 📺   📝
  • Python 응용하기-Making use of python - 📺   📝

*Link : 📺인강  📝정리노트

10년 안에 프로그래밍을 모르면 문맹이 되는 시대가 올 것입니다. 인공지능, 로봇, 사물인터넷, 가상현실, 스마트카 등 다가오는 미래 산업에 프로그래밍을 빼고 말할 수 있는 것은 없습니다. 그렇다면, 어떤 언어로 시작하는 게 좋을까요? 코드잇에서는 파이썬을 가장 추천합니다. 파이썬은 실리콘벨리를 비롯 세계 유수 기업에서 가장 많이 쓰는 언어이며, 미국 대학 상위 39개 컴퓨터 학과에서 선호하는 언어 1위이기도 합니다. 데이터 사이언스, 웹 개발 등 어디 하나 빠지지 않고 쓰이지요. 파이썬과 함께 프로그래밍의 세계에 첫 걸음을 내딛어 보세요.

Python을 배우면서 프로그래밍 자체도 배워보자

 

* 3.프로그래밍과 데이터 keyword정리는 다시 함


Topic 4. Python 응용하기-Making use of python

프로그래밍 문법만 익히고 실제로 활용을 못하는 사람들이 대다수입니다. 원래 프로그래밍은 이론만 갖고 느는 게 아닌데 말이죠. 다양한 상황에 응용을 해 봐야 새로운 상황에 적용하는 능력이 생깁니다.

이 토픽에서는 파이썬을 이용해서 간단한 데이터 분석도 해 보고, 로또 시뮬레이션 프로그램이나 단어장 프로그램을 만들어 볼 것입니다. 그러면서 창의력과 응용력을 모두 기를 수 있습니다.

또한 그냥 기본 문법을 넘어서서, 파이썬을 더 확장성 있게 사용하기 시작할 건데요. 대표적으로는 새로운 모듈을 불러와서 쓰는 것과 유저에게 인풋을 받는 방법을 배워 볼 것입니다.

 

⑴ 모듈 module

① 모듈

- 모듈(module) : 다른 파이썬 파일

# 모듈 : practice.py

def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def multiply(x, y):
    return x * y

def divide(x, y):
    return x / y

- 사용법1) 정통

  └ import 모듈명   # 불러오기

  └ 모듈명.객체명  # 모듈 내 객체사용

import practice             # 같은 폴더 내 모듈 불러오기
print(practice.add(1, 2))   # 모듈명.함수명()

- 사용법2) 약칭추천

  └ import 모듈명 as 약칭

  └ 약칭.객체명

import practice as p        # 추천 : 출처명시
print(p.subtract(1, 2)      # 약칭.함수명()

- 사용법3) 쓸 것만 소환 → 쬐금 추천

  └ from 모듈명 import 객체명1, 객체명2, ···

  └ 객체명1

from practice import multiply, divide
print(multiply(1, 2))       # 함수명() 바로 사용가능
print(divide(1, 2))

- 사용법4) 모두 소환 → 비추천 : WHY) 출처를 알기힘듬

  └ from 모듈명 import *

  └ 객체명1

from practice import *      # 비추
print(multiply(1, 2))       # 해당 함수의 출처를 알 수 없음
print(divide(1, 2))

나의 Choice : ② import 모듈명 as 약칭

 

② stdlib 속 모듈

Standard library(표준라이브러리) : 파이썬 설치 시 딸려오는, 개발자들이 자주 쓰는 기능들을 담은 모듈의 모음

▶ [한글 설명서]

library ⊃ module ⊃ Constants, Functions, Types, Exceptions, etc.

* Built-in : 함수/상수/타입/예외 → 우린 이미 Built-in 된 것들을 사용해왔음!

* Imported : 빌트인이 아닌, 사용자가 따로 import 해야하는 모듈들 ← 앞으로 배울 것

 

a. math

Mathematical functions : This module provides access to the mathematical functions defined by the C standard.

math.log(진수x [,밑])

└ 1 argument, Return 자연로그값 (= ln x )

└ 2 arguments, Return 로그값 (= log밑 진수)

밑변환 log(x)/log(a) 연산을 하므로, 정확도가 떨어짐

math.log2(진수x)

└ 1 argument, Return 밑이 2인 로그값

usually more accurate than log(x, 2)

math.log10(진수x)

└ 1 argument, Return 상용로그값 (= log x)

usually more accurate than log(x, 10)

import math
# 함수 : log(진수[, 밑]) → return (float)지수
print(math.log(256, 4))             # 4.0
print(math.log2(256)/math.log2(4))  # 4.0 : log4(256) 밑변환 되네
print(math.log10(100))              # 2.0
print(math.log2(2**99))             # 99.0

math.sqrt(x)

└ 1 argument, Return the square root of x (=x의 양의 제곱근, 제곱근x)

import math
# 함수 : sqrt(x) → 제곱근x (float)
print(math.sqrt(1024))            # 32.0
print(type(math.sqrt(4)))         # <class 'float'>

math.sin(x)

└ 1 argument, Return the sine of x radians

math.cos(x)

└ 1 argument, Return the cosine of x radians

math.tan(x)

└ 1 argument, Return the tangent of x radians

import math
# 함수 : sin/cos/tan(rad) → float
print(math.sin(0))                # 0.0
print(math.cos(math.pi))          # -1.0 : 코사인180도
print(math.tan(math.pi*(1/4)))    # 0.9999999999999999 : 원래는 1인데

math.pi

└ Constant 파이(π)-The mathematical constant π = 3.141592…, to available precision.

math.e

└ Constant 자연상수e-The mathematical constant e = 2.718281…, to available precision.

import math
# 상수 : 파이 ∏, 자연상수 e → (float)
print(math.e)   # 2.718281828459045
print(math.pi)  # 3.141592653589793
print(type(math.e), type(math.pi))  # <class 'float'> <class 'float'>

 

b. random

Generate pseudo-random numbers - Almost all module functions depend on the basic function random(), which generates a random float uniformly in the semi-open range [0.0, 1.0)

[실수] Real-valued distributions

random.random()

└ 0 argument, Return the next random floating point number [0.0, 1.0) = 0.0 ≤ N < 1.0

import random   # 랜덤한 숫자를 생성하기 위한 다양한 함수들을 담은 module
# 1. random() → return 0.0 ≤ ■ < 1.0인 랜덤한 float 객체
print(type(random.random()))     # <class 'float'>
print(random.random())           # 0.2623734691109664
print(f"{random.random():.2f}")  # 0.71

random.uniform(a, b)

└ 2 argument, Return a random floating point number (a ≤ N ≤<b for a ≤ b, and b ≤ N ≤<a  for b < a)

└ 끝 값을 범위에 포함시킬지의 여부a+(b-a)*random()방정식에 따른 부동소숫점반올림에 의해 결정됨

import random   # 랜덤한 숫자를 생성하기 위한 다양한 함수들을 담은 module
# 2. uniform(a, b) → return a ≤ ■ ≤ b인 랜덤한 float 객체
print(type(random.uniform(-10, 10)))    # <class 'float'>
print(random.uniform(-10, 10))          # 7.090006906596596
print(f"{random.uniform(-10, 10):.2f}") # -7.15

[정수] for integers

random.randint(a, b)

└ 2 arguments, Return a random integer N (a ≤ N ≤ b)

import random   # 랜덤한 숫자를 생성하기 위한 다양한 함수들을 담은 module
# 3. randint(a, b) → return a ≤ ■ ≤ b인 랜덤한 int 객체
print(type(random.randint(-100, 100)))  # <class 'int'>
print(random.randint(-100, 100))        # -91
print(random.randint(-100, 100))        # 17

 

c. decimal

support for fast correctly-rounded decimal floating point arithmetic-float형보다 더 빠르고 정확한 십진수 부동소수점 산술을 지원함

[클래스-객체의 type을 정의하고(어트리뷰트:변수/상수/함수=메소드), 해당 클래스의 객체(인스턴스)를 생성할 수 있음]

decimal.Decimal(■=str···)

└ 1 arguments, 값이 ■인 decimal.Decimal클래스의 인스턴스(객체)를 생성

└ 메소드 : 해당객체.quantize(exp, rounding=None, context=None)

  └ Return quantize(정량화)시킨 새 Decimal 객체-rounds a number to a fixed exponent (원하는 소숫점자리까지 Round it)

  └ 1st argument-exp : exponent(지수)-소수점의 위치 / Decimal형 객체입력-해당 객체의 소수점자리까지

  └ (2nd argument-rounding) : round방식설정1순위 / rounding=■ & 없는 경우, context의 rounding값 / 예 : rounding=ROUND_UP

  └ (3rd argument-context) : round방식설정2순위 / 없는 경우, current context의 설정 값

import decimal
# 반올림한 새로운 객체생성
print(decimal.getcontext().rounding)            # ROUND_HALF_UP : 일반 반올림
a = decimal.Decimal('123.456789')
print(a.quantize(decimal.Decimal('1.')))        # 123 : current context 대로
print(a.quantize(decimal.Decimal('.1'), rounding='ROUND_UP'))       # 123.5 : 올림
print(a.quantize(decimal.Decimal('.01'), rounding='ROUND_DOWN'))    # 123.45 : 내림
print(a.quantize(decimal.Decimal('.001')))      # 123.457 : current context 대로

decimal.getcontext()

└ 역할 : 현재 설정 확인 및 변경 → 자세한 설명서

└ 0 arguments, Return 현재 상황이 담긴 객체-the current context for the active thread

└ print(■)→ Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

└ 변경방법 : 해당객체.변경항목 = 변경값

 └ 변경값 : rounding = 'ROUND_HALF_UP'반올림/'ROUND_UP'올림/'ROUND_DOWN'내림/'ROUND_HALF_EVEN'(.5 → 짝수), etc.

import decimal
a = decimal.getcontext()    	# Alias - 간편?
print(a)    # 설정확인 : Context(prec=28, rounding=ROUND_HALF_EVEN, Emin= ···)
print(type(a.rounding))         # <class 'str'>
a.rounding = 'ROUND_HALF_UP'    # 반올림으로 설정변경 & str형으로 입력해야함
# round() VS Decimal형 객체.quantize()
print(round(13.5))  # 14 : ROUND_HALF_EVEN방식→올림 : 반올림인데,
print(round(13.4))  # 13 : ROUND_HALF_EVEN방식→버림 : 0.5인 경우는 (반)
print(round(12.5))  # 12 : ROUND_HALF_EVEN방식→버림★: 결과가 짝수이도록 올/내리는 방식

import decimal
a = decimal.Decimal('13.5')  # Decimal클래스의 객체(instance)생성
b = decimal.Decimal('12.5')  # 인수는 int/float/str/tuple형 다 되는데, str 추천
print(type(a))               # <class 'decimal.Decimal'>

print(decimal.getcontext().rounding)    # 현 설정 : ROUND_HALF_EVEN
c = a.quantize(decimal.Decimal('1.'))   # 현 설정대로 rounding한 새로운 객체
d = b.quantize(decimal.Decimal('1.'))   # 현 설정대로 rounding한 새로운 객체
print(c)        # 14 ← 13.5
print(d)        # 12 ← 12.5 ★

decimal.getcontext().rounding = 'ROUND_HALF_UP'     # 설정변경 : 일반 반올림
c = a.quantize(c)   # c의 소숫점자리대로 + 현 설정대로 rounding한 새로운 객체
d = b.quantize(d)   # d의 소숫점자리대로 + 현 설정대로 rounding한 새로운 객체
print(c)        # 14 ← 13.5
print(d)        # 13 ← 12.5 ★

d. os

This module provides a portable way(이식가능한 방법) of using operating system dependent functionality(운영체제에 종속된 기능).

os.getlogin()

└ Return (str) 현 프로세스의 제어 터미널에 로그인한 사용자 '이름'-the name of the user logged in on the controlling terminal of the process.

os.getcwd()

└ Return (str) 현 작업 디렉토리-a string representing the current working directory.

import os       # 운영체제를 조작하기위한 모듈
# getlogin() → 현재 로그인 되어있는 계정
print(os.getlogin())    # 계정명 출력
# 현재 파일이 있는 경로 출력
print(os.getcwd())      # C:\ 블라블라 출력
print(type(os.getlogin()), type(os.getcwd()))   # <class 'str'> <class 'str'>

 

e. datetime

날짜와 시간을 다룰 수 있는 클래스 & 산술 - This module supplies classes for manipulating dates and times.

+ Aware objects-can locate itself relative to others, represent a specific moment in time without interpretation.

+ Naive objects-up to the program, easy to understand and work with.

[클래스-객체의 type을 정의하고(어트리뷰트:변수/상수/함수=메소드), 해당 클래스의 객체(인스턴스)를 생성할 수 있음]

[* Object of these type is immutable]

datetime.date(year, month, day : int형)

└ 날짜(연, 월, 일)만 다루는 객체를 정의하는 클래스

└ 3 arguments, 해당 값들을 attribute로 가진 datetime.date클래스의 인스턴스(객체) 생성

└ 클래스 메소드 : date.today()

  └ Return 현재 날짜값들을 attribute로 가진 datetime.date클래스의 인스턴스(객체)

└ 인스턴스 메소드 : 특정객체.replace(year=self.year, month=self.month, day=self.day)

  └ Return 해당 객체의 특정 attribute를 바꾼 새로운 datetime.date클래스의 인스턴스(객체)

└ 인스턴스 메소드 : 특정객체.strftime(format="···")

  └ Return 해당 객체의 날짜관련attribute를 명시한 포맷에 맞춘 문자열(string from time)

datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

└ 시간(시, 분, 초, ···)만 다루는 객체를 정의하는 클래스

└ All optional arguments, 해당 값들을 attribute로 가진 datetime.time클래스의 인스턴스(객체) 생성

└ 인스턴스 메소드 : 특정객체.replace(hour=self.hour, minute=self.minute, second=self.sec···)

  └ Return 해당 객체의 특정 attribute를 바꾼 새로운 datetime.time클래스의 인스턴스(객체)

└ 인스턴스 메소드 : 특정객체.strftime(format="···")

  └ Return 해당 객체의 시간관련attribute를 명시한 포맷에 맞춘 문자열(string from time)

datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

└ 날짜와 시간을 모두를 다루는 객체를 정의하는 클래스

└ 3↑ arguments, 해당 값들을 attribute로 가진 datetime.datetime클래스의 인스턴스(객체)를 생성

└ 클래스 메소드 : datetime.now(tz=None)

  └ Return 현재 날짜와 시간을 attribute로 가진 datetime.datetime클래스의 인스턴스(객체)

└ 클래스 메소드 : datetime.combine(date, time, tzinfo=self.tzinfo)

  └ Return 입력한 date객체와 time객체의 각 attribute값을 결합한 datetime.datetime클래스의 인스턴스(객체)

└ 인스턴스 메소드 : 특정객체.strftime(format="···")

  └ Return 해당 객체의 날짜시간관련attribute를 명시한 포맷에 맞춘 문자열(string from time)

  * 포맷코드 : 연%Y,y 월%B,b,m 일%d 요일%A,a,w 오전오후%p 시%H(24h),I(12h) 분%M 초%S

  └  Appropriate representation : %c → Tue Aug 16 21:30:00 1988  %x → 08/16/88  %X→21:30:00

  └ * 메소드 사용하지않고, 문자열포멧팅 "문자와 포멧코드".format(시간관련 인스턴스)로 하는 것도 괜찮은데...

import datetime

now = datetime.datetime.now()     # 현재 연월일시분초를 담은 datetime.datetime 인스턴스

print("Today is " + now.strftime("%A(%B %dth)"))        # Today is Thursday(June 10th)
print("Today is {0:%A}({0:%B} {0:%d}th)".format(now))   # Today is Thursday(June 10th)
print(now.strftime("%c"))   # Thu Jun 10 15:40:40 2021 = 요일 월 일 시:분:초 연
print(now.strftime("%x"))   # 06/10/21  = 월/일/연
print(now.strftime("%X"))   # 15:40:40  = 시:분:초

└ 지원하는 연산 : datetime = datetime ± timedelta

└ 지원하는 연산 : timedelta = datetime - datetime

datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0:int, float, +, -)

└ 두 객체(date, time, datetime클래스)의 차이기간을 의미하는 객체(인스턴스)를 다루는 클래스

└ All optional arguments, 해당 값들을 attribute로 가진 datetime.timedelta클래스의 인스턴스(객체) 생성

└ 지원하는 연산 : datetime = datetime ± timedelta

└ 지원하는 연산 : timedelta = datetime - datetime

import datetime

# .datetime(연, 월, 일, 시, 분, 초)
print(type(datetime.datetime(2021, 5, 28))) # <class 'datetime.datetime'>
print(datetime.datetime(2021, 5, 28))       # 2021-05-28 00:00:00
print(datetime.datetime(2021, 5, 28, 15, 28, 9))    # 2021-05-28 15:28:09

# 객체의 attribute :
today = datetime.datetime.now()
print(type(today.year))         # <class 'int'>
print(today.year)               # 2021
print(type(today.microsecond))  # <class 'int'>
print(today.microsecond)        # 543286

# 객체의 method : .datetime.now() → return 현재
print(type(datetime.datetime.now()))        # <class 'datetime.datetime'>
print(datetime.datetime.now())              # 2021-05-28 15:29:08.860917 : 시간단위
first_delta = datetime.timedelta(
	days=48,
	seconds=16,
	microseconds=10,
	milliseconds=19000,
	minutes=1,
	hours=2,
	weeks=3
    )
  second_delta = datetime.timedelta(weeks=1, hours=3, minutes=4, seconds=5)

  # datetime객체끼리 빼기 → 시간차를 나타내는 timedelta객체
  dday = datetime.datetime(2021, 6, 1)
  today = datetime.datetime.now()
  print(type(dday - today))               # class 'datetime.timedelta' 시간차
  print(dday - today)                     # 3 days, 8:28:28.426436

  # datetime객체+-timedelta객체 → datetime객체
  print(datetime.datetime.now())                  # 2021-05-28 15:44:54.264421
  print(type(datetime.datetime.now() + second_delta))   # class 'datetime.datetime'

  # 설정하지 않은 항목은, default to 0

+ 객체, 변수함수클래스, 식별자에 대한 내식대로 정리

[All]Object : library[폴더📂] ⊃ module[파일📒] ⊃ object[體] ← class[틀]

▶ [[體] Entity독립체(포괄적)Data데이터(컴퓨터)Object객체(추상물) ↔ Identifier식별자(이름) ← Programmer]

Entity독립체(포괄적) : 다른 것에 기대지 않고 홀로 서 있는 형체나 상태

Data데이터(컴퓨터) : 프로그램 내 존재하는 표현 가능한 모든 독립체(entity)

Object객체(추상물) [넓은의미] 파이썬이 Data데이터추상화 한 것 ∴파이썬의 모든 것이 객체

          [좁은의미] 특정 Class가 정의한 대로 만들어져 구체적 메모리주소를 할당받은 실체인 Instance

               (instance의 일반적 의미인 '사례'도 특정 논리 틀에 찍혀나온 '썰')

└ + [名] Identifier식별자 : ≒ Object's name, Programmer can access object by using identifier - 식별자(Identifier) point → 객체(object)

 ∴ Var Func Class ⊂ 넓은 의미의 Object

 ∴ Var Func Class ⊄ 좁은 의미의 Object, 단순하게 Object를 가리키는 '식별자'

그래서, 변수함수클래스가 가리키는 Object도 변수함수클래스라고 혼용하기도 하고, 그 경우 Object의 식별자를 변수함수클래스'명'이라고 하는 것 같다.

이걸 제대로 알려면, 파이썬 인터프리터뜯어서 금이빨빼고 모조리 씹어먹어야 알 것 같은데 난 그럴 역량이 안 되고, 씹어먹은 사람에게 접근하는 것도 불가능인듯하여

내 결론(1) : 변수함수클래스는 Object를 가리키는 식별자이자, 객체이자, 식별자가 가리키는 객체이기도 하다라고 여기면 타인과의 원활한 의사소통'은' 가능하겠다.

가장 돌아버리겠는 포인트가 있었다.

▶배경지식1. [人 call 名 → 體 come 人]

 └ [體] Object객체 : 파이썬이 데이터를 추상화한 독립적 실체 ⊃ 변수/함수/클래스

 └ [名] Identifier식별자 : object's name, 프로그래머는 식별자를 통해 특정 객체에 접근

▶배경지식2. [Variable → 體]

 └ [→] Variable변수 : 객체를 가리키는 것

◆[충돌 포인트] 名→體 + V→體 = 名 = V ?

 └ 변수가 객체를 가리키는 이름(식별자)이란 말인가? 그럼 변수명은 또 뭐야? 변수 자체가 식별자인데.......

 

[도움 받은 글, 일부 인용]

'이제부터 메모리 주소를 대표하는 이름 내지 라벨을 줄여서 '변수variable'라고 부르려고 합니다.

메모리 주소를 채우는 데이터 내용은 변할 수 있기 때문에 이렇게 부르는 것이지

것은 본질적으로 주소를 뜻하는 것이며 결코 어떤 수(number)가 아닙니다.

따라서 '변수'는 일종의 오역입니다. 그래서 대신 식별자identifier라는 말을 사용하는 사람도 많습니다.'

[도움 받은 답변]

1) 변수를 식별자라고 할 순 없다 → 2) 맞는 말이다 → 3) 그냥 이 부분에 대해 집중하지않는게 좋다 (...) 

 

명확하게 -이다! 라고 말하는 사람과, 말이 첫 생각과 끝 생각이 다른 사람과, 그걸 지켜보는 나는 어떻게 해야할지모르겠네ㅔㅔㅔㅔ

혼란스러운 답변이었지만, 이런 모호하면서도 실무적이지 않은 부분에 초심자가 시간을 할애할 필요가 없는 것은 맞는 말이다.

그래서! 어떻게 덮고 넘어가기로 했냐면, 혼용하기로 했다 ^0^.... 변/함/클:객체를 가리키는 이름∪가리킴 받는 객체

 

▶ [Data 추상(추출) → Object객체(추상물)] 추출물 구성 ⊃ Identity Type Value

└ [주소] Identity : 메모리 내 주소

└ [] Type : 특정 객체들만이 가지는 특징으로 Type에 의해 객체의 동작 및 처리방식이 달라짐 ← 'Class'

└ [] Value : ㄹㅇ 값 ← Type이 해당 객체가 담을 수 있는 값을 결정

* 해당 객체의 주소, 형, 값은 객체 생성 후 바꿀 수 없다.

* 넓은 의미의 객체를 생각하면, 이 모든 추출물들도 객체다.

* Class → 형Type 정의

def add(x, y):
    return x + y


print(type(print))        # <class 'builtin_function_or_method'>
print(type(print('hi')))  # <class 'NoneType'>
print(type(add))          # <class 'function'>
print(type(add(2, 3)))    # <class 'int'>
# 그것이 type( )을 하는데, class' '라고 나오는 이유?

* id( ) 함수 → Return [ 입력받은 객체의 Identity를 '정수'로 표현한 값 ]

* < is > 이항연산자 → Return [ 두 객체의 Identity가 같은지를 비교한 후 True or False ]

* < == > 이항연산자 → Return [ 두 객체의 Value가 같은지를 비교한 후 True or False ]

* type( ) 함수 → Return [ 입력받은 객체의 Type/Class]

 

▶ [Object객체] ⊃⊅ Variable변수 Function함수 Class클래스

* 123D는 나 생각하기 좋으라고 달아놓은 태그, 변수-함수-클래스가 약간 변수⊃함수⊃클래스 같아서 점-선-평면-입체 느낌을 받는다. 이건 int float bool → str list 배울 때 받은 느낌과 비슷

└ [1D] Variable 변수 → 객체

    [넓은 의미] 가리키는 객체를 바꿀 수 있는 식별자 or 그 객체 ↔ 상수Constant : 파이썬에서 상수는 개념적으로만 존재한다.(전부 대문자인 식별자)

    [좁은 의미] 1D : 우리가 배운 일반적인 type인 int, float, string, bool, list, tuple, dict, set형 객체를 가리키는 식별자 or 그 객체

    내 결론(2) : 변수는 [넓] 가리키는 객체가 바뀔 수 있는 식별자이자 그 객체이면서도, [좁] 해당 객체를 1D로 제한하면 편하다

└ [2D] Function 함수객체 = 특정 task를 수행하는 코드들이 담긴 하나의 모듈

    함수 → return 함수자체 Ex. <function add at 0x0000019B152BCDC0>

    함수(■) → return 명령실행 후의 객체 (객체입력받음 → 명령실행 → return 객체)

└ [3D] Class 클래스객체 = 특징을 정의하고 해당 특징을 가진 객체(instance)를 생성하는 모듈

    * 특징을 정의한다? 해당 클래스의 객체라면 가져야 할 attribute 속성(변수상수함수)을 만들어놓음 → '객체.어트리뷰트'로 사용가능

     Instance⊂객체(특정 클래스 type)attribute(속성)⊂변수,상수,함수(클래스/인스턴스가 가져서 . 으로 불러낼 수 있는), method⊂함수

     Attribute(속성)⊂변수,상수,함수(클래스/인스턴스가 가져서 . 으로 불러낼 수 있는)

     Method⊂함수

    클래스 → return 클래스자체

    클래스(■) → return 해당 클래스의 객체 = 인스턴스instance

    클래스/객체.어트리뷰트 → return 클래스/인스턴스에 종속되어있는→어트리뷰트

    * 함수/클래스는 '접근해'느낌이고, 함수/클래스(■)는 접근해+'실행해!' 느낌

 

내 결론(1) : 변수함수클래스는 Object를 가리키는 식별자이자, 객체이자, 가리킴 받는 객체이기도 하다라고 여기면 타인과의 원활한 의사소통'은' 가능하겠다.

결론(1)은 그렇지만, 내 마음 속에서

'함수'는 특정 명령을 수행하는 코드덩어리 '객체'

'클래스'는 type을 정의하고 해당 type의 객체를 만드는 코드덩어리 '객체'로 즉, 식별자가 가리키는 '객체'라는 느낌이 더 강하다.

정의가 def 함수명(■): 혹은 class 클래스명()으로 명확하고, 코드 내용물의 역할이 명확해서 이건 함수다 이건 클래스다 딱 말할 수 있기때문이다.

그러나, 변수는 아니다. 함수/클래스와 달리 '변수'는 객체보다는 '식별자'같다. 혹은 어떤'體' 보다는 식별자→변하는 객체 사이의 '관계'를 지칭하는 것 같기도 하다

왜냐하면, 변수는 말 그대로 객체가 변해야하니까...?

변하는 '객체'를 변수라고 할 수가 없으니, 고정되어 있는 '식별자'를 변수라고 말하게 되는 것이다.

일상 속에서 예를 들자면, 함수/클래스는 특정한 메뉴얼BOOK의 느낌 ↔ 변수는 단축키F10에 등록한 '옷 예쁘다'라는 매크로채팅 속의 '옷'이다. 청자에 따라서 '옷'은 달라진다.

 

'그래 그럼, 변수를 식별자라고 하자!' 변수 → 객체 라고 하면, 식별자 → 객체의 관계 중에서 변수(식별자) → 함수or클래스(객체)인 상황에 마주친다

함수를 정의한 후, ①변수 = 함수명 ②변수() 이렇게 하면, 정말루 함수객체를 다룰 수 있게 된다. 변수=클래스도 마찬가지다

심지어, 함수를 가리키는 식별자인 함수명 = 값이 5인 int형 객체도 가능하다. 그럼 더 이상 그 식별자는 함수명이라고 부를 수 없고, 변수라고만 부를 수 있다.

함수명, 클래스명은 다 변수인 것이다.... → 그럼 어쩔

그래서, 객체를 넓은의미/좁은의미로 나누어 생각한 것처럼 변수도 [넓은]식별자or변하는관계, [좁은]특정type만으로 나누는게 좋겠다고 생각했다.

변수의 넓은 의미에 의하면, 함수이나 클래스를 가리키는 식별자(혹은 ●●명)도 변수다. 근데 그렇게만 생각하면 너무... 다 변수잖아.... 다 객체인 것처럼...

그래서 좁은 의미의 변수는 int~set까지의 특정 타입(1D)을 가리키는 식별자와 그 변할 수도 있는 객체만으로 제한했다.

내 결론(2) : 변수는 [넓] 가리키는 객체가 바뀔 수 있는 식별자이자 그 객체이면서도, [좁] 해당 객체를 1D로 제한하면 편하다

 

[+ 의문] 일단 이렇게 덮긴하는데, list의 item들은 식별자 → 객체 사이가 아니어도 한 item객체가 다음 item객체를 가리키잖아? '객체 → 객체'도 있나...? 그렇다면 식별자→객체랑 뭐가 다를까...?


      # 식별자 → 다양한 객체

      a = 5                   # 변수 정의


      def add(x, y):          # 함수 정의
      return x + y


      class Add():            # 클래스 정의
      five = 5

      def ret_five(self):
      return self

      # 1. <변수> 식별자 a → '객체'의 type/value/identity 조사
      # Type:<class 'int'> / Value: 5 / Id:2053288782256)
      print(type(a))  # Type : <class 'int'>
      print(a)        # Value : 5
      print(id(a))    # Identity : 2053288782256

      # 2. <함수> 식별자 add → '객체(명령모음)'의 type/value/identity 조사
      # Type:<class 'function'> / Value:<function add at 0x000001DE11AECD30> / Id:2053291035952)
      print(type(add))        # Type : <class 'function'>
      print(add)              # Value : <function add at 0x000001DE11AECD30> → Re-run 할 때마다 변함
      print(id(add))          # Identity : 2053291035952 → Re-run 할 때마다 변함
      print(a == add)         # Value 비교 : False (다름)
      print(a is add)         # Identity 비교 : False (다름)

      # 3. <함수()> 식별자 add() → '객체(명령수행 후 리턴한)'의 type/value/identity 조사
      # Type:<class 'int'> / Value:5 / Id:2053288782256)
      print(type(add(2, 3)))  # Type : <class 'int'>
      print(add(2, 3))        # Value : 5
      print(id(add(2, 3)))    # Identity : 2053288782256
      print(a == add(2, 3))   # Value 비교 : True (같음)
      print(a is add(2, 3))   # Identity 비교 : True (같음)
      # >>> a가 가리키는 객체와 add(2, 3)가 리턴한 객체는 같은 객체

      # 4. 가리키는 객체 바꿔보기(1)
      a = add         # a → (int형 객체 → 함수형 객체)
      print(type(a))  # Type : <class 'function'> ← <class 'int'>
      print(a)        # Value : <function add at 0x000001DE11AECD30> ← 5
      print(id(a))    # Identity : 2053291035952 ← 2053288782256
      print(a == add)   # Value 비교 : True (같음)
      print(a is add)   # Identity 비교 : True (같음)
      # remark>>> 함수의 식별자가 a로 바뀌었대도, Value는 function add 라고 함

      print(type(a(2, 3)))  # Type : <class 'int'>
      print(a(2, 3))        # Value : 5
      print(id(a))          # Identity : 2053288782256
      print(a(2, 3) == add(2, 3))   # Value 비교 : True (같음)
      print(a(2, 3) is add(2, 3))   # Identity 비교 : True (같음)
      # >>> a가 가리키는 객체와 add가 가리키는 객체는 같은 객체 → a()도 정상적으로 작동
      # >>> 깔끔하게 a는 '식별자'라고 하는게 좋겠다.
      # >>> 다만, 식별자가 자신이 가리키는 객체를 바꿀 수 없다면 상수 → 그 반대의 개념이 변수인 셈

      # 5. 가리키는 객체 바꿔보기(2)
      add = 5           # add → (함수형 객체 → int형 객체)
      print(type(add))  # Type : <class 'int'> ← <class 'function'>
      print(add)        # Value : 5 ← <function add at 0x000001DE11AECD30>
      print(a)          # Value : <function add at 0x000001DE11AECD30>
      print(id(add))    # Identity : 2053288782256 ← 2053291035952
      # >>> add는 함수형 객체를 가리키다가 int형의 값이 5인 객체를 가리키게 되었다
      # >>> 그래도, function add 라는 value값은 바뀌지 않음

      # 6. 클래스도 동일한가?
      print(Add)              # 클래스 : <class '__main__.Add'>
      print(type(Add))        # <class 'type'>

      print(Add())            # 객체 : <__main__.Add object at 0x000001FC170FCD90>
      print(type(Add()))      # <class '__main__.Add'>
      print(Add.ret_five)     # 함수 : <function Add.ret_five at 0x00000232F7BECDC0>
      print(Add().ret_five)   # 메소드 : <bound method Add.ret_five of <__main__.Add object at 0x000002E5BF83CD60>>

      a = Add                 # 가리키는 객체를 바꿔보기
      print(a)                # 클래스 : <class '__main__.Add'>
      print(a())              # 객체 : <__main__.Add object at 0x00000229F97FCD60>
      print(a().five)         # 객체.객체 : 5
      # >>> 동일하게 작동

 

⑵ 사용자 입력받기 : input(■)

- Console을 통해 사용자로부터 정보를 받아 활용 ↔ 개발자가 모든 동작을 결정

- Function : input("■"=str)

1. [출력] 문자열 파라미터 ■ 콘솔출력 : ■는 무엇을 입력해야할지 안내하는 용도로 사용

2. [인풋] 사용자로부터 입력받아 - 사용자는 입력 후 Enter

3. [리턴] return (str) 입력받은 값을 value로 하는 str형 객체

str1 = input("String: ")
print("5회 :", str1*5)

int1 = int(input("Integer: "))
print("5회 :", int1*5)

"""
[결과]
String:     String: 1       String: 1
            5회 : 11111     5회 : 11111
            Integer:        Integer: 1
                            5회 : 5
"""

- 실습:숫자 맞히기 게임

실습과제-숫자 맞히기 게임

+ Function 전체종료 : exit()

"""
1. [반복] 기회 있니 없니 → While 기회가 있는 동안:
    2. [제어] 정답VS입력 ①같니 ②크니 ③작니
"""
from random import randint

coin = 4                 # 기회
target = randint(1, 20)  # 정답

# 1. [반복]
while coin != 0:    # 기회가 있는 동안:
    answer = int(input(f"남은 기회{coin}: pick [1, 20]→"))
    # 2. [제어]
    if target == answer:    # ①정답이면
        print(f"축하! {5 - coin}번 만에 맞힘!")
        exit()                  # 전체 종료
    elif target > answer:   # ②답이 더 크면
        print("Up")
        coin -= 1
        continue                # while 조건확인
    else:                   # ③답이 더 작으면
        print("Down")
        coin -= 1
        continue                # while 조건확인

# -1. [반복종료] 기회 없음
print(f"기회없음, 정답 : {target}")

* 나올 수 있는 case 5 : '축하1~4번만에~' + '기회없음'

 

⑶ 파일 읽고 쓰기

with open('폴더명/파일명', 'r=읽기 or w=쓰기', 'encoding=인코딩방식') as 결과물명:

[안은문장] with EXPRESSION as TARGET:

└ open()으로 파일을 여는 경우, 해당객체.close()로 파일 닫기도 해주어야 함[불편] → [해결]with문 사용시, 구역을 벗어나면 자동으로 파일을 닫음

with EXPRESSION as TARGET:
	SUITE

 [안긴문장] open(file, mode='r', buffering=-1, encoding=None, ···)  *kor설명

 └ return, 파일과 상응하는 객체:Open file and → return a corresponding file object(=file-like objects, streams)

 └ ① file : 열려는 파일의 주소(path-like object) → 예:같은 폴더-'파일명.종류' 다른 폴더-'폴더명/파일명.종류'

 └ ② mode : 해당 파일을 여는 방식 - 기본모드 'r' & 't'

[mode 설명] * 출처: https://docs.python.org/3/library/functions.html#open & https://twpower.github.io/17-with-usage-in-python

 └ ④ encoding : 텍스트 모드('t')가 들어가는 경우, 파일을 인코딩/디코딩하는 방식 - 기본값 'ASCII' → 자주 쓰는 값'UTF-8'

 └ 관련함수 : 특정객체.read()

  └ Return (str) 해당 객체의 내용 전체를 변환한 문자열-읽은 영역 휘발

with open('data/chicken.txt', 'r', encoding='UTF-8') as txt:
    print(txt.read())
    """
        1일: 815400
        2일: 798000
        3일: 269200
             :
    """
    print(type(txt.read()))  # <class 'str'> : 다 읽고 남은 ''을 확인한 것
# 두 명령을 바꾸면, 아무것도 출력되지않음 → type 확인할 때, 다 읽고 휘발되어서

 └ 관련함수 : 특정객체.readline()

  └ Return (str) 해당 객체를 한 줄씩을 변환한 문자열-읽은 영역 휘발

with open('data/chicken.txt', 'r', encoding='UTF-8') as txt:
    print(type(txt.readline()))  # <class 'str'> : '1일: 815400\n' 확인
    print(txt.readline())        # 2일: 798000\n
    print(txt.readline())        # 3일: 269200\n

 └ 관련함수 : 특정객체.readlines()

  └ Return (list) 해당 객체의 한줄한줄을 각각의 item으로 한 리스트-읽은 영역 휘발

with open('data/chicken.txt', 'r', encoding='UTF-8') as txt:
    print(txt.readlines())        # ['1일: 815400\n', '2일: 798000\n', '3일: ···]
    print(type(txt.readlines()))  # <class 'list'> : list=[] 확인
# 두 명령을 바꾸면, txt.readlines() → list=[] 왜냐하면, type확인할 때 다 읽고 휘발됨

- 읽는 용도로 wrap된 객체를 사용하면, 사용한 줄만 휘발되는 것이 신기했다 → .readline()의 존재의의가 느껴짐

 

① 파일읽기 → open('mode=r')

- 1. 읽기에 필요한 '치킨집 매출.txt' 만들어보기

# [치킨집 매출 리스트 만들기]
import random

for i in range(1, 31, 1):
    print(f"{i}일: {random.randint(1000,9999)*100}")

- 2. 읽는 용도로 wrap된 객체, 콘솔에 출력하기

└ [문제] 개행(enter, \n)의 중복 : 문서 자체의 개행뿐만 아니라 print()도 개행을 하는 바람에 두 줄 띄어짐

# 1. 그냥 print :
with open('data/chicken.txt', 'r', encoding='UTF-8') as txt:
    for line in txt:         # 한 줄 : "문자열1··\n"
        print(line)          # + print의 개행
"""
1일: 815400

2일: 798000

3일: ···
"""

└ [해결1.] 문서 자체의 개행 제거 → 문자열.rstrip() : "", "\n", "\t"같은 모든 공백(whitespace)제거

# 2. 문자열.공백제거() - 공백 中 우측만 제거
with open('data/chicken.txt', 'r', encoding='UTF-8') as txt:
    for line in txt:		  # 한 줄 : "문자열1··\n"
        print(line.rstrip())  # 오른쪽 공백제거
"""
1일: 815400
2일: 798000
3일: ···
"""

└ [해결2.] print()의 개행 제거 → end=""

# 3. print 개행 무시 :
with open('data/chicken.txt', 'r', encoding='UTF-8') as txt:
    for line in txt:		 # 한 줄 : "문자열1··\n"
        print(line, end="")  # print()의 공백제거
"""
1일: 815400
2일: 798000
3일: ···
"""

사용한 것 정리+α

문자열.lstrip/rstrip/strip()

왼쪽/오른쪽/양쪽에 존재하는 whitespace( "", "\n", "\t")를 제거해주는 메소드

└ Return, (str) 해당 문자열의 공백을 제거한 새로운 문자열

문자열.split('□')

해당 문자열을 □을 기준으로 나눈 후, 각각을 item으로 하는 리스트를 생성하는 메소드

└ 0 argument Return, (list) 해당 문자열을 모든 종류의 공백을 기준으로 나눈 리스트

└ 1 argument Return, (list) 해당 문자열을 □을 기준으로 나눈 리스트

my_string = "1, 2, 3"           # 숫자 + 컴마 + 공백
print(my_string.split(","))     # 컴마로 나눔 → item = 숫자 / 공백 + 숫자
# ['1', ' 2', ' 3']
print(my_string.split(", "))    # 컴마 + 공백 으로 나눔 → item = 숫자
# ['1', '2', '3']

full_name = "Kim, Yuna"
print(full_name.split(","))         # ['Kim', ' Yuna']
print(full_name.split(", "))        # ['Kim', 'Yuna']
name_data = full_name.split(", ")
print(name_data[1], name_data[0])   # Yuna Kim

white_space = "  \n\n  1  \t  2  \n  3 4 5  \n\n"     # whitespace의 향연
list1 = white_space.split()         # 인자를 넘겨주지않으면, 모든 공백기반으로 나눔
# ['1', '2', '3', '4', '5']
print(list1[0] + list1[4])              # 211   → items = 숫자모양의 문자str
print(int(list1[0]) + int(list1[4]))    # 6     → 형변환 int(■)

end="□"

└ print(■)에 사용할 수 있는 인자 : print()의 개행을 하지말고, □를 붙일 것

 

- [ for ☆ in ■■ ] 의 ■■로 쓸 수 있는 객체들

1. range(시작, 끝+1, 공차) - <class 'range'>

2. 딕셔너리객체.items/keys/values() - <class 'dict_···'>

new 3. open( ) → 한 줄씩 ☆가 되는 반복문(≒.readline)

 

- 실습:코딩에 빠진 닭

문제내용
모범 답안 ↔ 내 답안

- open()사용시, 모드 'r', 't'는 default 모드니까 안 적었다.

- open()사용시, encoding="UTF-8"로 변경해주지않으면 오류가 났다.

 └ UnicodeDecodeError: 'cp949' codec can't decode byte 0xec in position 1: illegal multibyte sequence

- sum()는 혹시? 했는데 되네;;;;;;;;

- dict로 만든이유는 len(□)을 사용해서 확장성있는 코드로 만들고 싶었기때문이다.

 list형으로도 괜찮았는데, 기왕이면, n일-매출액 이렇게 페어를 맞추고 싶어서 dict로 했다.

 그런데 지금 생각하니까! 어차피 (index+1)일이니 list여도 괜찮았겠다.  

with open("data/chicken.txt", encoding="UTF-8") as sales:
    line_dict = dict()
    
    for line in sales:
        line_list = line.split(': ')
        line_dict[line_list[0]] = int(line_list[1])
    average = sum(line_dict.values()) / len(line_dict)
    print(average)      # 501916.12903225806 [=정답]

 

② 파일쓰기 → open(mode='w').write()

wrap된객체.write('ㅁ')

해당 객체에 입력받은 값을 기록해주는 메소드

- 손수 개행('\n')을 해주어야 함

- 기존 파일에 덧붙이고 싶은 경우, open('mode=a').write → append(덧붙임, 첨부)

 

- 실습

1. 단어장 만들기

과제
내 답 ↔ 모범답안 : [문자열 포멧팅]

- 누적형 단어장 mode='a' ↔ 새로운 단어장 mode='w'

- 영단어 입력+반영 → 한글뜻에서 quit하면, 이미 입력한 영단어를 지우고 닫아야 프로그램을 다시 돌려도 꼬임이 없는데 이미 기록된 자리를 지우는 법은 모름 킈

 └→ 모범답안도 마찬가지로 둘 다 quit 안 된 경우, 한 쌍으로 동시에 입력함

- 문자열포멧팅을 자꾸 print(□)에서만 사용해서 그렇지, 문자열을 사용하는 글.write(□)에서도 당연히 OK

 └ vocab.write(f"{eng}: {kor}\n")

- [무한반복] while True → [셀프종료] 모든 경우의 수에서 必 break

with open("data/vocabulary.txt", 'a', encoding='UTF-8') as vocab:
    while True:                     # 반복
        eng = input("영어 단어: ")
        if eng == 'q':
            break

        kor = input("한국어 뜻: ")
        if kor == 'q':
            break

        vocab.write(f"{eng}: {kor}\n")

 

2. 단어 퀴즈

실습문제와 결과
내 답 ↔ 모범답안

- while true, .readline 필요없음 → for (1_line) in (wrap된 객체)

 

3. 고급 단어장

문제, 예시동작

 

내 답안 ↔ 모범답안

- 나 : random으로 뭘 사용해야할 때는 list가 더 편한 것 같음 - index가 숫자니까

- 답 : 단어장이 dict형식이니까 list(dict.keys())에서 random을 사용한 후에, dict[key] = value

 

* 프로젝트: 로또 시뮬레이션

프로그램 전체 설명

1.

1. 번호뽑기 Function : 거의 n = 1 or 6

- 서로 다른 n개 뽑기 = 조합 중복조합 ∴ set type 사용이 가장 합리적

 └ list형+n회append : 중복됨 - X

 └ list형+중복제거+len()=n체크+append : 중복제거+list = set type [모범답안]

 └ set형+len()=n체크+add : OK [내 답안]

+ 밤샌 다음 날 졸면서 한 삽질ㅋㅋㅋ

 

2.

2. 당첨로또정하기 Function

- 정렬된 6개+Bonus1

 └ 6개뽑아서 정렬+중복체크+1개뽑기 : [내 답안]

 └ 7개뽑기+6개정렬 : OK [모범답안] → 그렇네? ㄷㄷㄷ generate_numbers에서 중복을 제거해주니까

 

3.

3. 두 리스트 사이 겹치는 번호의 갯수 알려주는 Function

- 졸던 나를 힘들게 한, TypeError: argument of type 'int' is not literable

 └ TypeError: for win in winning_lotto[6]  ∵ int형은 in □의 □로 사용할 수 없음( not literable )

 └ 받은 함수로 해결(1) : if int, list형변환

 └ 줄 때부터 list로 해결(2) : winning_lotto[6:] ← winning_lotto[6]  ∵ indexing[]=intslicing[:]=list

   아, 인덱싱은 int형, 슬라이싱은 list형으로 반환한다는 걸 몰랐네..

 └ in □을 사용하지 않게 해결실패(3) : len(set형변환 + 교집합) 그렇지만, WOW ★

 └ 결론 : (2) 줄 때부터 list (3) in □ len(set+교집합)

   진짜 정보교류의 장은 중요한 듯, 알린 사람: 자기愛, 보람 + 1 & 알게된 사람: 놀라움, 시원함, 분노 + 1

 

4.

4. 당첨된 액수 알려주는 Function

- 줄줄이 if-elif-else VS list

 └ list를 고른 이유 : 영혼의 끌림 & 6이야? 5에다가 보너스야? 5야? 4야? 계속 체크하는게 싫음, list(count)로 하고 싶음

 └ + list[count-3] VS list[count] : count-3을 하는 경우, elif count=0, 1, 2 를 추가하지않으면 list[-3, -2 ,-1]이 되어버림

- html파일뽑을 때, 연산을 해야해서 None→0, 나머지는 int형으로 바꿔주었다

 

LAST.

두근두근 html출력
~땨다~

from random import randint


# [1~45 n회 비복원추출] 입력:n회 → 리턴:추출한(list)
def generate_numbers(n):
    lotto = set()

    while len(lotto) != n:
        lotto.add(randint(1, 45))

    return list(lotto)


# [이달의 로또 뽑기] return 당첨번호6(오름차순)개+보너스번호 list
def draw_winning_numbers():
    winning_numbers = generate_numbers(7)
    return sorted(winning_numbers[:6]) + winning_numbers[6:]


# [얼마나 겹쳤는가] 입력:(내 로또번호6개) & (당첨번호6개 or 보너스번호1개) → 리턴:겹치는 횟수
def count_matching_numbers(my_lotto, winning_lotto):
    return len(set(my_lotto) & set(winning_lotto))


# [상금을 알려줘] 입력:두 리스트 → 비교 → 리턴:받는 상금
def check(numbers, winning_numbers):
    count = count_matching_numbers(numbers, winning_numbers[:6])
    bonus = bool(count_matching_numbers(numbers, winning_numbers[6:]))
    price = [0, 0, 0, 5000, 50000, 1000000, 100000000]

    if count == 5 and bonus:
        return 50000000
    else:
        return price[count]

 

* 프로젝트: 숫자 야구

전체 지시사항

1.

1. 정답정하기 : [0, 9] 순열 (경우의 수 : 10P3)

- list형으로 모범답안처럼 작성할까했는데, set으로 진행해도 순서가 무작위로 나왔음

 

2.

2. 사용자가 선택한 숫자 3개 입력받아서, list로 return하기

- input으로 받은 객체의 형은 str이니, int 형변환 必

 └ 문제: int(정수형태의 str) OK ↔ 그 외 int(소수, 문자모양)를 받은 경우 Err이 나오는데 어떻게 걸러내지

 └ 해결: try-except구문을 사용하자

- 정수 中 0미만, 9초과 = not in range(0, 10)

- 문자열포메팅 f-string이 너무 편해서, 포멧메소드를 까먹겠으니 다시 읽고옴

 

3.

3. 스트라이크, 볼 횟수 int로 return

- 출력도 여러 개 가능

- LIST.index(값) → return 인덱스

 

LAST.

 

from random import randint


# 0~9사이의 서로 다른 숫자 3개 뽑기:Return(list) ⊃ items(int)
def generate_numbers():
    numbers = set()

    while len(numbers) != 3:
        numbers.add(randint(0, 9))

    print("0과 9 사이의 서로 다른 숫자 3개를 랜덤한 순서로 뽑았습니다.\n")
    return list(numbers)


# 사용자입력받기:Return(list) ⊃ items(int)
def take_guess():
    print("숫자 3개를 하나씩 차례대로 입력하세요.")

    new_guess = []
    while len(new_guess) < 3:
        try:
            number = int(input(f"{len(new_guess)+1}번째 숫자를 입력하세요: "))
        except ValueError as err:
            print(err, "→ 0~9사이의 '정수'만 입력해주세요")
            continue

        if number not in range(0, 10):      # [0, 1, 2, ···, 9]
            print("범위를 벗어나는 숫자입니다. 다시 입력하세요.")
        elif number in new_guess:
            print("중복되는 숫자입니다. 다시 입력하세요.")
        else:
            new_guess.append(number)

    return new_guess


# Count strike, ball:Return(int s, int b)
def get_score(guess, solution):
    strike_count = 0
    ball_count = 0

    for turn in range(3):                       # 3회 비교
        if guess[turn] in solution:             # 유저의 n번째 값이 정답에 존재하고,
            if guess[turn] == solution[turn]:   # 위치도 같으면 strike
                strike_count += 1
            else:                               # 위치가 다르면 ball
                ball_count += 1

    return strike_count, ball_count


# 여기서부터 게임 시작!
ANSWER = generate_numbers()
tries = 0

while True:     # self break 必
    tries += 1
    mine = take_guess()
    s, b = get_score(mine, ANSWER)
    print(f"{s}S {b}B\n")

    if s == 3:
        break

print("축하합니다. {}번 만에 숫자 3개의 값과 위치를 모두 맞추셨습니다.".format(tries))

 

[Keyword]

# stdlib & module:math random decimal os datetime

- from □ import ◇ as ★ (* = All)

- math: log(진수, 밑), log2(진수), log10(진수), sqrt(제곱), sin/cos/tan(rad), pi, e

- random:(float) random()→[0.0, 1.0), uniform(a, b)→[a, b)] & (int) randint(a, b)→[a, b]

- decimal:(class) Decimal(■=str) → instance

 decimal.getcontext().rounding = 'ROUND_HALF_UP'

 (method) instance.quantize(원하는instance, rounding='ROUND_HALF_UP')

- os:getlogin()→유저이름, getcwd()→현 작업디렉토리

- datetime:(class) date, time, datetime, timedelta(연, 월, 일, 시, 분, 초, ···)

  .now() → 현재, .strftime(format='···') → return(str)원하는 형태

  [format code]연%Y,y 월%B,b,m 일%d 요일%A,a,w 오전오후%p 시%H(24h),I(12h) 분%M 초%S

  [format code]%c → Tue Aug 16 21:30:00 1988  %x → 08/16/88  %X→21:30:00

  = "문자와 포멧코드".format(instance)

# 사용자입력 input("□")

- print("□") → 입력받기 → return(str)입력값

# File Read & Write

- with □ as ★: 해당 구간에서 □을 ★로 사용 & 종료

  open('파일위치/명', mode='rt', encoding='UTF-8'): 해당파일을 프로그램 內 특정 방식으로 사용할 수 있는 객체로써 엶

   mode=w:새로 덮어쓰기, =a:기존에 추가하기

- for i in ★

- ★.read/readline/readlines():전체str/첫줄str/한줄씩list

- ★.write('□'):★의 설정에 맞춰, ★에 write □

- str.l/r/strip()→공백제거, str.split("기준")→list

- print(end='□'):개행제거

+ exit() & try-except-else

- exit():종료

- try: 실행구역

 except 오류 as ★: 해당 오류인 경우, 실행할 구역

반응형

블로그의 정보

노력하는 실버티어

노실언니

활동하기