7일차

송용진·2024년 2월 27일

# %% [markdown]
# DataClass
# 기존 클래스 사용보다 조금은 편하다

# %%
#데이터 클래스 생성하기(오류,개발속도 부분에서 유리)
from dataclasses import dataclass

@dataclass
class Student:
    name : str
    age : int
    major : str

student1 = Student("샘", 30, "OpenAI")

# %%
student1

# %%
#일반 클래스와 비교
# class Student_1:
#     def __repr__(self):


# %%
#심화
# from dataclasses import dataclass

@dataclass
class Student:
    name : str
    age : int
    major : str

    def __post_init__(self):
        if not isinstance(self.age, int):
            raise TypeError(f"나이는 숫자로 들어와야함")

student1 = Student("샘", "서른살", "OpenAI") #검사하는 기능?(+알파,포트폴리오에 추가하면 좋음)

# %%
student2 = Student("민수",20,"우아한형제들")
student3 = Student("태연",25,"카카오")

# %%
student2 == student3

# %%
class Student_1:
    def __init__(self,name,age,major):
        self.name = name
        self.age = age
        self.major = major

# %%
student3_1 = Student_1("태연",25,"카카오")
student4_1 = Student_1("태연",25,"카카오")

student3_1 == student4_1

# %%
student5_1 = Student("태연",25,"카카오")
student6_1 = Student("태연",25,"카카오")

# %%
student5_1 == student6_1

# %%
#
'''
@dataclass
'''

# %%
student6_1.major = 'Google'

# %%
student6_1

# %%
@dataclass(frozen=True)#값을 고정
class Employee:
    name : str
    position : str

employee1 = Employee("John","Manager")

# %%
employee1

# %%
employee1.name = 'Jane' #값을 고정했기 때문에 문제 발생
employee1

# %%
def func(msg="Hi"):
    print(msg)

func("Hello")
func()

# %%
@dataclass
class AppConfig: #앱의 설정 값을 다뤄보자
    debug : bool = False #기본값은 False
    database_url : str ="some_url"
    port : int = 1234

default_config = AppConfig()


# %%
default_config

# %%
custom_config = AppConfig(debug = True,database_url='naver',port=4321)
custom_config

# %% [markdown]
# 개인 프로젝트에서 데이터 클래스 적용해보기
# 데이터클래스는 비교할 때 인스턴스의 내용이 같으면 같은 걸로 취급

# %%
#가변 타입 필드 사용할 때 이렇게 하면 됨
from dataclasses import dataclass, field

@dataclass
class StudentCourses:
    name : str
    courses : list = field(default_factory=list)

# %% [markdown]
# Python의 dataclasses 모듈에서는 
# field() 함수를 사용하여 
# 클래스 필드의 기본값을 설정할 수 있는 방법을 제공하고 있습니다.
# 
# 이 field() 함수는 
# 데이터 클래스 필드를 세부적으로 커스터마이징 할 수 있게 도와줍니다.
# 
# 이 중 default_factory 는 기본값을 생성하는 함수를 의미합니다.
# 
# list = field(default_factory=list) 이 부분은 
# courses 필드의 기본값을 빈 리스트로 설정하고 있습니다. 
# 이것은 가변 객체를 기본값으로 사용하려는 경우에 주로 사용됩니다. 
# 왜냐하면 가변 객체는 공유될 수 있기 때문에, 
# 이런 식으로 함수를 사용해서 각 인스턴스마다 새로운 객체를 생성하는 것이 안전합니다.
# 
# 즉, 여기서 list = field(default_factory=list)는 
# 새로운 StudentCourses 인스턴스가 생성될 때마다, 
# courses 필드에 새로운 빈 리스트를 할당하는 것을 보장합니다. 이렇게 하면 
# StudentCourses 인스턴스 간에 
# courses 리스트가 공유되지 않으므로 
# 각 학생이 수강하는 과목 리스트를 독립적으로 관리할 수 있게 됩니다.

# %%
student10 = StudentCourses(name='멋사')
student10.courses.append("파이썬 문법")
student10.courses.append("웹서비스")
student10.courses.append("배포")

# %%
student10

# %% [markdown]
# 
# 

# %%
# class에서 초기값 지정할 때 조심해야 되는 점
class A:
    def __init__(self,name,courses=[]):
        self.name = name
        self.courses = courses


# %%
a = A("a")
a

# %%
a.courses.append("파이썬")

# %%
b = A("b")
a.courses, b.courses

# %%
# class에서 초기값 지정할 때 조심해야 되는 점
class A:
    def __init__(self,name,courses=None):
        self.name = name
        if courses is None:
            self.courses = []
        else:
            self.courses = courses

# %%
a = A('a')
a.courses

# %%
b = A('b')
b.courses

# %%
a.courses.append("good")
a.courses

# %%
b.courses

# %% [markdown]
# **TDD란?**
# Test Driven Development 테스트 주도 개발
# 소프트웨어 개발 방법론 중 하나로,
# 소프트웨어의 기능을 구현하기 전에 테스트를 작성하고,
# 그 테스트를 통과시키는 코드를 작성한 후에야 기능을 구현하는 방식
# 
# TDD 개발 과정
# 실패하는 테스트 작성 > 테스트 통과하게 만드는 코드 작성 > 코드 리팩토링

# %% [markdown]
# assert
# assert 조건, "에러 메시지"

# %%
def get_age(age):
    assert age >= 0, "값이 잘못 입력됨"
    print("당신의 나이는 {}세".format(age))

# %%
get_age(15)


# %%
get_age(-15)

# %% [markdown]
# Mock 객체를 사용한 테스트
# setUP 및 tearDown 사용
# 조건부 테스트 실행

# %% [markdown]
# Pythonic 코드 개발
# 파이썬의 철학과 관용구를 따라
# 효율적이고 가독성 높은 코드를 작성하는 방식

# %%
import this

# %% [markdown]
# 명확함이 애매함보다 낫다

# %%
# 명확한 변수명 사용
# dt = 10
days_to_complete = 10

# %%
# 함수 이름으로 기능 명시
def process(data):
    pass

def remove_duplicated_records(data):
    pass

# %%
#조건문 간소화
status = True

if status == True:
    pass

if status:
    pass

# %% [markdown]
# 단순함이 복잡함보다 낫다

# %%
#리스트 컴프리헨션 사용
result = []
for i in range(10):
    if i % 2 == 0:
        result.append(i**2)

result = [i**2 for i in range(10) if i%2 == 0]

# %%
# 함수 분리
def process_data(data):
    # 데이터 전처리
    # 데이터 처리
    # 결과 반환
    pass

#데이터 전처리
def preprocess_data(data):
    pass
#데이터 처리
def process_data(data):
    pass

# %%
# 내장 함수 사용
nums = [ i for i in range(100)]

# %%
total = 0
for num in nums:
    total += num

average = total /len(nums)
average


# %%
average = sum(nums) / len(nums)
average

# %%
# 조건문 간소화
status = None

if status == "success" or status == "complete" or status == "finished":
    pass
if status in ["success","complete","finished"]:
    pass

# %% [markdown]
# 가독성이 중요하다

# %%
#적절한 줄바꿈과 들여쓰기
result = some_function(param1, param2, param3, param4, param5)

result = some_function(param1, 
                       param2, 
                       param3, 
                       param4, 
                       param5)

# %%
# 의미 있는 주석 추가
# 현재 시간에서 일주일을 더한다.
next_week = current_time + week_time

# %%
# 함수와 변수의 적절한 분리
print("Result : ", process_data(data))

result = process_data(data)
print("Result : ", result)

# %%
# 적절한 변수명 사용

# %%
# 중첩 제한하기
items = [(i,i*3) for i in range(10)]

# %%
for item in items:
    if item:
        for value in item:
            pass

# %%
# 오류는 결코 조용히 지나가지 않아야 한다.
def process_data(data):
    return int(data)

# %%
data = "일이삼"
try:
    process_data(data)
except ValueError as e:
    print(f"ValueError:{e}")
except Exception as e:
    print(f"Unexpected error : {e}")
    # raise

# %% [markdown]
# 명시적인 것이 암시적인 것보다 낫다

# %%
# from math import *
# print(sqrt(4))

# %%
from math import sqrt
print(sqrt(4))

# %%
def make_request(url, timeout=5):
    pass

make_request("http://example.com",10)
make_request(url = "http://example.com",timeout = 10)

# %%
def get_position():
    return 100,200

x,y = get_position()
x,y


# %%
position = get_position()
x = position[0]
y = position[1]
x,y

x,y = get_position()
x,y

# %% [markdown]
# 실용성은 순수성보다 중요

# %%
result = list(map(lambda x:x**2, filter(lambda x:x%2==0,range(10))))
result

# %%
result = [x**2 for x in range(10) if x%2 == 0]

# %%
#성능을 위한 실용적 최적화
def is_prime_1(n):
    return n>1 and all(n%i for i in range(2,n))

def is_prime_2(n):
    if n <= 1:
        return False
    for i in range(2, int(n**0.5)):
        if n % i == 0:
            return False
        return True

# %%
%%time
is_prime_1(10007)

# %%
%%time
is_prime_2(10007)

# %%
# 유지 보수를 위한 실용적 구조
class Animal: pass
class Dog(Animal): pass

def make_sound(animal_type):
    sounds = {"dong":"bark","cat":"meow"}
    return sounds.get(animal_type, 'unknown')

# %% [markdown]
# 일관성은 중요하다

# %%
#네이밍 컨벤션 일관성
class MyClass:
    pass        #class는 camel case

def my_function():
    pass            #변수는 snake case

# %%
import requests #코랩에서 가능
url = "https://www.dhlottery.co.kr/common.do?method=getLottoNumber&drwNo=100"

# %%
response = requests.get(url)

# %%
output = response.json()

# %%
output

# %% [markdown]
# 특정 회차 정보를 가져오려면 어떻게 해야 되나?->함수
# 그 회차의 당첨번호,보너스 번호는 몇번인가?->함수
# 파이써닉한 코드에 대해 고민해보기
# 

profile
개발자

0개의 댓글