파이썬 기말 정리
1. 딕셔너리
- 값을 저장하는 자료구조
- 값과 관련된 키도 저장된다.
- 순서가 없다.
Key : Value
Key
- 반드시 불변 객체여야 한다.
-> 문자열, 숫자, 튜플 ,, (리스트는 X) - 한 딕셔너리 내에서 유일한 키를 가져야 한다.
- key가 중복되면 기존 값을 덮어쓰기 한다.
Value
- 어떤 타입도 올 수 있다.
- 딕셔너리도 올 수 있다.
1.1 딕셔너리 연산
항목 탐색
capitals = {"Korea": "Seoul", "USA": "Washington"}
1)
print(capitals["France"])
--> Key Error
2)
print(capitals.get("France", "해당 키가 없습니다."))
// 프로그램 오류로 중단되지 않게 하려면 이렇게 해야 함
or
if "France" in capitals:
- dict에 없는 키 값을 가져오려 하면 Error
- dict.get()이나 in 연산자로 사용
- 2) get()은 key가 없으면 None 반환 / 두번째 인자가 있으면 인자를 반환
- in 연산자는 key를 대상으로 찾음
항목 추가
capitals = {"Korea": "Seoul", "USA": "Washington"}
capitals["UK"] = "London"
print(capitals)
# {"Korea": "Seoul", "USA": "Washington", "UK": "London"}
- 새로운 키를 가지고 대입하면 새 항목이 추가된다.
딕셔너리 전체 추가/변경 - update({})
capitals = {"Korea": "Seoul", "USA": "Washington"}
capitals.update({"Korea": "Busan", "France": "Paris", "Germany": "Berlin"})
# {"Korea": "Busan",
# "USA": "Washington",
# "France": "Paris",
# "Germany": "Berlin"}
- update 메소드 사용하여 새로운 딕셔너리를 기존 딕셔너리에 추가하거나 수정
- 이미 있는 키는 value만 update된다.
항목 삭제하기 - dict.pop("UK") / dict.clear()
city = capitals.pop("UK")
# 에러 발생 안하게 하려면..
if "UK" in capitals:
capitals.pop("UK")
# 전체 삭제
capitals.clear()
- 주어진 키를 가진 항목이 없으면 KeyError 가 발생한다.
- 전체 삭제 = clear()
항목 방문
for key in capitals:
print(key, ":", capitals[key])
for key, value in capitals.items(): # tuple 리스트를 리턴(List(tuple))
print(key, ":", value)
- dict.items()는 튜플들의 리스트를 리턴
키 or 값만 가져오기
capitals.keys()
# ['Korea', 'USA', 'UK']
capitals.values()
# ['Seoul', 'Washington', 'London']
if user == 3:
pass # 나중에 구현
딕셔너리 메소드
d = dict() | 공백 딕셔너리 생성 |
d = {k1: v1, k2:v2, ..} | 초기값으로 딕셔너리 생성 |
len(d) | 딕셔너리에 저장된 항목 갯수 반환 |
k in d | k 가 딕셔너리 d 안에 있는 키인지 반환 |
k not in d | k가 딕셔너리 d 안에 없으면 True |
d[key] = value | 딕셔너리에 키와 값을 저장 |
d.get(key, default = None) | 주어진 키를 가지고 값을 찾는다. 없으면 default 값이 반환된다. |
d.pop(key) | 항목 삭제 |
d.values() | 딕셔너리 안의 모든 값의 (시퀀스)리스트 반환 |
d.keys() | 딕셔너리 안의 모든 키의 시퀀스(리스트)를 반환한다. |
d.items() | 딕셔너리 안의 모든 (key, value)를 리스트 형태로 반환 |
딕셔너리 복사하기
- dict2 = dict1.copy()
- dict2 = dict1
- dict2 = dict(dict1)
- dict2 = dict(dict1.items())
1.2 딕셔너리 함축
dic = { i: str(i) for i in [1,2,3,4,5]}
#{1: "1", 2: "2", 3:"3", 4:"4", 5: "5"}
dic1 = {"One": 1, "Two": 2, "Three": 3}
dic2 = {n:w for w,n in dic1.items()}
# dic2 {1: "One", 2: "Two", 3: "Three"}
출력 수식에는 { key : 값 } 수식 형태로 되어야 한다.
ex) 학생 성적 처리
3가지 과목에서의 각 학생의 성적 평균 구하기
score_dic = {'Kim': [99, 83, 95],
'Lee': [68, 45, 78],
'Choi': [25, 56, 69]}
result = {k: (sum(l) / len(l)) for k, l in score_dic.items()}
# {'Kim': 92.33333333333333, 'Lee': 63.666666666666664, 'Choi': 50.0}
1.3 단어 카운터 만들기
from collections import Counter
text_data = "Create the highest, ,,,,you become what you believe"
Counter(text_data.split())
# Counter({'you': 2, 'Create': 1, ,,,})
2. 문자열
아나콘다 모듈: BeautifulSoup, csv, json, nltk
Java, Python : Unicode
C++ : ASCII
문자열 내장 함수
chr(97) = 'a' | 정수 -> 문자로 변환 |
ord('a') = 97 | 문자 -> 정수로 변환 |
ascii | 문자열에서 아스키면 아스키 값, 이외의 값은 유니코드로 바꿔주는 함수 |
len( ) | 문자열의 길이를 반환 |
str( ) | 객체의 문자열 표현을 반환 |
2.1 문자열 슬라이싱
s = "Monty Python"
s[6:10]
# "Pyth"
s[:2] # "Mo"
s[4:] # "y Python"
s[:] # "Monty Python"
문자열은 불변 객체이다.
-> 수정할 수 없다. (word[0] ='a' 불가능)
word = "abcd"
word = "A" + word[1:] # Abcd
새로운 메모리를 가리키게 된다.
- 문자열도 시퀀스 자료형
text[ start_index : end_index + 1 ]
2.2 문자열 연산, 메소드
==, != , <, > 연산자를 사용할 수 있다.
문자열 메소드
s.capitalize() | 맨 앞글자만 대문자로 변환해준다. |
s.lower() | 전체를 소문자로 변환한 값 리턴 |
s.upper() | 전체를 대문자로 변환한 값 리턴 |
s.endswith(".py") | 문자열이 .py 로 끝나는지 |
s.startswith("ab") | 문자열이 ab로 시작하는지 |
s.find(".kr") | ".kr"이 들어있는지 찾아서 .kr이 있는 위치를 리턴한다. |
s.rfind("let") | 오른쪽부터 찾아서 처음에 나오는 문자열 위치를 리턴한다 |
s.count(".") s.count(".", 0, 5) |
문자열에 포함된 . 의 갯수를 세서 반환 index 0~4 범위에서 찾음 |
s.isdigit() | 문자열이 숫자인지 |
s.isalpha() | 문자열이 알파벳인지 |
"abc".islower() | 문자열이 소문자인지 |
s.strip() s.lstrip() s.rstrip() |
앞, 뒤에 있는 공백을 제거한다. 왼쪽에 있는 공백 제거 오른쪽 끝에 있는 공백 제거 - 문자열이 주어지는 경우 그 문자를 제거한다. |
s.split() s.split(",") |
공백문자를 기준으로 문자열을 분리하여 리스트에 넣는다. 주어진 문자를 구분자로 하여 문자열을 분리해 리스트 형태로 반환 (list(문자열) -> 한글자씩 쪼개진 리스트가 된다) |
",".join(["apple", "grape"]) -> "apple,grape" |
주어진 문자열을 맨 앞 문자열을 가지고 붙인다. |
s.isspace() | 공백문자인지 체크 (' ', \n, \t..) |
3. 객체와 클래스
파이썬은 객체지향을 지원하긴 하지만 완전히 구현한 언어는 아니다. OOP로 완벽한 언어는 아님
- 객체 지향 프로그래밍에서는 서로 관련 있는 데이터와 함수를 묶어서 객체로 만들고 이들 객체들이 모여서 하나의 프로그램이 된다.
- 객체지향: data(object)부터 생각하는 Bottom-Up(상향식)
- 함수형: 기능부터 생각하는 Top-down(하향식)
- 절차지향과 객체 지향
- 절차지향
프로시저 기반 프로그래밍 방법
- 작은 SW, 실시간 시스템에 적합 - 객체지향
데이터와 함수를 하나의 덩어리로 묶어서 생각하는 방법
- 큰 시스템에 적합, 재사용성이 높다.
- 절차지향
3.1 객체지향 3대 특성 PIE
Polymorphism
- 다형성
- 오버라이딩 된 메서드가 다형성을 띈다고 한다.
- 클래스 상속 관계를 갖는 클래스의 객체 중 오버라이딩 된 메서드를 호출하면 그 객체에 타입에 맞는 메서드가 호출된다.
Encapsulation
- 캡슐화
- class = data + behavior(func)
data를 가려서 보이지 않게 하고, func(사용법)만 밖에 보이게 한다. - 공용 인터페이스만 제공하고 구현 세부 사항을 감추는 것이다.
- struct 는 data만 가진다.
Inheritance
- 상속
- is-a 관계를 상속 관계라고 한다.
- 기존 코드를 재사용한다. 기존 클래스를 바탕으로 새로운 클래스를 정의한다.
- 클래스 계층 구조가 나타난다.
파이썬에서는 모든 것이 객체이다.
파이썬에서는 모든 것이 객체로 구현된다. 정수도 객체, 문자열도 객체, 리스트도 객체이다.
3.2 클래스 작성하기
class 클래스이름:
def __init__(self, ..):
self.count = 0
def func1(self, ..):
pass
- python 클래스의 모든 메소드는 제일 앞에 self가 온다.
- C++, Java는 this가 넘어가긴 하는데, 숨어서 넘어간다.
this: C++(포인터), Java(this = 레퍼런스 객체) - python은 변수 선언 시 자료형을 명시적으로 선언하지 않음(변수 선언 명시적으로 안함)
- __init__ 안에서 하는 self.count 형식으로 멤버변수를 선언한다.
3.3 객체 생성
- C++
- 일반 객체는 스택 영역에 메모리 잡힘
- new 로 생성한 객체는 heap 영역에 들어감
- Java
- class 객체는 무조건 heap 영역에 잡힘
- 모든 클래스 객체는 new 로 생성
- Python
- Java같은 형태
- __init__은 객체 생성시 자동으로 호출되는 생성자이다.
- 멤버변수 선언 시 self.을 붙이지 않으면 지역변수가 된다.
- 멤버 변수/메소드명 앞에 __를 붙이면 private 변수가 된다
(외부에서 클래스 멤버 변수에 직접 접근하는 것은 정보은닉에 위배된다.) - privte 인스턴스 변수는 클래스 내부에서만 접근할 수 있다.
3.4 객체 참조
- 파이썬에서 변수는 실제로 객체를 저장하지 않는다. 변수는 단지 객체의 메모리 주소를 저장한다.
- 객체 자체는 메모리의 다른 곳에 생성된다.
3.5 is, is not
- 2개의 변수가 동일한 객체를 참조하고 있는지를 검사하는 연산자 = is, is not
주소를 비교한다. - s is t 와 s == t 는 같음
- 내용이 같아도, 주소가 다르면 다른 객체
- 기본 데이터타입들은 == 연산자에 대해 정의되어있으므로 값을 비교한다.
-
a = Television(10, 11) b = Television(10, 11) a == b # False a is b # False a is not b # True
3.6 None
- 변수가 현재 아무것도 가리키고 있지 않다면 None 으로 설정하는 것이 좋다.
- 아무것도 참조하고 있지 않다는 것을 나타내는 특별한 값.
3.7 가변 객체를 함수로 전달
- 불변 객체는 함수로 전달되면 함수 안에서 변경이 일어나도 밖에서는 변경되지 않는다.
- 가변 객체는 함수 내에서 변경되면 객체의 내용이 변경된다.
3.8 클래스 변수
class Television:
serial = 0 # class 변수
def __init__(self):
Television.serial += 1
- 클래스 변수는 생성자가 아니라 클래스 안에 선언한다.
- 클래스 변수에 접근할 때는 클래스명.변수 로 접근한다.
- 객체명.클래스변수로 접근하는 것도 가능하지만 좋은 것은 아니다.
- 상수는 흔히 클래스 변수로 정의된다.
- Monster.WEAK -> 따로 상수 문법 없음
- C++ => const
- Java -> static(클래스 변수) final (상수)
3.9 특수 메소드
- 연산자에 관련된 특수 메소드 = 연산자 오버로딩(C++, 같은 이름에 여러 의미 부여) (오버로딩: 같은 이름 함수가 여러개)
- 객체에 대하여 연산 적용시 호출됨
연산자 | 메소드 | 설명 |
x + y | __add__(self, y) | 덧셈 |
x - y | __sub__(self, y) | 뺄셈 |
x * y | __mul__(self, y) | 곱셈 |
x / y | __truediv__(self, y) | 실수 나눗셈 |
x // y | __floordiv__(self, y) | 정수 나눗셈 |
x % y | __mod__(self, y) | 나머지 |
divmod(x, y) | __divmod__(self, y) | 실수 나눗셈과 나머지 |
x ** y | __pow__(self, y) | 지수 |
x << y | __lshift__(self, y) | 왼쪽 비트 이동 |
x >> y | __rshift__(self, y) | 오른쪽 비트 이동 |
x <= y | __le__(self, y) | less than or equal(작거나 같다) |
x < y | __lt__(self, y) | less than (작다) |
x >= y | __ge__(self, y) | greater than or equal (크거나 같다) |
x > y | __gt__(self, y) | greater than (크다) |
x == y | __eq__(self, y) | 같다 |
x != y | __neq__(self, y) | 같지 않다. |
__str__() 메소드
- print() 실행 시 자동으로 호출됨
- Java의 toString() (클래스 정보를 문자열로 반환)
- 일반적으로 객체를 문자열로 만들어 반환
'(%g, %g)' % (self.x, self.y)
%g: 실수
4. GUI 프로그래밍
tkinter는 파이썬에서 그래픽 사용자 인터페이스를 개발할 때 필요한 모듈이다.
유닉스 계열에서 사용되던 Tcl/Tk 위에 객체지향 계층을 입힌 것이다. Tk는 Tcl 스크립팅 언어를 위한 GUI 확장으로 개발
4.1 단순 위젯과 컨테이너 위젯
- 단순 위젯
- Button, Canvas, Checkbutton, Entry, Label, Message
- 컨테이너 컴포넌트
- 다른 컴포넌트를 안에 포함할 수 있는 컴포넌트
- Frame, Toplevel, LabelFrame, PanedWindow
윈도우 생성하기
from tkinter import * # tkinter 모듈 포함
window = Tk() # 윈도우 생성
label = Label(window, text="Hello tkinter") # 레이블 위젯 생성
label.pack() # 레이블 위젯을 윈도우에 배치
window.mainloop() # 윈도우가 사용자 동작을 대기
- python 에서는 GUI 프로그램은 맨 밑에 항상 window.mainloop() 가 있어야 함
- Tk() 를 호출하면 Tk 클래스의 객체가 생성되면서 화면에 하나의 윈도우가 생성된다.
- label = Label(window, text="Hello tkinter")
레이블 위젯을 생성 - label.pack()
- pack() 은 압축 배치 관리자를 이용하여 레이블을 컨테이너에 위치시킨다.
- window.mainloop()는 이벤트 처리 루프로서 사용자로부터오는 마우스나 키보드 이벤트를 처리한다.
Button | 간단한 버튼으로 명령을 수행할 때 사용된다 |
Canvas | 화면에 무언가를 그릴 때 사용한다 |
Checkbutton | 2가지의 구별되는 값을 가지는 변수를 표현한다. |
Entry | TextField) 한 줄의 텍스트를 입력받는 필드 |
Frame | 컨테이너 클래스이다. 프레임은 경계선과 배경을 가지고 있다. 다른 위젯들을 그루핑하는데 사용된다. (Panel) |
Label | 텍스트나 이미지를 표시한다. |
Listbox | 선택 사항을 표시한다. |
Menu | 메뉴를 표시한다. 풀다운 메뉴나 팝업 메뉴가 가능하다. |
Menubutton | 메뉴 버튼. 풀 다운 메뉴가 가능하다. |
Message | 텍스트를 표시한다. 레이블 위젯과 비슷하다. 하지만 자동적으로 주어진 크기로 텍스트를 축소할 수 있다. |
Radiobutton | 여러 값을 가질 수 있는 변수를 표시한다. |
Scale | 슬라이더를 끌어서 수치를 입력하는데 사용된다. |
Scrollbar | 캔버스, 엔트리, 리스트 박스, 텍스트 위젯을 위한 스크롤 바를 제공한다. |
Text | 형식을 가지는 텍스트를 표시한다. 여러가지 스타일과 속성으로 테스트를 표시할 수 있다. |
Toplevel | 최상위 윈도우로 표시되는 독립적인 컨테이너 위젯 |
LabelFrame | 경계선과 제목을 가지는 프레임 위젯의 변형 |
PanedWindow | 자식 위젯들을 크기조절이 가능한 패널로 관리하는 컨테이너 위젯 |
Spinbox | 특정한 범위에서 값을 선택하는 엔트리 위젯의 변형 |
버튼 위젯
from tkinter import *
window = Tk()
button = Button(window, text="클릭", bg="yellow",
fg="blue", width=80, height=2)
# 크기 설정, 픽셀이 아닌 글자 단위
# 컨테이너 크기 설정 시 px 단위로 설정됨
button.pack() # 컴포넌트들을 팩으로 붙임
window.mainloop()
엔트리 위젯 = TextField
from tkinter import *
window = Tk()
entry = Entry(window, fg="black", bg="yellow", width=80)
entry.pack()
window.mainloop()
- Entry().insert(추가할 위치, 넣을 문자열)
- Entry().delete(삭제할 처음 위치, 마지막 위치)
- END = 끝
entry.delete(0, END) -> 처음부터 끝까지 지운다.
4.2 배치 관리자: Layout Manager
- 압축 배치 관리자
- 격자 배치 관리자
- 절대 배치 관리자
Java Swing:
FlowLayout, GridLayout, BorderLayout, GridBagLayout, ...
1) 압축 배치 관리자 Pack Geometry Manager
- 압축 배치 관리자는 위젯들을 최대한 압축하여 컨테이너 안에 세로로 배치 (상하)
- 위젯들을 사각형 블록으로 간주
- pack() 메소드 사용
from tkinter import * window = Tk() Label(window, text="박스 #1", bg="red", fg="white").pack() Label(window, text="박스 #2", bg="green", fg="black").pack() Label(window, text="박스 #3", bg="blue", fg="white").pack() window.mainloop()
- pack(side=LEFT)
왼쪽에 붙임 - LEFT, RIGHT, TOP(default), BOTTOM
- "left", "right",,,
- label, button color 변경
bg="red" background color
fg="black" foreground color
2) 격자 배치 관리자 Grid Geometry Manager
- 위젯(버튼, 레이블 등)을 테이블 형태로 배치한다
- grid(row= , column=) 메소드 사용
- 모든 행과 열이 같을 필요는 없다.
- 직사각형 형태일 필요 없음
3) 절대 위치 배치 관리자 Place
- 절대 위치 배치 관리자는 절대 위치를 사용하여 위젯을 배치
- 위젯의 왼쪽 상단 지점 위치 지정
- place(x= , y= ) 메소드 사용
- Frame
- Java swing, awt = Pannel
- 컴포넌트들을 그룹핑 하는 역할을 한다.
- 위젯들을 프레임에 붙인 뒤 프레임을 윈도우에 붙인다.
- 윈도우 크기 설정
- window.geometry("600x100")
- px 단위
- 위젯 크기 설정
- ex) Button(window, text="box1", width=10, height=1).pack()
- 글자 단위로 설정됨
Java는 그리드 레이아웃의 모든 크기가 동일
- Python은 그리드 레이아웃의 비율이 각각 다를 수 있음
- sticky=W+E+N+S
주어진 방향으로 딱 붙임 - PhotoImage(file="d://fig3.png")
- 이미지 넣기
- file 경로 : 코드 파일과 같은 위치에 이미지가 있으면 상대경로 지정 가능
- Grid
- row, column 은 위치 지정
- rowspan, columnspan 은 차지할 행의 수, 차지할 열의 수이다.
4.3 버튼 이벤트 처리
이벤트 드리븐 방식
이벤트가 발생하면 지정된 함수를 호출한다. (callback 함수 / 이벤트 핸들러)
Button(window, command=함수이름)
Label
- Label 의 text 속성은 딕셔너리 같이 접근 가능
- label['text']
- label.config(text="world", bg="yellow")
4.4 람다식
- 람다식은 이름은 없고 몸체만 있는 함수이다.
- 람다식은 lambda 키워드로 만들어진다.
- 람다식은 딱 한번 사용하는 함수를 만드는데 사용된다.
- lambda x, y : x + y
- lambda 매개변수: 수식
- eval("2 + 3") -> 5
문자열을 계산한다. - command=lambda t=button_text:click(t)
def process(t = button_text)
click(t)
def click(key):
pass
4.5 그림 그리는 화면 : Canvas
from tkinter import *
window = Tk()
w = Canvas(window, width=300, height=200)
w.pack()
i = w.create_rectangle(50, 25, 200, 100, fill="blue")
w.coords(i, 0, 0, 100, 100) # 좌표 변경
w.itemconfig(i, fill="blue") # 색상 변경
w.delete(i) # i 항목을 삭제한다
w.delete(ALL) # 모든 항목을 삭제한다
window.mainloop()
create_line(15, 25, 200, 25) | 직선을 그리는 메소드 (x1, y1, x2, y2) |
create_rectangle(50, 25, 150, 75, fill="blue") | 사각형을 그리는 메소드 (x1, y1, x2, y2) |
create_text(200, 100, fill="darkblue", font="Times 30 italic bold", text="This is a text example") | 텍스트 그리기 x, y 가 중심 좌표가 된다. |
create_arc(10, 10, 100, 150, extent=90) | ![]() |
create_oval(15, 25, 100, 125) | 타원은 지정된 사각형 안에 그려진다. |
create_polygon(10, 10, 150, 110, 250, 20, fill="yellow") | 10, 10 에서 출발, (150, 110) -> (250, 20) 에서 종료 |
- 옵션
- anchor=NWES
NW => 북쪽 + 서쪽 방향에 붙인다. - width: 선 굵기
좌표 변경: canvas.coords(캔버스에 그린 객체 id, x1, y1, x2, y2)
좌표 가져오기: canvas.coords(캔버스에 그린 객체 id)
4.6 키보드와 마우스 이벤트 처리
def callback(event):
pass
- event.x, event.y 를 통해 클릭된 위치 파악 가능
이벤트 지정자
- <Button-1> : 왼쪽 버튼
마우스가 버튼 위젯 위에서 눌렸을 때 발생하는 이벤트
<Button-2> 중간 버튼
<Button-3> 오른쪽 버튼
<Button-1>, <ButtonPress-1>, <1> 은 모두 버튼 이벤트를 가리킴 - <B1-Motion>
마우스 버튼 1이 눌려진 채로 움직일 때 발생
중간버튼 B2, 오른쪽 버튼 B3 - <ButtonRelease-1>
사용자가 Button1 에서 손을 뗄 때 발생 - <Double-Button-1>
마우스 버튼 1이 더블 클릭될 때 발생
Triple도 가능
단일 클릭과 더블 클릭에 동시에 연결하면 양쪽 콜백 메서드가 모두 호출됨 - <Enter>
마우스 포인터가 위젯으로 진입하였을 때 발생
*엔터키 아님 - <Leave>
마우스 포인터가 위젯을 떠났을 때 발생 - <FocusIn>
키보드 포커스가 현재의 위젯으로 이동 - <FocusOut>
키보드 포커스가 현재의 위젯에서 다른 위젯으로 이동 - <return>
엔터키 입력
Backspace, Cancel(Break), Tab, return, Shift_L, Control_L, Alt_L - <Key>
사용자가 어떤 키라도 누르면 발생한다.
눌려진 키는 이벤트 객체의 char 멤버(event.char)에 저장되어있다.
F5같은 키는 저장 안됨 - a
사용자가 "a"를 입력하였을 때 발생. 대부분의 인쇄 가능한 문자는 이런 식으로 연결
예외) <space>, "<": <less>
1 - 키보드 바인딩
<1> - 버튼 바인딩 - <Shift-Up>
시프트 키 + 위쪽 화살표
<Shift-Down>
시프트 + 아래쪽 화살표
Alt, Shift, Control 과 같은 수식어 사용 가능 - <Configure>
위젯이 크기 변경했을 때 발생. 위젯의 위치나 플랫폼을 변경해도 발생
새로운 크기는 콜백 메소드로 전달되는 이벤트 객체의 width나 height 속성에 저장된다.
1) 마우스이벤트 처리
from tkinter import *
window = Tk()
def key(event):
print(repr(event.char), '가 눌렸습니다.')
def callback(event):
frame.focus_set()
print(event.x, event.y, '에서 마우스 이벤트 발생')
frame = Frame(window, width=100, height=100)
frame.bind('<Key>', key)
frame.bind('<Button-1>', callback)
frame.pack()
window.mainloop()
- frame.focus_set() 메소드를 이용하여 원하는 위젯으로 포커스를 이동시킬 수 있다.
- repr('a') -> 'a' 그대로 출력
- event.char
어느 키가 눌렸는지 알려줌 - event.x, event.y
마우스가 눌린 좌표
Java: JTextField, JPasswordField < - > Python: Entry
5. 상속
상속
기존에 존재하는 클래스로부터 멤버 함수와 멤버변수를 이어받고, 자신이 필요한 기능을 추가하는 기법
- 객체지향 프로그래밍에서는 상속이 클래스 간의 is-a 관계를 생성하는데 사용
- 자식 클래스 is a 부모 클래스
- 푸들은 강아지이다.
상속 구현하기
class 자식클래스(부모클래스):
def __init__(self, ..):
super.__init__(...)
...
- 부모 클래스를 호출하는 방법
super.으로 호출하거나
부모클래스. 으로 호출 가능 (자식 클래스 내에서) - 파이썬은 반드시 자식 생성자에서 부모 생성자를 호출해야 한다.
부모 클래스의 변수를 초기화 하기 위해서는 부모 클래스의 생성자를 호출해서 초기화 한다. - 부모 클래스의 생성자를 명시적으로 호출해야 함
- 부모 클래스의 생성자를 호출하지 않으면 부모 클래스에 정의된 멤버변수가 생성되지 않는다. (사용 불가, 사용하려고 하면 Error)
- C++, Java는 부모생성자를 호출하지 않으면 암묵적으로 호출됨) 컴파일러가 자동으로 호출해준다.
상속을 사용하는 이유
- 코드 중복을 제거할 수 있다.
- 중복되는 코드를 모아서 부모 클래스로 두게 되면 코드 재사용성이 높아진다.
- type()
함수를 사용하면 변수의 타입을 알 수 있다. - isinstance()
부모 클래스까지 체크가 가능
x = Animal() y = Dog() isinstance(x, Animal) >> True isinstance(y, Animal) >> True isinstance(y, Dog) >> True isinstance(x, Dog) >> False
- 부모 클래스의 private 멤버는 자식 클래스에서 사용할 수 없다.
self.__data # private
5.1 다중 상속
class A:
def __init__(self, ...):
class B:
def __init__(self, ...):
pass
class C(A, B):
def __init__(self, ...):
# 다중 상속은 super()를 사용할 수 없음
A.__init__(self, ...)
B.__init__(self, ...)
- 다중 상속에서 부모 클래스를 호출하는 경우 super()를 쓰면 알아볼 수 없으므로 클래스 이름으로 호출한다.
- 다중 상속에서 부모 생성자를 호출할 때 self를 넘겨줘야 한다.
5.2 메소드 오버라이딩
- 자식 클래스의 메소드가 부모 클래스의 메소드를 오버라이드한다고 말한다.
- 자식 클래스가 부모 클래스에서 상속받은 메소드를 필요에 따라 변경하는 것
- 다형성의 대상 == 자식 클래스
- 상위 클래스와 하위 클래스에 동일한 함수 헤더가 정의되고 구현만 다른 경우
C++: virtual이 붙어야 오버라이딩 됨
Java, python: 자동 오버라이딩 효과
객체 출력
- __str__(self):
메소드가 문자열을 리턴한 내용이 객체 출력
객체를 가독성있는 텍스트로 출력 (사용자 입장) - __repr__(self):
str이 없을 때 메소드에서 반환하는 내용을 객체 출력시 출력
객체를 확실히 구별하기 위한 출력 (시스템)
5.3 다형성
다형성은 많은(poly) + 모양(morph) 이라는 의미로
주로 프로그래밍 언어에서 하나의 식별자로 다양한 타입을 처리하는 것을 의미한다.
- 동일한 코드로 다양한 타입의 객체를 처리할 수 있는 기법
- Animal a = Dog() / Cat()
a 안에 들어가 있는 객체의 타입에 맞는 speak를 호출한다.
실행할 때 a 안에 들어있는 객체의 타입을 알 수 있다. - 다형성이 구현되려면 Runtime 바인딩이 되어야 한다.
- 컴파일 시에는 실제 들어있는 객체의 타입이 무엇인지 알 수 없다.
- 일반적인 경우에는 컴파일 시에 알수있다. 오버라이딩된 객체지향 언어인 경우 data type에 따라 호출하는 것이 아니라 안에 들어있는 객체의 타입을 보고 호출한다.
- 부모 클래스에 구현되어 있지 않으면 오버라이딩이 아님
- 다형성의 대상: 오버라이딩된 멤버함수
5.4 object class
- 모든 클래스의 맨 위에는 object 클래스가 있다.
- object class 메소드
__init__(self, ..) 생성자 __del__( self ) 소멸자 __repr__( self ) 객체 표현 문자열 반환 __str__( self ) 문자열 표현 반환 __cmp__( self ) 객체 비교
5.5 클래스 관계
is-a 관계 = 상속
- Car is a Vehicle
- Dog is a Animal
- Circle is a Shape
has-a 관계 = 구성
- Library has a book
- Living room has a sofa
6. 내장함수, 람다식, 제너레이터, 모듈
6.1 내장함수
- abs(-20)
숫자의 절댓값을 반환하는데 사용됨
실수, 정수 동일 - all()
시퀀스(리스트, 딕셔너리)를 받아서 시퀀스의 모든 항목이 참이면 True를 반환한다. (0이 없으면 True)
(AND) - any()
시퀀스 객체에 있는 한 개의 항목이라도 참인 경우 True
(OR) - bin()
정수의 이진 표현 반환
bin(64) == 0b1000000 - eval('x + 1')
전달된 수식을 구문 분석하고 프로그램 내에서 수식을 실행한다.
- string으로 값을 넘겨줘야 함 - sum([1,2,3])
리스트에 존재하는 항목들을 전부 더하여 합계를 반환한다. - len()
객체의 길이를 계산하여 반환하는 함수 - list()함수
리스트를 생성하는 함수
문자열을 넣으면 한글자씩 쪼갬 - map(function, 이터레이터 객체) 함수
반복 가능한 객체의 각 항목에 주어진 결과를 적용한 후 결과를 반환 - dir()
객체가 가지고 있는 변수나 함수를 보여준다
객체에 사용가능한 함수들을 알고싶을 때 유용 - complex(실수 , 허수)
복소수 객체 생성 - max(), min()
리스트나 튜플, 문자열에서 가장 큰 항목을 반환 - enumerate()
시퀀스 객체를 입력받아 열거형 객체를 반환
열거형객체는 첫번째 요소가 번호, 두번째 요소가 해당 값을 갖는 객체
ex) enumerate(mylist, start=1)
[(1, 'a'), (2, 'b')] # 시작 번호가 1부터 시작함 (default = 0) - filter(func, 반복 가능한 객체)
함수의 결과가 true 인 요소만 뽑아냄 - zip()
두개의 자료형을 하나로 묶어주는 함수
numbers[1, 2, 3, 4], slist['a', 'b', 'c']
zip(numbers, slist) => [(1, 'a'), (2, 'b'), (3, 'c')]
6.2 정렬과 탐색
- mylist.sort()
- 이 메소드는 주어진 리스트를 정렬된 상태로 변경
- 주어진 리스트가 정렬됨.
- 리턴되지 않음
- sorted(mylist)
- 정렬된 리스트를 생성하여 리턴한다.
- 기존 리스트는 변경되지 않음
- sort()는 원 리스트를 변경하고, sorted()는 변경하지 않는다.
- sort()는 리스트만을 위한 메소드
sorted()는 반복가능한 어느 객체에도 사용 가능 - key=str.lower 옵션
sorted를 호출하기 전에 모두 소문자로 변경
클래스 객체의 경우 특정 값을 리턴하는 함수를 넣을 수 있음
- reverse = True 옵션
- sort(), sorted() 모두 사용 가능
- default = 오름차순 [1, 2, 3, 4, 5]
- reverse = True => 내림차순 정렬[5, 4, 3, 2, 1]
6.3 람다식
- 이름은 없고 몸체만 있는 함수
- lambda 매개변수 : 수식
- 딱 한번 사용하는 함수를 만드는데 사용된다.
- 여러개의 매개변수, 리턴값은 하나 이하
reduce
import functools
result = functools.reduce(lambda x, y: x + y, [1, 2, 3, 4])
print(result) # 10
- (((1 + 2) + 3) + 4) = 10
6.4 이터러블 객체 만들기
- __iter__()
- 자기 자신을 반환
return self
- 자기 자신을 반환
- __next__()
- 다음 반복을 위한 값을 반환
- 더 이상의 값이 없으면 raise StopIteration을 발생
class MyCounter(object):
def __init__(self, low, high):
self.current = low
self.high = high
def __iter__(self):
return self
def __next__(self):
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current - 1
6.5 제너레이터
- 키워드 yield 를 사용해서 함수로부터 이터레이터를 생성
def myGenerator():
yield 'first'
yield 'second'
yield 'third'
for word in myGenerator():
print(word)
- first
second
third가 순서대로 출력된다.
def myCounter(low, high):
while low <= high:
yield low
low += 1
for i in myCounter(1, 10):
print(i, end=" ")
# 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
피보나치 이터레이터
class FibIterator:
def __init__(self, a=1, b=0, maxValue=50):
self.a = a
self.b = b
self.maxValue = maxValue
def __iter__(self):
return self
def __next__(self):
n = self.a + self.b
if n > self.maxValue:
raise StopIteration()
self.a = self.b
self.b = n
return n
for i in FibIterator():
print(i, end =" ")
# 1 1 2 3 5 8 13 21 34
6.6 연산자 오버로딩
덧셈 | x + y | x.__add__(y) |
뺄셈 | x - y | x.__sub__(y) |
곱셈 | x * y | x.__mul__(y) |
지수 | x ** y | x.__pow__(y) |
나눗셈(실수) | x / y | x.__truediv__(y) |
나눗셈(정수) | x // y | x.__floordiv__(y) |
나머지 | x % y | x.__mod__(y) |
작음 | x < y | x.__lt__(y) |
작거나 같음 | x <= y | x.__le__(y) |
같음 | x == y | x.__eq__(y) |
같지 않음 | x != y | x.__ne__(y) |
큼 | x > y | x.__gt__(y) |
크거나 같음 | x >= y | x.__ge__(y) |
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Point(x, y)
def __str__(self):
return f'Point({self.x}, {self.y})'
p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1 + p2)
6.7 모듈
- 파이썬 프로그램이 길어지면 유지 보수를 쉽게 하기 위해 여러개의 파일로 분할할 수 있다.
- 파일을 사용하면 한번 작성한 함수를 복사하지 않고 여러 프로그램에서 사용할 수 있다.
# fibo.py
def fib(n):
pass
def fib2(n):
pass
모듈 사용하기
import fibo
>>>> fibo.fib(1000)
>>>> fibo.fib2(100)
#모듈 이름
>>>> fibo.__name__
'fibo'
- import 를 선언할 때 .py 를 붙이면 안됨
- 모듈 안의 함수들을 현재 심볼테이블에 저장하지 않음
- 모듈 이름 fibo만 심볼 테이블에 저장되므로 모듈 알의 함수들을 호출하려면 fibo. 으로 호출해야 한다
- 모듈의 이름을 사용하지 않고 안에 함수들을 호출하려면
from fibo import *
from fibo import fib2 - 모듈의 별칭
import fibo as fib
모듈 탐색 경로 (sys.path는 다음과 같이 초기화 됨)
- 입력 스크립트가 있는 디렉토리 (현재 디렉토리)
- PYTHONPATH 환경 변수
각자 만든 모듈의 경로를 넣어도 됨 - 설치에 의존하는 디폴트 값
Java: java.util
C++: STL
python: list, set, map
- copy 모듈
- copy.deepcopy(['r', 'b', 'g'])
- random 모듈
- random.randint(1, 6)
- random.random()
0 <= x < 1.0 범위의 실수형 난수 - random.choice(mylist)
mylist에서 랜덤으로 하나 선택 - random.shuffle(mylist)
리스트의 내용을 섞음 - random.randrange(0, 101, 3)
[0, 101 - 1] 범위의 3의 배수 - random.sample("문자열", 선택할 문자 개수)
문자열에서 선택할 문자 개수만큼 임의로 선택하여 리스트로 된 결과를 반환
- sys 모듈
- sys.prefix()
파이썬 설치 경로 - sys.executable()
파이썬 실행 파일 - sys.path
라이브러리 경로
- sys.prefix()
- time 모듈
- time.time()
1970.1.1 0시부터 지금까지 초 시간 - time.asctime()
현재 날짜와 시간을 문자열로 표현 - time.sleep(secs)
초 단위
- time.time()
- calendar 모듈
- calendar.month(2016, 8)
print(cal)
해당 연도의 8월 달력 출력
- calendar.month(2016, 8)
- keyword 모듈
- keyword.iskeyword(name)
name이 키워드 명인지 체크
- keyword.iskeyword(name)
7. 파일과 예외처리
파일의 맨 끝에는 EOF 마커가 들어있다.
7.1 파일 열고 닫기
infile = open('input.txt', 'r')
infile.close()
- open( '파일 이름', '파일 모드' )
- infile.close()
- 파일 모드
"r" 읽기 모드 파일의 처음부터 읽음 "w" 쓰기 모드 파일의 처음부터 쓴다. 파일이 없으면 생성된다.
파일이 존재하면 기존 내용은 지워진다."a" 추가 모드 파일의 끝에 내용을 추가한다.
파일이 없으면 생성됨"r+" 읽기 + 쓰기 파일에 읽고 쓸 수 있는 모드.
seek()를 호출해서 현재 포인트 위치를 변경 - seek(offset, 기준점)
기준점 0: 맨 앞, 1: 현재 위치, 2: 맨 뒤
7.2 파일 읽고 쓰기
1) 파일 읽기
infile = open('input.txt', 'r')
# 홍길동\n
# 김철수\n
line = infile.readline() # 홍길동\n
while line != "":
print(line) # 홍길동\n\n
line = infile.readline()
- readline()
끝에 개행문자까지 읽어옴 - infile.readline().rstrip()
오른쪽에 있는 \n 문자 삭제 (공백문자 삭제) - for line in infile:
print(line)
파일에서 한줄씩 읽음 (개행문자까지 읽어들임)
읽기용 메소드
readline() | 한 줄 씩 읽어옴 (개행문자 포함) |
readlines() | 파일 전체를 한줄씩 구분된 리스트로 읽어옴 (개행 포함) |
read() read(1) |
파일 전체를 하나의 문자열로 읽음 원하는 갯수만큼 읽음 |
2) 파일 쓰기
outfile = open("output.txt", "w")
outfile.write("김영희\n");
print("hello world\n", file=outfile)
outfile.close()
- outfile.write(text)
- print(text, file=outfile)
file에 쓸 객체 입력
3) 파일 닫기
- f.close()
- with open("test.txt", "w") as f:
f.write("hello")
블록을 빠져나오면 자동으로 파일이 닫힌다.
line.split()
-> 공백 문자를 기준으로 분리
ord('A')
-> 주어진 문자를 아스키 코드 숫자로 변환
7.3 이진 파일 읽고 쓰기
- 이진 파일에서 데이터를 읽으려면
infile = open(filename, "rb")
"rb" = read binary - infile.read(8)
입력 파일에서 8바이트 읽기 - 이진 파일에 바이트들을 저장하려면
outfile = open( filename, "wb" )
outfile.write( bytes([255, 128, 0, 1]) ) # 4 byte
7.4 임의 접근의 원리
** seek()에서 offset 은 바이너리 파일만 지원. 텍스트 파일에서 오프셋은 사용할 수 없음(whence가 1, 2일 때)
- seek( offset, 0 )
파일 처음에서 offset 만큼 떨어진 위치에 접근 - seek( offset, 1 )
현재 위치에서 offset 만큼 떨어진 위치에 접근 - seek( offset, 2 )
파일 맨 끝에서 offset 만큼 떨어진 위치에 접근
offset은 - 음수 값
7.5 예외 처리
Java: try, catch, finally
python: try, except, else, finally
1) 오류의 종류
- IOError
파일을 열 수 없을 때 발생 - importError
파이썬이 모듈을 찾을 수 없을 때 - ValueError
연산이나 내장 함수에서 인수가 적절치 않은 값을 가지고 있으면 발생 - KeyboardInterrupt
사용자가 인터럽트 키를 누르면 발생 - EOFError
내장 함수가 파일의 끝을 만나면 발생
2) try-catch 구조
- try 에서 예외가 던져지면, except 목록 중에서 순서대로 내려가면서 첫번째로 일치되는 예외를 선택
(x, y) = (2, 0)
try:
z = x/y
except ZeroDivisionError as e:
print(e) # 에러 정보를 출력해줌
except 블록은 예외가 발생하지 않으면 실행되지 않는다.
3) else 블록
try:
fh = open("testfile", "r")
fh.write("test data file write\n")
except IOError as e:
print(e)
else:
print('else')
finally:
print('finally')
- else 블록
- 아무런 예외가 발생하지 않았을 때 실행된다.
- except 블록 바로 뒤에 옴
- finally
- 예외가 발생하는지 여부와 상관없이 무조건 실행하는 블록
- try-catch 블록의 가장 마지막에 온다
4) 예외 발생하기
- 파이썬에서는 오류가 감지되면 raise 문을 사용하여 예외를 생성한다
- raise (error 객체)
예외 객체를 생성해서 던짐