- import 키워드 이용해서 모듈을 임포트 한다.
- import calculator as cal
--> calculator라는 모듈을 improt하고 cal 로 단축해서 사용하겠다.- from ~ as 키워드 이용해 모듈의 특정 기능만 사용 가능
- from calculator import add
--> calculator 모듈에서 add() 기능만 사용하겠다.- from calculator import add,sub,mul
--> calculator 모듈에서 add(),sub(),mul()기능을 사용하겠다.- from calculator import *
-->calculator모듈에 모든 기능을 사용하겠다 == claculator모듈 import
#합
lisrVar = [2, 5, 3.14, 58, 10, 2]
print(f'{sum(lisrVar)}')
#최댓값
lisrVar = [2, 5, 3.14, 58, 10, 2]
print(f'{max(lisrVar)}')
#최솟값
lisrVar = [2, 5, 3.14, 58, 10, 2]
print(f'{min(lisrVar)}')
#거듭제곱
print(f'{pow(12,2)}')
#반올림
print(f'{round(3.141592,1)}')
import math
#절대값
print(f'{math.fabs(-10)}')
print(f'{math.fabs(-0.20314)}')
#올림
print(f'{math.ceil(5.21)}')
#내림
print(f'{math.floor(5.21)}')
#버림
print(f'{math.trunc(5.32)}')
#최대공약수
print(f'{math.gcd(12,24)}')
#팩토리얼
print(f'{math.factorial(10)}')
#제곱근
print(f'{math.sqrt(4)}')
import time
lt = time.localtime()
#현제 년월일 시간 정보
print(f'{lt}')
#현제 연도
print(f'{lt.tm_year}')
#현제 월
print(f'{lt.tm_mon}')
#현제 일
print(f'{lt.tm_mday}')
#현제 시,분,초
print(f'{lt.tm_hour}')
print(f'{lt.tm_min}')
print(f'{lt.tm_sec}')
#현제 요일
print(f'{lt.tm_wday}')
#결과 2 이면 수요일(0부터 월요일)
- 파이썬에서 기본적으로 제공하는 전역변수
- 모듈명이 저장되거나 --main--이 저장된다.
- --main--이 저장되는 이유는 실행파일(메인)을 모듈과 구분짓기 위해서이다.
1.환산해주는 기능을 가진 모듈 제작
2.실행 파일
- 결과
- 디렉토리와 동일
- 모듈을 모아두고 효율적으로 관리 할 수 있는 것
- 똑같은 이름의 모듈인데 기능이 다르다면 각각 다른 패키지에 넣어 구분짓기
- 모듈제작을 해도 동일 패키지 안에서만 제작한 모듈을 사용 할 수 있다.
- 제작한 모듈을 다른 패키지에서도 자유롭게 사용하기 위해 site-package로 해당 모듈이 있는 패키지를 옮긴다.
- 프로젝트 내에서 언제나 사용 가능
venv - Lib - site-package
- 이 위치에 해당 패키지를 잘라 붙여넣으면 해당 프로젝트내에서 어디서든 해당 패키지에 속한 모듈기능 사용 가능
객체를 이용한 프로그램으로 객체는 속성,기능 으로 구성
- 객체(Object) = 속성(Attribute) + 기능(Function)
- 일상생활 속으로 생각해보면
- 자동차(객체)
-- 속성 : 색상,가격,크기...
-- 기능 : 전진, 후진, 정지...- 계산기(객체)
-- 속성 : 숫자
-- 기능 : 덧셈, 뺄셈, ...
객체지향 프로그램 : 일상생활에서의 객체 의미를 프로그램에 가져와서 프로그램을 구현 한 것
- 코드 재사용, 모듈화에 좋다.
- 결합도가 낮아 조립하는 식으로 프로그래밍 가능
- 객체를 생성하기 위해서는 클래스는 먼저 생성해야 한다.
- 클래스명의 첫 글자는 대문자로 한다.
- 클래스 = 붕어빵 틀, 객체 = 붕어빵
#클래스 생성
class Airplain:
#속성 정의
def __init__(self,siz,spd):
self.size = siz
self.speed = spd
#기능 정의
def doFly(self):
print('날아라')
def doLend(self):
print('착륙하라')
def printInfo(self):
print(f'size = {self.size}')
print(f'speed = {self.speed}')
#Airplane클래스 생성자 호출
air1 = Airplain(2000,500.34)
air2 = Airplain(4945,690)
air1.doFly()
air2.doLend()
air1.printInfo()
날아라
착륙하라
size = 2000
speed = 500.0
객체의 속성은 변경이 가능하다.
#클래스 생성
class NewGenerationPC:
def __init__(self, name, cpu, memory, ssd):
#self.name의 name은 NewGeneration의 객체에 속해있는 속성, 매개변수에서 받은 name
self.name = name
self.cpu = cpu
self.memory = memory
self.ssd = ssd
def doExcel(self):
print('excel run!!')
def doPhotoshop(self):
print('Photoshop run!!')
def printPCInfo(self):
print(f'name : {self.name}')
print(f'cpu : {self.cpu}')
print(f'memory : {self.memory}')
print(f'ssd : {self.ssd}')
#생성자 호출
myPC1 = NewGenerationPC('김준호', 'i7','16G','256G')
myPC1.printPCInfo()
friendPC1 = NewGenerationPC('rlatl', 'i3','8G','32G')
friendPC1.printPCInfo()
#객체 속성 변경
myPC1.cpu = 'i9'
myPC1.memory = '64G'
myPC1.ssd = '1T'
#변경된 속성 적용되어 출력
myPC1.printPCInfo()
name : 김준호
cpu : i7
memory : 16G
ssd : 256G
------------
name : rlatl
cpu : i3
memory : 8G
ssd : 32G
------------
name : 김준호
cpu : i9
memory : 64G
ssd : 1T
- 객체를 사용하기 위해서 변수를 만들었다.
myCar = Car('red',200)- 변수(myCar)는 객체(Car())와 메모리 내에 각각 다른 위치에 저장되어 있다.
- 즉, 변수에 직접 객체가 저장되는게 아니다.
- 객체가 생성 될 때 메모리 주소가 생성된다. 이 메모리 주소가 변수에 저장이 된다.
- 따라서, 변수를 이용해서 객체를 조작한건 정확히는 변수 안의 객체의 메모리주소를 이용해 조작했던 것
- 이런 변수를 [참조변수] 라고한다.
class Robot:
def __init__(self, color, height, weight):
self.color = color
self.height = height
self.weight = weight
def printRobotInfo(self):
print(f'Color :{self.color}')
print(f'height :{self.height}')
print(f'weight :{self.weight}')
#rb1에 Robot객체가 들어있는게 아니라 rb1이 객체주소를 참조하는 것이다.
rb1 = Robot('red',200,80)
rb2 = Robot('blue',300,120)
# 이렇게 복사를 한다면 rb1이 참조하고 있는 객체주소가 rb3에 저장되는 것
#따라서 rb3이랑 rb1은 같은 객체
rb3 = rb1
rb1.printRobotInfo()
rb2.printRobotInfo()
rb3.printRobotInfo()
#rb1객체 속성을 변경하면 rb3의 속성도 변경된다. 같은 객체주소를 참조하고 있으니까
rb1.color = 'gray'
rb1.height = 199
rb1.weight = 200
rb1.printRobotInfo()
rb2.printRobotInfo()
rb3.printRobotInfo()
Color :red
height :200
weight :80
Color :blue
height :300
weight :120
Color :red
height :200
weight :80
--------------------
Color :gray
height :199
weight :200
Color :blue
height :300
weight :120
Color :gray
height :199
weight :200
--------------------
- 얕은 복사 : [객체 주소]를 복사하는 것으로 객체 자체가 복사 되지는 않는다.
- 깊은 복사 : [객체] 자체를 복사하는 것으로 또 하나의 객체가 만들어 진다.
class TemCls: def __init__(self,n, s): self.number = n self.string = s def printClsInfo(self): print(f'number = {self.number}') print(f'string = {self.string}')
#얕은 복사
tc1 = TemCls(100,'hello')
tc2 = tc1
tc1.printClsInfo()
tc2.printClsInfo()
print(id(tc1))
print(id(tc2))
print('-'*15)
tc2.num = 3.14
tc1.printClsInfo()
tc2.printClsInfo()
<#id(): 주소를 읽을 수 있다.>
print(id(tc1))
print(id(tc2))
print('-'*15)
num = 100
str = hello
num = 100
str = hello
2799792540560
2799792540560
---------------
num = 3.14
str = hello
num = 3.14
str = hello
2799792540560
2799792540560
---------------
- 깊은 복사1. copy모듈 사용
import copy
#생성자 호출
tc1 = TemCls(10,'hello')
tc2 = copy.copy(tc1)
tc1.printClsInfo()
tc2.printClsInfo()
print('='*30)
tc2.number = 30
tc1.printClsInfo()
tc2.printClsInfo()
-결과에서 tc2 속성을 변경할 때 tc2단독으로 변경 된 것을 볼 수 있다.
num = 10
str = hello
num = 10
str = hello
==============================
num = 10
str = hello
num = 30
str = hello
import copy
scores = [1,2,3,4,5]
scoresCopy = []
scoresCopy = scores
print(f'{id(scores)}')
print(f'{id(scoresCopy)}')
#참조하는 주소가 같다 ==같은 객체 주소를 참조한다.
2265950669952
2265950669952
-깊은복사1. append()사용
import copy
scores = [1,2,3,4,5]
scoresCopy = []
for s in scores:
<#append() : ()안의 인수가 scoreCopy리스트에 추가된다.>
scoresCopy.append(scores)
print(f'{id(scores)}')
print(f'{id(scoresCopy)}')
#주소가 다르다 == 참조하는 객체 주소도 다르다
2543462730880
2543462501184
-깊은복사2. exrend()사용
scores = [9,8,5,7,6,10]
scoresCopy =[]
<#extend() : ()안의 값을 리스트에 추가한다.>
scoresCopy.extend(scores)
print(f'{id(scores)}')
print(f'{id(scoresCopy)}')
scores = [9,8,5,7,6,10]
scoresCopy =[]
scoresCopy = scores.copy()
print(f'{id(scores)}')
print(f'{id(scoresCopy)}')
- sort() : 리스트를 오름차순 정리
- pop(n) : n-1번째 값 제외한 리스트
plaOriSco = [8.7, 9.1, 8.9, 9.0, 7.9, 9.5, 8.8, 8.3 ]
plaCopSco = plaOriSco.copy()
#원본점수 오름차순 정리
plaOriSco.sort()
#복사한 점수 오름차순 정리 후 최저, 최고 제외
plaCopSco.sort()
plaCopSco.pop(0)
plaCopSco.pop()
#선수 원본점수, 최고최저점 뺀 리스트 출력
print(f'plaOriSco : {plaOriSco}')
print(f'plaCopSco : {plaCopSco}')
#원본 점수 총합, 평균
oriTot = sum(plaOriSco)
oriAvg = round(sum(plaOriSco)/len(plaOriSco),2)
print(f'Original Total: {oriTot}')
print(f'Original Average: {oriAvg}')
#복사 점수 총합, 평균
copTot = round(sum(plaCopSco),2)
#
copAvg = round(sum(plaCopSco)/len(plaCopSco),2)
#
print(f'Copy Total: {copTot}')
print(f'Copy Average: {copAvg}')
result = round(oriAvg - copAvg,2)
print(f'oriAvg - copAvg: {result}')
클래스는 또 다른 클래스를 상속해서 내 것 처럼 사용 할 수 있다.
class NormalCar:
def drive(self):
print('[NormalCar] drive called!!')
def back(self):
print('[NormalCar] back called!!')
<#TurboCar가 NormalCar를 상속 받는다>
class TurboCar(NormalCar):
def turbo(self):
print('[TurboCar] turbo() called!!')
myTurboCar = TurboCar()
myTurboCar.turbo()
myTurboCar.drive()
myTurboCar.back()
[TurboCar] turbo() called!!
[NormalCar] drive called!!
[NormalCar] back called!!
덧셈,뺄셈 기능이 있는 클래스를 만들고, 이를 상속하는 클래스를 만들어서 곱셈과 나눗셈 기능을 추가해보자.
class CalculatorPS:
def add(self, n1, n2):
return n1 +n2
def sub(self, n1, n2):
return n1 - n2
class CalculatorMD(CalculatorPS):
def mul(self,n1,n2):
return n1*n2
def div(self,n1,n2):
return n1/n2
myCal = CalculatorMD()
print(f'n1+n2 = {myCal.add(10,20)}')
print(f'n1-n2 = {myCal.sub(10,20)}')
print(f'n1*n2 = {myCal.mul(10,20)}')
print(f'n1/n2 = {myCal.div(10,20)}')
n1+n2 = 30
n1-n2 = -10
n1*n2 = 200
n1/n2 = 0.5
객체가 생성 될 때 생성자를 호출 하면 __init__()가 자동 호출 된다.
class Calculator:
#__init__()가 속성을 초기화 한다.
def __init__(self,n1,n2):
print('[Calculator] called')
self.num1 = n1
self.num2 = n2
#생성자 호출(__init__()가 호출)
cal = Calculator(10,20)
print(f'cal num1 = {cal.num1}')
print(f'cal num2 = {cal.num2}')
초기화 한다는 말은 첫 값을 정해 준다 라는 말과 동일(?)
super()사용
class P_Class:
def __init__(self,pNum1,pNum2):
print('[P_class] __init__ called!')
self.pNum1 = pNum1
self.pNum2 = pNum2
class C_Class(P_Class):
def __init__(self,cNum1,cNum2):
print('[C_Class] __init__ called!')
#상위 클래스(P_Class)의 이닛매소드도 사용하겠다
#P_Class.__init__(self, cNum1, cNum2)
#좀 더 세련되게 super()는 상위클래스, super()뒤 init에는 self생략
super().__init__(cNum1,cNum2)
self.cNum1 = cNum1
self.cNum2 = cNum2
cls = C_Class(10,20)
중간고사 클래스와 기말고사 클래스를 상속관계로 만들고 각각의 점수를 초기화 하자.
또한 총점 및 평균을 반환하는 기능도 만들어 보자
class MidExam:
def __init__(self, s1, s2, s3):
print(f'[MidExam] __init__()')
self.mid_kor_score = s1
self.mid_eng_score = s2
self.mid_mat_score = s3
def printScores(self):
print(f'mid_kor_score: {self.mid_kor_score}')
print(f'mid_eng_score: {self.mid_eng_score}')
print(f'mid_mat_score: {self.mid_mat_score}')
class EndExam(MidExam):
def __init__(self,s1, s2, s3, s4, s5, s6):
print('[EndExam] __init__()')
#상위클래스 MidExam의 __init__() 초기화
super().__init__(s1,s2,s3)
self.end_kor_score = s4
self.end_eng_score = s5
self.end_mat_score = s6
def printScores(self):
super().printScores()
print(f'end_kor_score: {self.end_kor_score}')
print(f'end_eng_score: {self.end_eng_score}')
print(f'end_mat_score: {self.end_mat_score}')
def getTotalScore(self):
total = self.mid_kor_score + self.mid_eng_score + self.mid_mat_score
total += self.end_kor_score + self.end_eng_score + self.end_mat_score
return total
def getAverageScore(self):
return self.getTotalScore()/6
exam = EndExam(85,90,88,75,85,95)
exam.printScores()
print(f'totalScore : {exam.getTotalScore()}')
print(f'AverageScore : {round(exam.getAverageScore(),2)}')
[EndExam] __init__()
[MidExam] __init__()
mid_kor_score: 85
mid_eng_score: 90
mid_mat_score: 88
end_kor_score: 75
end_eng_score: 85
end_mat_score: 95
totalScore : 518
AverageScore : 86.33
2개 이상의 클래스를 상속한다.
- #상속 받고 싶은 클래스 ','로 이어붙여 상속
class Car01:
def drive(self):
print('drive() method called')
class Car02:
def turbo(self):
print('turbo() method called')
class Car03:
def fly(self):
print('fly() method called')
#상속 받고 싶은 클래스 ','로 이어붙여 상속
class Car(Car01,Car02,Car03):
def __init__(self):
pass
myCar = Car()
myCar.drive()
myCar.turbo()
myCar.fly()
drive() method called
turbo() method called
fly() method called
하위 클래스에서 상위 클래스의 매서드를 재정의 하는 것
class Robot:
def __init__(self,c, h, w):
self.color = c
self.height = h
self.weight = w
def fire(self):
print('[미사일 발사]')
def printRobotInfo(self):
print(f'self.color ={self.color}')
print(f'self.height ={self.height}')
print(f'self.weight ={self.weight}')
class NewRobot(Robot):
def __init__(self, c, h, w):
super().__init__(c,h,w)
def fire(self):
print('레이저발사')
myRobot = NewRobot('red',200,300)
myRobot.printRobotInfo()
myRobot.fire()
self.color =red
self.height =200
self.weight =300
레이저발사
- 상위클래스에서 하위클래스에 메서드 구현을 강요하는 것.
- 더 자세히 말하면 상위 클래스에서는 매서드 선언만 하고 하위 클래스에서 해당 매서드 구현
하위 클래스들의 입맛에 맞게 매소드 구현을 하기 위해서
- abc 모듈에서 ABCMeta(), abstractmethod()를 import 한다.
- 해당 클래스에 metaclass=ABCMEta 를 상속해준다.
- 해당 기능 매소드 정의 전에 @absreactmethod 입력해준다.
- 하위 클래스에서 해당 기능 매소드를 구현
#추상클래스 명시에 필요한 모듈 import
from abc import ABCMeta
from abc import abstractmethod
#추상클래스 명시
class Airplane(metaclass=ABCMeta):
#추상클래스 명시, 기능이 구현되어 있지 않다.
@abstractmethod
def flight(self)
pass
def forward(self):
print('전진')
def backward(self):
print('후진')
class AirLine(Airplane):
def __init__(self,c):
self.color = c
#기능 구현
def flight(self):
print('시속 400km/h 비행')
al = AirLine('red')
al.flight()
시속 400km/h 비행
문법적인 문제는 없으나 실행 중 발생하는 예상하지 못한 문제
예외 관련 클래스는 Exception클래스를 상속한다.
예외 발생 예쌍 구문을 try ~ except로 감싼다.
n1 = 10
n2 = 0
#나눗셈은 0으로 나누지 못한다. ->예상 예외 구간
try:
print(f'n1 / n2 ={n1/n2}')
#예외가 발생하면 except 실행, 발생하지 않으면 계속 실행
except:
print('예상치 못한 문제 발생')
print('다음으로 프로그램 실행')
print(f'n1 + n2 ={n1+n2}')
print(f'n1 * n2 ={n1*n2}')
예상치 못한 문제 발생
다음으로 프로그램 실행
n1 + n2 =10
n1 * n2 =0
nums = []
n =1
while n<6:
try:
data = int(input('input number : '))
except:
print('예외 발생!')
continue
nums.append(data)
n +=1
print(f'nums : {nums}')
input number : 1
input number : 2
input number : f
예외 발생!
input number : 3
input number : b
예외 발생!
input number : 4
input number : 5
nums : [1, 2, 3, 4, 5]
try에서 예외 발생하면 except로 진행
try에서 예외 발생 않하면 else 진행
eveList = []; oddList = []; floatList =[]
n = 1
while n<6:
try:
num = float(input('input num'))
except:
print('예외 발생')
continue
else:
if num - int(num) != 0:
print('float number!')
floatList.append(num)
else:
if num % 2 == 0:
print('even number!')
eveList.append(int(num))
else:
print('odd number!')
oddList.append(int(num))
n+=1
print(f'eveList = {eveList}')
print(f'oddList = {oddList}')
print(f'floatList = {floatList}')
input num1
odd number!
input num2
even number!
input num3
odd number!
input num3.14
float number!
input numd
예외 발생
input num5
odd number!
eveList = [2]
oddList = [1, 3, 5]
floatList = [3.14]
예외 발생과 상관없이 항상 실행 하려고 할때
try:
inputdata = input('number:')
numInt = int(inputdata)
except:
print('예외 발생')
print('not number')
else:
if numInt % 2 == 0:
print('짝수')
else:
print('홀수')
finally:
print(f'inputdata : {inputdata}')
number:d
예외 발생
not number
inputdata : d