디자인 결정 재고

Beginner

This tutorial is from open-source community. Access the source code

소개

이 섹션에서는 앞서 내린 설계 결정을 다시 고려합니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 83%입니다.학습자들로부터 100%의 긍정적인 리뷰율을 받았습니다.

파일 이름 대 이터러블 (Iterables)

동일한 출력을 반환하는 다음 두 프로그램을 비교해 보겠습니다.

## Provide a filename
def read_data(filename):
    records = []
    with open(filename) as f:
        for line in f:
            ...
            records.append(r)
    return records

d = read_data('file.csv')
## Provide lines
def read_data(lines):
    records = []
    for line in lines:
        ...
        records.append(r)
    return records

with open('file.csv') as f:
    d = read_data(f)
  • 이 함수들 중 어떤 것을 선호하십니까? 이유는 무엇입니까?
  • 이 함수들 중 어떤 것이 더 유연합니까?

심오한 아이디어: "덕 타이핑 (Duck Typing)"

덕 타이핑 (Duck Typing)은 객체가 특정 목적에 사용될 수 있는지 여부를 결정하는 컴퓨터 프로그래밍 개념입니다. 이는 덕 테스트 (duck test)의 적용입니다.

만약 그것이 오리처럼 보이고, 오리처럼 헤엄치고, 오리처럼 꽥꽥거린다면, 아마도 그것은 오리일 것이다.

위의 read_data()의 두 번째 버전에서, 함수는 모든 이터러블 (iterable) 객체를 예상합니다. 파일의 줄뿐만 아니라.

def read_data(lines):
    records = []
    for line in lines:
        ...
        records.append(r)
    return records

이는 다른 lines와 함께 사용할 수 있음을 의미합니다.

## A CSV file
lines = open('data.csv')
data = read_data(lines)

## A zipped file
lines = gzip.open('data.csv.gz','rt')
data = read_data(lines)

## The Standard Input
lines = sys.stdin
data = read_data(lines)

## A list of strings
lines = ['ACME,50,91.1','IBM,75,123.45', ... ]
data = read_data(lines)

이 설계는 상당한 유연성을 제공합니다.

질문: 이러한 유연성을 받아들여야 할까요, 아니면 거부해야 할까요?

라이브러리 설계 모범 사례

코드 라이브러리는 유연성을 포용하는 것이 더 나은 경우가 많습니다. 옵션을 제한하지 마십시오. 큰 유연성은 큰 힘을 가져다줍니다.

연습 문제 3.17: 파일 이름에서 파일 유사 객체로

이제 parse_csv() 함수를 포함하는 파일 fileparse.py를 만들었습니다. 이 함수는 다음과 같이 작동했습니다.

>>> import fileparse
>>> portfolio = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>>

현재, 이 함수는 파일 이름을 전달받도록 되어 있습니다. 하지만 코드를 더 유연하게 만들 수 있습니다. 파일 유사/이터러블 (iterable) 객체와 함께 작동하도록 함수를 수정하십시오. 예를 들어:

>>> import fileparse
>>> import gzip
>>> with gzip.open('portfolio.csv.gz', 'rt') as file:
...      port = fileparse.parse_csv(file, types=[str,int,float])
...
>>> lines = ['name,shares,price', 'AA,100,34.23', 'IBM,50,91.1', 'HPE,75,45.1']
>>> port = fileparse.parse_csv(lines, types=[str,int,float])
>>>

이 새로운 코드에서, 이전처럼 파일 이름을 전달하면 어떻게 될까요?

>>> port = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>> port
... 출력 결과를 확인하세요 (엉망일 것입니다) ...
>>>

네, 주의해야 합니다. 이를 방지하기 위해 안전 점검을 추가할 수 있을까요?

연습 문제 3.18: 기존 함수 수정

parse_csv()의 수정된 버전과 함께 작동하도록 report.py 파일의 read_portfolio()read_prices() 함수를 수정하십시오. 이는 사소한 수정만 포함해야 합니다. 그 후, report.pypcost.py 프로그램은 항상 그랬던 것처럼 동일하게 작동해야 합니다.

요약

축하합니다! 디자인 토론 랩을 완료했습니다. LabEx 에서 더 많은 랩을 연습하여 기술을 향상시킬 수 있습니다.