2024. 10. 31. 10:55ㆍ파이썬을 활용한 데이터 분석
클래스 변수와 인스턴스 변수
#클래스 변수와 인스턴스 변수
#한국사람을 나타내는 korean클래스 정의
class Korean:
country='한국'
#생성자
def __init__(self,name,age,address):
self.name=name
self.age=age
self.address=address
#클래스 변수: country
#인스턴스(객체변수) : name, age, address
#객체화
man1=Korean('정대만',25,'북산')
man2=Korean('이정환',25,'해남')
#객체(인스턴스 변수)
print(man1.name)
print(man1.age)
print(man1.address)
print(man2.name)
print(man2.age)
print(man2.address)
#클래스 변수
#클래스변수는 따로 self를 이용하지 않았는데도 객체별로 확인이 가능함
#객체가 모두 같은 값을 공유하고있기때문
#클래스변수는 객체와 같이 출력도 가능하고
print(man1.country)
print(man2.country)
#클래스명.클래스명 변수 방법으로도 호출이 가능하다(클래스 변수이기때문에)
print(Korean.country)
#하지만 객체(인스턴스)변수를 클래스명과 함께 호출할수없다
# print(Korean.name)이러면 에러발생
print(f"{man1.name}은 {man1.country}사람이다")
#클래스변수의 값이 변경되면 클래스변수를 공유하고있는 모든 객체의 값이 변경됨
#같은 변수를 공유하고있기때문!
클래스변수는 모든 객체(인스턴스)가 동일한 값을 사용할때 모든 객체들이 공유할 수 있는 변수로, 클래스명. 클래스변수명의 형태로 적는다. 인스턴스 변수는 self키워드를 붙여서 사용하는 변수로, 객체명.인스턴스 변수명의 형태로 적는다. 인스턴스 변수는self를 사용하고 클래스 변수는 사용하지 않는다. 인스턴스변수는 객체를 통해서만 접근 가능하며, 클래스 변수는 객체, 클래스명으로 접근 가능하다. 클래스명에 인스턴스 변수를 사용하려고 하면 오류가 발생한다. 위의쿼리에서 클래스변수는 country이다. 클래스변수는 따로 self처리를 하지 않아도 출력이 가능한것을 확인할 수 있다.
클래스메소드, 인스턴스 메소드, 정적메소드
인스턴스 메소드
#인스턴스 메소드
#인스턴스 메소드는 메소드 작성후 마지막에 self.매개변수명으로 정의한것을
#활용하여 했었것들을 메소드라고 함
#↓밑에 예시
# def info(self):
# print(f"제이름은{self.name}이고 집주소는 {self.adress}입니다")
인스턴스 메소드는 인스턴스 변수를 사용하는 메소드를 의미한다. 첫번째 매개변수에 self를 사용하여 인스턴스변수에 접근한다.
클래스 메소드
from types import ClassMethodDescriptorType
#클래스 메소드
class Korean:
country='한국' #클래스변수
@classmethod
def trip(cls,country):
if cls.country==country: #cls.country(Korean클래스의 클래스변수)==country(trip의 변수)
#self대신 cls라는 것을 사용. cls는 클래스변수를 받아오는 기능.
print('국내여행입니다')
else:
print("해외여행입니다")
Korean.trip('한국')
#클래스변수는 클래스명.메소드명/ 객체명.메소드명()으로사용
class band:
band_type='락'
@classmethod
def band_sing(cls,type):
if cls.band_type==type:
print(f"장르는{type}입니다")
else:
print(f'락을 들으세요...')
band.band_sing('락')
클래스메소드는 클래스 변수를 사용하는 메소드를 의미한다. self를 사용하지 않기때문에 인스턴스 변수에는 접근할수없지만 cls를 통해서 클래스변수에 접근할 수 있다. 클래스메소드는 객체나 클래스명으로 호출가능, 생성된 객체가 없어도 호출가능하며, @classmethod 데코레이터를 표시하고 작성해야한다. 첫번째 매개변수에 cls를 사용해야한다.
정적메소드
#정적메소드
class Korean:
country='한국'
@staticmethod
def staticmethod(): #정적메소드는 self나 cls처럼 반드시 작성해줘야하는 매개변수가따로 없음
return '정적메소드'
#매개변수가 없기때문에 return값이나 print()구문을 사용하여 이용가능
print(Korean.staticmethod())
#메소드를 실행시켰을때 정적메소드라는 반환값이 출력됨
#정적메소드
class Korean:
country='한국'
@staticmethod
def staticmethod(name,age): #정적메소드는 self나 cls처럼 반드시 작성해줘야하는 매개변수가따로 없음
print(name)
print(age)
return '정적메소드'
print(Korean.staticmethod('홍길동',25))
#매개변수를만들어주어도 가능.
#일반 사용자 정의함수 썼을때랑 방법이 동일
#밖에서 받아온 값들로만(매개변수) 값을 정의하는 경우에는 정적메소드를 사용하는것이 좋음
#객체를 만들지 않아도 이용가능하기때문
#일반 사용자 정의 함수처럼 정적메소드를 만들어 놓고 객체화시켜서 사용도 가능
p1=Korean
p1.name='홍길동'
p1.age=25
print(p1.name)
p1.country
print(f"{p1.name}은 {p1.age}살이며 {Korean.country}사람이다")
정적메소드는 self를 사용하지 않기때문에 인스턴스 변수를 사용할 수가 없다. 객체를 만들지 않아도 사용할 수 있다는 점에서 클래스메소드와 비슷하다. 인스턴스 변수, 클래스변수를 모두 사용하지 않는경우에 적절하다. 반드시 작성해야하는 매개변수가 없으며, 객체 또는 클래스명을 호출할 수 있고, 생성된 객체가 없어도 호출가능하다. 정적메소드의 경우 @staticmethod데코레이터를 표시하고 작성한다.
상속
#상속
#<부모클래스 생성>
#부모 클래스의 생성자
class Person:
def __init__(self,name):
self.name=name
#<부모 클래스의 메소드>
def eat(self,food):
print(f"{self.name}이/가 {food}를 먹습니다")
#food는 인스턴스 매개변수가 아님. self가 붙은 name은 객체를 만들어서
#이름값을 저장할 수있지만, food처럼 self를 지정하지 않는다면
#food의 값은 특정한 객체에 저장되지 않으며 메소드를 호출 할때마다
#food에 있는 값이 바뀔 수 있음
#자식 클래스 생성
class Student(Person):
#자식클래스의 생성자
def __init__(self,name,school):
#자식클래스 생성할때 부모클래스의 매개변수에 name이 있기때문에
#자식클래스 매개변수에도 name이 있어야함
super().__init__(name)#부모클래스를 불러온다는 의미이므로 부모클래스에서
#지정해준 매개변수들은 전부 순서까지 동일하게 적어야함
#만약 부모테이블에서 def __init__(self,name,age,adderss)가 있었다면
#super적을때 자식클래스에서도 전부다 순서에 맞게 적어야 한다는것!
self.school=school
#name은 부모에게서 상속받아온것이기때문에 따로 적지 않음. 이미 가지고 있기때문!
def study(self):
print(f"{self.name}은/는 {self.school}에서 공부합니다")
#<부모클래스의 속성>
#데이터 속성: name
#메소드: eat(생성자 제외)
#<자식클래스의 속성>
#데이터 속성: name(상속받은것), school(직접 추가)
#메소드: eat(상속받은것),study(직접 추가)
#부모클래스의 객체
pr1=Person('홍길동')
pr1.eat('떡볶이')
#자식클래스의 객체
stud1=Student('해리포터','호그와트')
stud1.study()
stud1.eat('감자')#est메소드 정상실행. 자식클래스의 객체로 부모클래스의 메소드 사용
# pr1.study() 부모클래스가 자 식클래스의 메소드를 가질 수 없음
상속은 기존에 사용중인 클래스를 바탕으로 새로운 요소를 추가해서 클래스를 다시 정의하는 것을 말한다. 새로운 클래스는 작성하지 않더라도 기존 클래스의 데이터 속성, 메소드를 상속받는 구조로 되어있기때문에 전부 가지고 있다. 기존 클래스에서 새롭게 필요한 데이터속성, 메소드를 추가해서 코드 작성가능하며 이를 상속과 계승관계라고 부른다. 부모 클래스를 만들어줬다면, 자식클래스를 만들때 자식클래스명(부모클래스명)으로 적어주어야 상속과 계승관계가 성립되며, 자식클래스에 super().__init__(부모클래스 매개변수)를 적어, 부모클래스에있던 매개변수와 메소드등을 받아올 수 있도록 생성자를 재정의 해주어야한다. 이렇게 부모클래스와 자식클래스를 작성해주었다면 자시글래스에서 정의하지않은 부모클래스의 메소드를 사용할 수 있는 것을 확인할 수 있다.
부모 클래스의 인스턴스
#부모 클래스의 인스턴스
print(isinstance(pr1,Person))
#isinstance(객체명, 클래스명) <-앞에 객체가 뒤에 클래스의 인스턴스냐고 묻는것
print(isinstance(pr1,Student)) #부모객체는 자식 클래스의 인스턴스가 될수없기에 False반환
print(isinstance(stud1,Person)) #자식객체는 부모 클래스의 인스턴스가 될 수 있음
print(isinstance(stud1,Student))
부모클래의 인스턴스인지 아닌지 확인하는 방법으로는 isintance(객체명, 클래스명)의 방법으로 적어, 확인하는 방법이 있다. 앞의 객체가 뒤의 클래스의 인스턴스냐고 물어보는 구문이기때문에 논리형으로 출력된다. 이때 자식객체는 부모클래스의 인스턴스가 될 수 있지만 부모객체는 자식 클래스의 인스턴스가 될 수 없는것을 확인할 수 있다.
오버라이딩
#오버라이딩
#자식클래스의 메소드가 부모클래스의 메소드를 다시 재정의해서 사용하는것을 의미
#부모클래스 Animal
#데이터 속성: 이름(name), 나이:(age)
#메소드 : 동물객체별 소리를 출력하는 메소드 : make_soud
class Animal:
def __init__(self,name,age):
self.name=name
self.age=age
def make_sound(self):
pass #자식클래스에서 오버라이딩해서 사용할 것이기때문에 pass
#Animal클래스를 상속받는 Dog클래스
#메소드 : 산책가자를 출력하는 메소드 :walk()
class Dog(Animal):
def __init__(self,name,age):
super().__init__(name,age)
def walk(self):
print(f"{self.name}이랑 산책가자!")
#부모클래스의 메소드인 make_soud재정의
def make_sound(self):
print(f"{self.name}이가 멍멍!")
#Animal 클래스를 상속받는 Cat클래스
#메소드: 잘거야를 출력하는 메소드 : sleep
class Cat(Animal):
def __init__(self,name,age):
super().__init__(name,age)
def sleep(self):
print(f"{self.name}는 잘거야")
def make_sound(self):
print(f"{self.name}는 야옹!!")
오버라이딩은 자식클래스의 메소드가 부모클래스의 메소드를 다시 재정의 해서 사용하는 것을 의미한다. 즉, 변수를 다시 재정의하는것과 비슷하다. 먼저 부모 클래스를 정의한 후 자식클래스인 cat과 dog클래스를 정의해준다.
#강아지, 고양이 객체생성후 매소드 호출
dog=Dog('멍멍이',3)
dog.make_sound()
dog.walk()
# dog.sleep()
#'Dog' object has no attribute 'sleep' 다른 자식 클래스에서 만든건 사용못함
print()
cat=Cat('고양이',4)
cat.sleep()
cat.make_sound()
그 후 자식 클래스인 cat과 dog객체 생성후 메소드를 호출해주면 각각 오버라이딩 해준 문구로 출력되는것을 확인할 수 있다.
예외처리
#예외처리
#비정상적으로 프로그램이 종료되는것을 막고
#사용자에게 발생한 문제을 설명하기 위함
num1=3
num2=0
# print(num1/num2)
# ZeroDivisionError: division by zero : 0으로 나누면 안된다는 오류
#0으로는 무언갈 나눌수가 없기때문에
print('출력끝')
if num2==0:
print('0으로 나눌 수 없습니다')
else:
print('num1/num2')
#보통 이런 오류는 조건문과 같은 다른 방법을 사용해서 오류 해결이 가능하지만
#매번 이런식으로 조건문과 다른 방법들을 이용해서 모든 오류를 처리할 수 없음
#그렇기 때문에 예외처리라는 것을 사용함
파이썬에서 발생하는 각종 오류를 처리하기 위해 예외처리라는것을 사용한다. 예외가 발생했을때 프로그램이 정상적으로 종료될 수 있도록 다루는 행위를 예외처리라고 부른다. 여기서 예외는 개발자가 직접 처리할 수 있는 간단한 문제를 말하며, 오류는 개발자가 처리할 수 없는 복잡한 문제를 말한다. 예외처리를 왜 사용해야하냐면, 발생된 문제로 인해 프로그램이 비정상적으로 종료되는것을 막고, 사용자에게 발생한 문제에 대한 정보를 전달하기 위해 사용한다. 위의 쿼리문 처럼 0으로 나눴을때 발생하는 오류를 방지하기 위해서 if문을 사용했다. 조건문을 사용하여 에러가 나는것을 방지하긴 하였으나, 매번 조건문을 이용하여 에러를 해결하기에는 한계가 있다. 이럴때 사용하는것이 try~except예외문이다.
try~except
#예외처리
try:
# try에는 예외가 발생될 것으로 예상되는 문장
num1=int(input('첫번째 정수입력: '))
num2=int(input('두번째 정수입력: '))
print(f"{num1}/{num2}={round(num1/num2,2)}") #예외(오류)없이 정상실행되면 나올 문장
except ZeroDivisionError: #try블록안에서 ZeroDivisionError 오류가 발생했을때
print("0으로 나눌 수 없습니다") #여기있는 문장을 실행시키겠다
except ValueError:
print("정수만 입력할 수 있습니다")
except Exception:
print('알수없는 예외가 발생했습니다')
try는 예외가 발생할수 있는 문장을 적는다. try문 영역안에서 예외가 발생하면 예외가 발생시에 실행할 문장을 except안에 적어서 오류가 발생했을때 해당문장이 실행될 수 있도록 해야한다. except는 여러개를 추가할 수 있다. 위의 쿼리에서 정수만 입력되어야하는데 정수가 입력되지않아, 벨류에러가 발생한상황이다. 이때 에러가발생하는것이 아니라 except문에 있는 문장이 실행된것을 확인할 수 있다.
try~except~else~finally
#예외처리
#try~except~else~finally
li=['h','e','l','l','o']
print(li,type(li))
# print(li[100]) #인덱스 에러 발생
#IndexError: list index out of range
try:
print(li[0])
print(li[100])
except IndexError:
print('범위에 맞는 인덱스를 입력하세요')
else:
print(f"li리스트의 인덱스 범위는 {li[0]}입니다")
finally:
print('프로그램 종료')
try~except~else~finally구문은 else문에 예외가 발생하지 않으면 실행할 문장을 적고 finally에는 예외발생유무와 상관없이 실행되는 문장을 적는다. 위의 쿼리문에서 범위에 맞는 인덱스가 입력되지 않았기때문에 except문에 적힌 문장이 실행된 것이고 예외발생유무와 상관없이 finally에 있는 문장역시 출력된것을 확인 할 수 있다.
예외 강제 발생
#예외강제 발생
num=int(input('1~5사이의 숫자를 입력하세요'))
#사실 그냥 문구로만 지정해준것이기때문에 5벗어나도 오류 안남
#근데 벗어났을때 오류를 내고 싶다면
if num>=5 or num<=1:
raise ValueError('범위를 벗어났습니다.')
예외를 강제로 발생시켜야하는 경우에는 파이썬이 발생시킨 오류가 아니라 사용자가 발생시키고 싶은 경우에 사용한다. 즉, 실행되면 안되는데 코드문이 실행됐을 경우, 억지로 오류를 내서 코드를 멈춰야하는 경우가 이에 속한다. 강제로 예외를 발생시킬때는 raise 예외명 ('예외시 출력될 문장')의 형태로 적는다.
위의 쿼리의 경우 1~5사이의 숫자만 입력이 되어야하는 코드를 작성했다. 하지만 다른 숫자가 입력이 되더라도 오류가 발생하는 상황은 아니라, 범위를 벗어났을때 오류가 발생하도록 억지로 만들어주어야한다. if문을 사용하여 5이상의 숫자가 입력됐을때 raise를 적어 예외를 만들어주었다.
상속 클래스 실습
#<밴드소개서_상속class연습>
class Band:
def __init__(self,name,member,song):
self.name=name
self.member=member
self.song=song
def band_info(self):
print("===오늘의 밴드소개===")
print(f"밴드명: {self.name}")
print(f"멤버수: {self.member}명")
print(f"참가곡: {self.song}")
def cute(self,cute):
print(f"{self.name}의 오늘 입덕멤은 {cute}입니다^^")
print()
class Band_prize(Band):
def __init__(self,name,member,song,prize):
super().__init__(name,member,song)
self.prize=prize
def band_info(self): #오버라이딩
super().band_info()
print(f"수상갯수: {self.prize}개")
class Sing(Band):
def __init__(self,name,member,song,sing):
super().__init__(name,member,song)
self.sing=sing
def band_info(self,licys):
super().band_info()
print(f"오늘의 {self.sing}노래의 한줄 가사는 {licys}입니다! 오늘도 노래와 함께 모두 평안한 하루!")
#부모 클래스를 통해 각각 3가지의 밴드 소개서 만들기
b1=Band('유다빈 밴드',4,'항해')
b1.band_info()
b1.cute('유다빈')
bp=Band_prize('실리카겔',4,'루데자케이루',5)
bp.band_info()
bp.cute('김한주')
bs=Sing('롤링쿼츠',4,'빅토리','Fearlss')
bs.band_info('\'자 어때 기분이 별거 아니지? 이정돈 어림없지\'')
bs.cute('지영')
학습일기
드디어 파이썬 기초가 끝났다..!!! 이제 부터 활용+심화부분 복습으로 들어간다...후..그래도 사실 파이썬 기초 부분에서 클래스 부분은 거의 잊은게 많았는데 이렇게 티스토리에 정리하면서 다시한번 더 복기하고 이번기회에 확실히 이해못했던 부분도 이해하고 넘어가서 좋았다. 다시한번 기초복습의 중요성을 느끼며...활용+심화도 끝까지 해보자..!
'파이썬을 활용한 데이터 분석' 카테고리의 다른 글
AI데이터 분석_ 파이썬 기초10_클래스(전역,지역변수, global키워드, 표준모듈 사용법) (1) | 2024.10.26 |
---|---|
AI데이터 분석_ 파이썬 기초9_문자열 메소드와 사용자 정의 함수 (0) | 2024.09.11 |
AI데이터 분석_ 파이썬 기초8_파이썬의 내장함수 종류 (0) | 2024.09.08 |
AI데이터 분석_ 파이썬 기초7_튜플,세트,딕셔너리(의 값수정, 메소드, 함수, 집합연산,실습) (0) | 2024.09.08 |
AI데이터 분석_ 파이썬 기초6(리스트 값 수정, 리스트의 함수, 리스트의 메소드) (0) | 2024.09.05 |