혼공파 6주

JIN·2023년 8월 20일
0

혼공단 10기

목록 보기
6/7
post-thumbnail

🔎 외부 모듈


모듈 설치하기

  • 외부 모듈은 Window + R 키를 눌러 CMD에서 실행해야 함
  • 이미 설치되어 있는 모듈을 다시 한 번 더 설치하면 '이미 설치되어 있습니다.'라는 메시지를 출력함

    pip install 모듈 이름


pip

  • 파이썬 패키지 관리 시스템
  • 특정 버전의 모듈을 설치하거나 설치한 모듈을 제거하는 기능 등을 모두 지원함

Beautiful Soup 모듈

  • 파이썬 웹 페이지 분석 모듈
  • 아래의 코드는 bs4모듈의 BeautifulSoup() 함수의 매개변수로 HTML문자열과 "html.parser"라는 문자열을 넣으면 BeautifulSoup라는 특수한 객체 리턴함
# 모듈 읽어 들임
from urllib import request
from bs4 import BeautifulSoup

# urlopen() 함수로 기상청의 전국 날씨 읽음
target = request.urlopen("http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108")

# BeautifulSoup을 사용해 웹 페이지 분석
soup = BeautifulSoup(target, "html.parser")

# location 태그 찾기
for location in soup.select("location"):
    # 내부의 city, wf, tmn, tmx 태그 찾아 출력
    print("도시:", location.select_one("city").string)
    print("날씨:", location.select_one("wf").string)
    print("최저기온:", location.select_one("tmn").string)
    print("최고기온:", location.select_one("tmx").string)
    print()
  • select() : 태그를 여러 개 선택할 경우에 사용
  • select_one() : 태그를 하나만 선택할 때 사용

Flask 모듈

  • 작은 기능만을제공하는 웹 개발 프레임워크

Django 모듈

  • 매우 다양한 기능을 제공하는 웹 개발 프레임워크

제어 역전

  • 확실하게 구분하자면 제어역전(IoC; Inversion of Control)여부에 따라서 달라진다.
  • 제어 역전 : 제어가 역전된다는 뜻

라이브러리(library)

  • 개발자가 모듈의 기능을 호출하는 형태의 모듈
  • 정상적인 제어를 하는 모듈

프레임워크(framework)

  • 모듈이 개발자가 작성한 코드를 실행하는 형태의 모듈
  • 제어 전이 발생하는 모듈

데코레이터

  • @로 시작하는 구문
  • 데코레이터는 만드는 방법에 따로 함수 데코레이터와 클래스 데코레이터로 나뉨

함수 데코레이터의 기본

  • 함수에 사용되는 데코레이터
  • 대상 함수의 앞 뒤에 꾸밀 부가적인 내용, 혹은 반복할 내용을 데코레이터로 정의해서 손쉽게 사용할 수 있도록 한 것을 말함
# hello 앞에 인사가 시작되었습니다.
# hello 뒤에 인사가 종료되었습니다 출력하는 함수

# 함수 데코레이터 생성
def test(function):
    def wrapper():
        print("인사가 시작되었습니다.")
        function()
        print("인사가 종료되었습니다.")
    return wrapper
    
    # 데코레이터 붙여 함수 만듦
@test
def hello():
    print("hello")

# 함수 호출
hello()


# 실행 결과
----------
인사가 시작되었습니다.
hello
인사가 종료되었습니다.
  • 데코레이터를 사용하면 functools라는 모듈을 사용할 수 있음
  • 함수 데코레이터를 사용할 때 매개변수 등을 전달할 수 있어 구문이 많아질 때 가독성도 높이고 매우 유용하게 사용 가능함
# 모듈 가져옴
from functools import wraps

# 함수로 데코레이터 생성
def test(function):
    @wraps(function)
    def wrapper(*arg, **kwargs):
        print("인사가 시작되었습니다.")
        function(*arg, **kwargs)
        print("인사가 종료되었습니다.")
    return wrapper



🔎 모듈 만들기


패키지(package)

  • 복잡하고 구조화된 모듈을 만 들 때 사용함

name == "main"


name

  • 프로그램의 진입점을 엔트리포인트(entry point)또는 메인(main)이라고 부름
  • 엔트리 포인트 또는 메인 내부에서 name은 "main"임
__name__

# 실행 결과
----------
__main__

모듈의 __name__

  • 엔트리포인트가 아니지만 엔트리 포인트 파일 내에서 import 되었기 때문에 모듈 내 코드가 실행됨
  • __name__을 출력하면 모듈의 이름을 나타냄
# 모듈 이름 출력하는 모듈 만들기
# main.py파일

import test_module

print("# 메인의 __name__출력하기")
print(__name__)
print()

# 실행 결과
----------
# 메인의 __name__출력하기
__main__
# test_module.py 파일
print("# 모듈의 __name__ 출력하기")
print(__name__)
print()

# 실행 결과
----------
# 모듈의 __name__ 출력하기
test_module

# 메인의 __name__ cnffurgkrl
__main__

__name__활용하기

  • 엔트리 포인트 파일 내부에서는 __name__이 "__main__"이라는 값을 가짐
  • 이를 활용하면 현재 파일이 모듈로 실행되는지, 엔트리 포인트로 실행되는지 확인 가능함
PI = 3.141592

def number_input():
    output = input("숫자 입력> ")
    return float(output)

def get_circumference(radius):
    return 2 * PI * radius
def get_circle_area(radius):
    return PI * radius * radius

print("get_circumference(10):", get_circumference(10))
print("get_circle_area(10):", get_circle_area(10))
import test_module as test

radius = test.number_input()
print(test.get_circumference(radius))
print(test.get_circle_area(radius))

# 실행 결과
----------
get_circumference(10): 62.83184
get_circle_area(10): 314.1592
숫자 입력> 10
62.83184
314.1592

패키지

  • 모듈이 모여서 구조를 이루는 것

__init__.py 파일

  • 어떤 처리를 수행해야 하거나패키지 내부의 모듈들을 한꺼번에 가져오고 싶을 때 파일을 생성하여 사용함
  • 해당 폴더가 패키지임을 알려주고, 패키지와 관련된 초기화 처리를 하는 파일
  • __init__.py에 __all__이라는 이름의 리스트를 만드는데, 이 리스트에 지정한 모듈들이 from <패키지 이름> import *를 할 때 전부 읽어 들여짐

텍스트 데이터

  • text data
  • 내부적으로는 이진수로 저장되지만, 우리가 쉽게 읽을 수 있는 텍스트로 변환될 수 있는 이진수 데이터

바이너리 데이터

  • binary data
  • 텍스트 에디토로 열었을 때 의미를 이해할 수 없으며, 전용 에디터를 사용해서만 편집할 수 있는 데이터



클래스의 기본


객체 지향 프로그래밍(Object Oriented Programming)

  • 프로그램을 개발하는 기법으로 부품에 해당하는 객체들을 먼저 만들고, 이것들을 하나씩 조립 및 연결해서 전체 프로그램을 완성하는 기법
  • 객체와 관련된 코드를 분리할 수 있게 하는 것이 객체 지향 프로그래밍의 핵심
  • 객체 지향 프로그래밍의 특징 : 상속, 다형성, 캡슐화

객체

  • 여러 가지 속성을 가질 수 있는 대상
  • 프로그래밍 언어에서는 속성을 가질 수 있는 모든 것을 '객체'라고 부름
# 객체 만들기
# 학생 리스트를 선언함
students = [
    {"name":"윤인성", "korean":87, "math":98, "english":88, "science":95},
    {"name":"연하진", "korean":92, "math":98, "english":96, "science":98},
    {"name":"구지연", "korean":76, "math":96, "english":94, "science":90},
    {"name":"나선주", "korean":98, "math":92, "english":96, "science":92},
    {"name":"윤아린", "korean":95, "math":98, "english":98, "science":98},
    {"name":"윤명월", "korean":64, "math":88, "english":92, "science":92}
]

# 학생을 한 명씩 반복함
print("이름", "총점", "평균", sep="\t")

for student in students:
    # 점수의 총합과 평균을 구함
    score_sum = student["korean"] + student["math"] +\
        student["english"] + student["science"]
    score_average = score_sum / 4
    # 출력
    print(student["name"], score_sum, score_average, sep="\t")

# 실행 결과
----------
이름	총점	평균
윤인성	368	92.0
연하진	384	96.0
구지연	356	89.0
나선주	378	94.5
윤아린	389	97.25
윤명월	336	84.0
  • 위의 코드에서는 학생이 객체가 됨

클래스(class) 선언하기

  • 클래스는 객체에 포함할 변수와 함수를 미리 정의한 것이며 객체의 설계도에 해당함

    class 클래스 이름:
    . . . . 클래스 내용

  • 이렇게 만들어진 클래스는 클래스 이름과 같은 함수(생성자)를 사용해서 객체를 만듦

    인스턴스 이름(변수 이름) = 클래스 이름() ---> 생성자 함수라고 부름

  • 이러한 클래스를 기반으로 만들어진 객체를 인스턴스(instence)라고 부름

# 클래스 선언
class Student:

### 생성자(constructor)
- 클래스 이름과 같은 함수
- 클래스 내부에__init__이라는 함수를 만들면 객체를 생성할 때 처리를 작성할 수 있음
> class 클래스 이름:
. . . . def __init__(self, 추가적인 매개변수):
. . . . . . . . pass
- 클래스 내부의 함수는 첫 번째 매개변수로 반드시 self를 입력해야 함

### self
- self는 '자기 자신'을 나타내는 딕셔너리라고 생각하면 됨
- self가 가지고 있는 속성과 기능에 접근할 때는 self.<식별자> 형태로 접근함
- self는 키워드가 아니라 단순한 식별자 이므로, 변수 이름을 활용해도 됨
- 그러나 모든 파이썬 개발자가 self라는 이름을 사용하고 있으므로 기본 규칙을 지키는 것이 좋음
```py
# 클래스 선언
class Student:
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science

# 학생 리스트 선언
students = [
    Student("윤인성", 87, 98, 88, 95),
    Student("연하진", 92, 98, 96, 98),
    Student("구지연", 76, 96, 94, 90),
    Student("나선주", 76, 96, 94, 90),
    Student("윤아린", 95, 98, 98, 98),
    Student("윤명월", 64, 88, 92, 92)
]

# Student 인스턴스의 속성에 접근하는 방법
students[0].name
students[0].korean
students[0].math
students[0].english
students[0].science

소멸자(destructor)

  • 인스턴스가 소멸될 때 호출되는 함수

메소드(method)

  • 클래스가 가지고 있는 함수
  • 첫 번째 매개변수로 self를 넣어야 한다.

    class 클래스 이름:
    . . . . def 메소드 이름(self, 추가적인 매개변수):
    . . . . . . . . pass

# 클래스 내부에 함수(메소드)선언

# 클래스 선언
class Student:
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
        
    def get_sum(self):
        return self.korean + self.math +\
            self.english + self.science
    
    def get_average(self):
        return self.get_sum() / 4
    
    def to_string(self):
        return "{}\t{}\t{}".format(\
            self.name, \
                self.get_sum(), \
                    self.get_average())
        
# 학생 리스트 선언
students = [
    Student("윤인성", 87, 98, 88, 95),
    Student("연하진", 92, 98, 96, 98),
    Student("구지연", 76, 96, 94, 90),
    Student("나선주", 76, 96, 94, 90),
    Student("윤아린", 95, 98, 98, 98),
    Student("윤명월", 64, 88, 92, 92)
]

# 학생을 한 명씩 반복
print("이름", "총점", "평균", sep="\t")
for student in students:
    # 출력
    print(student.to_string())

# 실행 결과
----------
이름	총점	평균
윤인성	368	92.0
연하진	384	96.0
구지연	356	89.0
나선주	356	89.0
윤아린	389	97.25
윤명월	336	84.0



🔎 클래스의 추가적인 구문


상속(inheritance)

  • 상위(부모) 객체를 기반으로 하위(자식) 객체를 생성하는 관계
  • 상위 객체는 자기가 가지고 있는 변수와 함수를 하위 객체에 물려주어 하위 객체가 사용할 수 있도록 함
    • 부모(parent class, super class, 상위 클래스): 해당 클래스에 선언된 변수와 함수를 물려주는 클래스
    • 자식(child class, sub class, 하위 클래스) : 다른 클래스로부터 물려받고자 하는 클래스

다중 상속

  • 다른 누군가가 만들어 놓은 형태를 졸비해서 내가 원한느 것을 만드는 것

어떤 클래스의 인스턴스인지 확인하기

  • 객체(instance)가 어떤 클래스로부터 만들어졌는지 확인할 수 있도록 ininstance()함수를 제공함
  • isinstance() 함수는 첫 번째 매개변수에 객체(instance), 두 번째 매개변수에 클래스를 입력함
  • isinstance()함수는 하나의 리스트로 여러 종류의 데이터를 다룰 수 있음

    isinstance(인스턴스, 클래스)

  • 인스턴스가 해당 클래스를 기반으로 만들어졌다면 True, 전혀 상관이 없는 인스턴스와 클래스라면 False를 리턴함
# 클래스 선언
class Student:
    def __init__(self):
        pass

# 학생 선언
student = Student()

# 인스턴스 확인하기
print("isinstance(student, Student):", isinstance(student, Student))

# 실행 결과
----------
isinstance(student, Student): True   # student는 Student 클래스를 기반으로 만들었으므로 True를 출력함

단순한 인스턴스 확인

  • 단순한 인스턴스라면 'type(인스턴스) == 클래스' 형식으로 사용 가능함
# isinstance() 함수와 type()함수로 확인하는 것의 ㅊ아ㅣ

# 클래스 선언
class Human:
    def __init__(self):
        pass
class Student(Human):
    def __init__(self):
        pass

# 학생 선언
student = Student()

# 인스턴스 확인
print("isinstance(student, Human):", isinstance(student, Human))
print("type(student) == Human:", type(student) == Human)

# 실행 결과
----------
isinstance(student, Human): True
type(student) == Human: False
  • student 클래스는 Human 클래스를 상속받아서 만들었음
  • isinstance() 함수는 이러한 상속 관계까지 확인함
  • 반면 type()함수를 사용한 확인은 이러한 상속 관계를 확인하지 않음

특수한 이름의 메소드

  • __<이름>__() 형태로 특수한 상황에 자동으로 호출되도록 만들어 졌음
# __str__() 함수

# 클래스 선언
class Student:
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science

    def get_sum(self):
        return self.korean + self.math +\
            self.english + self.science
    
    def get_average(self):
        return self.get_sum() / 4
    
    def __str__(self):
        return "{}\t{}\t{}".format(\
            self.name, \
                self.get_sum(), \
                    self.get_average())
        
# 학생 리스트 선언
students = [
    Student("윤인성", 87, 98, 88, 95),
    Student("연하진", 92, 98, 96, 98),
    Student("구지연", 76, 96, 94, 90),
    Student("나선주", 76, 96, 94, 90),
    Student("윤아린", 95, 98, 98, 98),
    Student("윤명월", 64, 88, 92, 92)
]

# 학생을 한 명씩 반복
print("이름", "총점", "평균", sep="\t")
for student in students:
    print(str(student))

# 실행 결과
----------
이름	총점	평균
윤인성	368	92.0
연하진	384	96.0
구지연	356	89.0
나선주	356	89.0
윤아린	389	97.25
윤명월	336	84.0

크기를 비교하는 함수 이름

이름영어설명
eqequal같다
nenot equal다르다
gtgreater than크다
gegreater than of equal크거나 같다
ltless than작다
leless than or equal작거나 같다
# 크기 비교 함수

# 클래스 선언
class Student:
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
        
    def get_sum(self):
        return self.korean + self.math +\
            self.english + self.science
    
    def get_average(self):
        return self.get_sum() / 4
    
    def __str__(self):
        return "{}\t{}\t{}".format(\
            self.name,
            self.get_sum(),
            self.get_average())
    
    def __eq__(self, value):
        return self.get_sum() == value.get_sum()
    def __eq__(self, value):
        return self.get_sum() != value.get_sum()
    def __eq__(self, value):
        return self.get_sum() > value.get_sum()
    def __eq__(self, value):
        return self.get_sum() >= value.get_sum()
    def __eq__(self, value):
        return self.get_sum() < value.get_sum()
    def __eq__(self, value):
        return self.get_sum() <= value.get_sum()
    
# 학생 리스트 선언
students = [
    Student("윤인성", 87, 98, 88, 95),
    Student("연하진", 92, 98, 96, 98),
    Student("구지연", 76, 96, 94, 90),
    Student("나선주", 76, 96, 94, 90),
    Student("윤아린", 95, 98, 98, 98),
    Student("윤명월", 64, 88, 92, 92)
]

# 학생 선언
student_a = Student("윤인성", 87, 98, 88, 95),
student_b = Student("연하진", 92, 98, 96, 98),

# 출력
print("student_a == student_b = ", student_a == student_b)
print("student_a != student_b = ", student_a != student_b)
print("student_a > student_b = ", student_a > student_b)
print("student_a >= student_b = ", student_a >= student_b)
print("student_a < student_b = ", student_a < student_b)
print("student_a <= student_b = ", student_a <= student_b)

# 실행 결과
----------
student_a == student_b =  True
student_a != student_b =  False
student_a > student_b =  False
student_a >= student_b =  True
student_a < student_b =  False
student_a <= student_b =  True

클래스 변수

  • class 구문 바로 아래의 단계에 변수를 선언하기만 하면 됨
  • 클래스 변수 만들기

    class 클래스 이름:
    . . . . 클래스 변수 = 값

  • 클래스 변수에 접근하기

    클래스 이름.변수 이름

# 클래스 선언
class Student:
    count = 0

    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
    
        # 클래스 변수 설정
        Student.count += 1
        print("{}번째 학생이 생성되었습니다.".format(Student.count))

# 학생 리스트 선언
students = [
    Student("윤인성", 87, 98, 88, 95),
    Student("연하진", 92, 98, 96, 98),
    Student("구지연", 76, 96, 94, 90),
    Student("나선주", 76, 96, 94, 90),
    Student("윤아린", 95, 98, 98, 98),
    Student("윤명월", 64, 88, 92, 92)
]

# 출력
print()
print("현재 생성된 총 학생 수는 {}명입니다.".format(Student.count))

# 실행 결과
----------
1번째 학생이 생성되었습니다.
2번째 학생이 생성되었습니다.
3번째 학생이 생성되었습니다.
4번째 학생이 생성되었습니다.
5번째 학생이 생성되었습니다.
6번째 학생이 생성되었습니다.

현재 생성된 총 학생 수는 6명입니다.

클래스 함수

  • 클래스 변수처럼 그냥 클래스가 가진 함수

  • 일반적인 함수로 만드나 클래스 함수로 만드나 사용에는 큰 차이가 없음

  • '클래스가 가진 기능'이라고 명시적으로 나타내는 것 뿐

  • 생성하는 방법 : @classmethod 부분을 데코레이터라고 부름

  • 클래스 함수 만들기

    class 클래스 이름:
    . . . . @classmethod
    . . . . def 클래스 함수(cls, 매개변수): ---> cls이외에 원하는 이름을 사용해도 되지만, 관례적으로 cls 사용함
    . . . . . . . . pass

  • 클래스 함수 호출하기

    클래스 이름.함수 이름(매개변수)

# 클래스 선언
class Student:
    # 클래스 변수
    count = 0
    students = []

    # 클래스 함수
    @classmethod
    def print(cls):
        print("------ 학생 목록 ------")
        print("이름\t총점\t평균")
        for student in cls.students:
            print(str(student))
        print("------ ------ ------")

    # 인스턴스 함수
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
        Student.count += 1
        Student.students.append(self)

    def get_sum(self):
        return self.korean + self.math +\
            self.english + self.science
    
    def get_average(self):
        return self.get_sum() / 4
    
    def __str__(self):
        return "{}\t{}\t{}".format(\
            self.name,
            self.get_sum(),
            self.get_average())

# 학생 리스트 선언
Student("윤인성", 87, 98, 88, 95),
Student("연하진", 92, 98, 96, 98),
Student("구지연", 76, 96, 94, 90),
Student("나선주", 76, 96, 94, 90),
Student("윤아린", 95, 98, 98, 98),
Student("윤명월", 64, 88, 92, 92),
Student("김미화", 82, 86, 98, 88),
Student("김연화", 88, 74, 78, 92),
Student("박아현", 97, 92, 88, 95),
Student("서준서", 45, 52, 72, 78)

# 현재 생성된 학생 모두 출력
Student.print()

# 실행 결과
----------
------ 학생 목록 ------
이름	총점	평균
윤인성	368	92.0
연하진	384	96.0
구지연	356	89.0
나선주	356	89.0
윤아린	389	97.25
윤명월	336	84.0
김미화	354	88.5
김연화	332	83.0
박아현	372	93.0
서준서	247	61.75
------ ------ ------

가비지 컬렉터(garbage collector)

  • 더 이상 사용할 가능성이 없는 데이터를 메모리에서 제거하는 프로그램
# 가비지 컬렉터: 변수에 저장하지 않은 경우
class Test:
    def __init__(self, name):
        self.name = name
        print("{} - 생성되었습니다".format(self.name))

    def __del__(self):
        print("{} - 파괴되었습니다.".format(self.name))

Test("A")
Test("B")
Test("C")

# 실행 결과
----------
A - 생성되었습니다
A - 파괴되었습니다.
B - 생성되었습니다
B - 파괴되었습니다.
C - 생성되었습니다
  • A가 생성되고 다음 줄로 넘어갈 때 이것을 변수에 저장하지 않으면 가비지 컬렉터는 이후에 활용하지 않겠다는 의미로 이해하고 메모리를 아끼기 위해서 과감히 지워버림
  • A가 생성되고 사용되지 않을 것이 확실하므로 A를 제거해 소멸함
  • 이러한 과정이 반복되므로 A생성 A파괴, B생성 B파괴, C생성 C파괴 과정이 진행됨
# 가비지 컬렉터 : 변수에 저장한 경우
class Test:
    def __init__(self, name):
        self.name = name
        print("{} - 생성되었습니다".format(self.name))

    def __del__(self):
        print("{} - 파괴되었습니다.".format(self.name))

a = Test("A")
b = Test("B")
c = Test("C")

# 실행 결과
----------
A - 생성되었습니다
B - 생성되었습니다
C - 생성되었습니다
A - 파괴되었습니다.
B - 파괴되었습니다.
C - 파괴되었습니다.
  • 변수에 저장한 경우에 가비지 컬렉터는 변수에 저장하면 나중에 활용한다는 의미로 생각하고 프로그램이 종료되는 순간까지 데이터를 메모리에서 제거하지 않음
  • 따라서 A, B, C가 생성된 후 종료될 때 A, B, C파괴가 일어남

오버라이드(override)

  • 부모에게서 상속받은 메소드를 자식 클래스에서 다시 정의하는 것

프라이빗 변수

  • 변수를 마음대로 사용하는 것을 막아야 한다.
  • 파이썬은 클래스 내부의 변수를 외부에서 사용하는 것을 막고 싶을 때 인스턴스 변수 이름을 __<변수 이름>형태로 선언
# 모듈 가져옴
import math

# 클래스 선언
class Circle:
    def __init__(self, radius):
        self.__radius = radius
    def get_circumference(self):
        return 2 * math.pi * self.__radius
    def get_area(self):
        return math.pi * (self.__radius ** 2)

# 원의 둘레와 넓이 구하기
circle = Circle(10)
print("# 원의 둘레와 넓이를 구합니다.")
print("원의 둘레:", circle.get_circumference())
print("원의 넓이:", circle.get_area())
print()

# __radius에 접근
print("#__radius에 접근합니다.")
print(circle.__radius)

# 실행 결과
----------
# 원의 둘레와 넓이를 구합니다.
원의 둘레: 62.83185307179586
원의 넓이: 314.1592653589793

#__radius에 접근합니다.
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[24], line 22
     20 # __radius에 접근
     21 print("#__radius에 접근합니다.")
---> 22 print(circle.__radius)

AttributeError: 'Circle' object has no attribute '__radius'
  • 클래스 내부에서 radiusf를 사용하는 것은 문제가 없지만, 클래스 외부에서 radius를 사용하려고 할 때 그런 속성이 없다는 오류를 출력함
  • 속성을 선언할 때 앞에 __를 붙이기만 함녀 외부에서 사용할 수 없는 변수가 됨

게터(getter)와 세터(setter)

  • 프라이빗 변수의 값을 추출하거나 변경할 목적으로, 간접적으로 속성에 접근하도록 해주는 함수
# 모듈 가져옴
import math

# 클래스 선언
class Circle:
    def __init__(self, radius):
        self.__radius = radius
    def get_circumference(self):
        return 2 * math.pi * self.__radius
    def get_area(self):
        return math.pi * (self.__radius ** 2)

    # 게터와 세터 선언
    def get_radius(self):
        return self.__radius
    def set_radius(self, value):
        self.__radius = value

# 원의 둘레와 넓이 구하기
circle = Circle(10)
print("# 원의 둘레와 넓이를 구합니다.")
print("원의 둘레:", circle.get_circumference())
print("원의 넓이:", circle.get_area())
print()

# 간접적으로 __radius에 접근
print("#__radius에 접근합니다.")
print(circle.get_radius())
print()

# 원의 둘레와 넓이를 구하기
circle.set_radius(2)
print("#반지름을 변경하고 원의 둘레와 넓이를 구합니다.")
print("원의 둘레:", circle.get_circumference())
print("원의 넓이:", circle.get_area())

# 실행 결과
----------
# 원의 둘레와 넓이를 구합니다.
원의 둘레: 62.83185307179586
원의 넓이: 314.1592653589793

#__radius에 접근합니다.
10

#반지름을 변경하고 원의 둘레와 넓이를 구합니다.
원의 둘레: 12.566370614359172
원의 넓이: 12.566370614359172
  • get_radius() 함수와 set_radius 함수를 만들어서 함수로 프라이빗 변수의 값에 접근하거나, 값을 변경하게 했음
  • 함수를 사용해 변경하면 여러 가지 처리를 추가할 수 있음
  • 예를 들어 set_radius()함수에 다음과 같은 코드를 추가하면 __radius에 할당할 값을 양의 숫자로만 한정할 수 있음
  • 게터와 세터로 변수 안전하게 사용하기

    def set_radius(self, value):
    . . . . if value <= 0:
    . . . . . . . . raise TypeError("길이는 양의 숫자여야 합니다.")
    . . . . self.__radius = value


데코레이터를 사용한 게터와 세터

  • 파이썬은 게터와 세터를 쉽게 만들고 사용할 수 있게 하는 기능을 제공함
  • 변수 이름과 같은 함수를 정의하고 위에 @property와 @<게터 함수 이름>.setter란느 데코레이터를 붙임



🤔 기본 미션 ) p. 431 [직접 해보는 손코딩:BeautifulSoup 스크레이핑 실행하기] 예제 실행 후 결과 화면 캡처하기

# 모듈 읽어 들임
from flask import Flask
from urllib import request
from bs4 import BeautifulSoup

# 웹 서버 생성
app = Flask(__name__)
@app.route("/")

def hello():
    #urlopen() 함수로 기상청의 전국 날씨를 읽음
    target = request.urlopen("http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108")


    # BeautifulSoup를 사용해 웹 페이지 분석
    soup = BeautifulSoup(target, "html.parser")

    # location 태그 찾기
    output = ""
    for location in soup.select("location"):
        # 내부의 city, wf, tmn, tmx 태그를 찾아 출력함
        output += "<h3>{}</h3>".format(location.select_one("city").string)
        output += "날씨: {}<br/>".format(location.select_one("wf").string)
        output += "최저/최고 기온: {}/{}"\
            .format(\
                location.select_one("tmn").string, \
                location.select_one("tmx").string\
            )
        output += "<hr/>"
    return output
  • 실행 결과



😮 선택 미션 ) 혼공 용어 노트에 나만의 언어로 객체, 클래스, 인스턴스, 생성자, 메소드 정리하고 공유하기

객체(object)

  • 여러 가지 속성을 가질 수 있는 대상
  • 프로그래밍 언어에서는 속성을 가질 수 있는 모든 것을 '객체'라고 부름

클래스(class)

  • 객체에 포함한 변수와 함수를 미리 정의한 것
  • 객체의 설계도에 해당

인스턴스(instance)

  • 클래스 기반으로 만들어진 객체

생성자(constructor)

  • 클래스 이름과 같은 함수
  • 클래스 내부에 init이라는 함수를 만들면 객체를 생성할 때 처리를 작성할 수 있음

메소드(method)

  • 클래스가 가지고 있는 함수
  • 첫 번째 매개변수로 self를 넣어야 한다.



👀 도전 문제

1. StudentList 클래스 구현하기

name과 score 속성만 갖게 구성

class Student:
	def __init__(self, name, score):
    	self.name = name
        self.score = score

아래의 결과값이 나오도록 코드 구현하기

실행 결과
학급의 평균 점수는 80.0입니다.
가장 성적이 높은 학생은 구름입니다.
가장 성적이 낮은 학생은 별입니다.

🖥️

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

class StudentList:
    def __init__(self):
        # 구성 사용
        self.students = []

    def append(self, student):
        self.students.append(student)

    def get_average(self):
        return sum([
            student.score
            for student in self.students
        ]) / len(self.students)
    def get_first_by_score(self):
        return max(self.students, key=lambda x: x.score)
    
    def get_last_by_score(self):
        return min(self.students, key=lambda x:x.score)
    
students = StudentList()
students.append(Student("구름", 100))
students.append(Student("별", 49))
students.append(Student("초코", 81))
students.append(Student("아지", 90))

print(f"학급의 평균 점수는 {students.get_average()}입니다.")
print(f"가장 성적이 높은 학생은 {students.get_first_by_score().name}입니다.")
print(f"가장 성적이 낮은 학생은 {students.get_last_by_score().name}입니다.")

2. 스택 구현하기

  • 스택(stack) : 기본 자료형이 차곡차곡 쌓여서 정리되어 있는 공간
  • 푸시(push) : 스택이라는 상자 안에 물건을 넣는 행위
  • 팝(pop) : 상자 안에서 물건을 꺼내는 행위
  • 큐(queue) : 먼저 진입한 것이 먼저 꺼내지는 자료 구조
  • 인큐(enqueue) : 큐라는 상자 안에 물건을 넣는 행위
  • 디큐(dequeue) : 상자 안에서 물건을 꺼내는 행위

🖥️

class Stack:
    def __init__(self):
        self.list = []
    def push(self, item):
        self.list.append(item)
    def pop (self):
        return self.list.pop()
    
stack = Stack()
stack.push(10)
stack.push(20)
stack.push(30)

print(stack.pop())
print(stack.pop())
print(stack.pop())

# 실행 결과
----------
30
20
10

3. 큐 구현하기

🖥️

class Stack:
    def __init__(self):
        self.list = []
    def push(self, item):
        self.list.append(item)
    def pop (self):
        return self.list.pop(0)
    
stack = Stack()
stack.push(10)
stack.push(20)
stack.push(30)

print(stack.pop())
print(stack.pop())
print(stack.pop())

# 실행 결과
----------
10
20
30

profile
개발을 '잘'하고 싶다는 마음은 항상 늘 지니고 있는 사람

0개의 댓글