연습문제

아래 문제들을 해결하는 코드를 lab07.py 파일에 작성하여 제출하라.

연습 1

미국 해양대기청(NOAA)은 전세계 날씨를 실시간으로 제공한다. 한국의 경우 공항이 있는 도시의 날씨정보를 제공하며 평택도 포함된다. 평택의 현재 날씨 정보를 텍스트파일로 얻고자 하면 아래 NOAA 사이트를 클릭해서 파일을 다운로드받으면 된다.

아니면 아래 함수를 이용하여 위 링크에 연결된 파일 내용을 확인할 수 있다.

def NOAA_string():
    url = "http://weather.noaa.gov/pub/data" +\
        "/observations/metar/decoded/RKSG.TXT"
    noaa_data_string = urllib.urlopen(url).read()
    return noaa_data_string

위 코드를 사용하려면 urllib 모듈을 임포트해야 한다. 위 함수를 파이썬 셸에서 실행하여 리턴값을 확인해보기 바란다.

이제 아래 일을 수행하는 함수 NOAA_temperature(s) 함수를 작성하라.

  • NOAA_string()의 리턴값을 인자로 받아서 해당 도시의 섭씨 단위 온도의 정수값을 리턴한다.
  • 미국은 온도를 화씨(Fahrenheit) 단위로 나타내며 우리는 섭씨(Celsius) 단위를 사용한다.

주의: 위 사이트는 실시간으로 날씨 정보를 제공한다. 따라서 위 링크를 누를 때마다 온도 정보가 변한다. 예를 들어 2015년 10월 16일 0시 38분에 확인한 경우 아래 처럼 확인된 평택시 온도는 섭씨 14.2이다. 따라서 NOAA_temperature(NOAA_string())14를 리턴해야 한다. 하지만 다른 시각에 확인하면 다른 값이 나올 수 있음에 주의해야 한다. 어떻게 섭씨에 해당하는 숫자를 끄집어 낼 수 있는지 확인해야 한다.

Pyongtaek Ab, Korea, South (RKSG) 36-56N 127-00E 16M
Oct 15, 2015 - 10:58 AM EDT / 2015.10.15 1458 UTC
Wind: Calm:0
Visibility: 2 mile(s):0
Sky conditions: partly cloudy
Weather: mist
Temperature: 57.6 F (14.2 C)
Dew Point: 57.6 F (14.2 C)
Relative Humidity: 100%
Pressure (altimeter): 30.11 in. Hg (1019 hPa)
ob: RKSG 151458Z 00000KT 2SM R32/2600FT BR SCT010 14/14 A3011 RMK AO2A SLP199 T01420142 
cycle: 15

힌트: 문자열 메소드 중에서 특정 부분 문자열(substring)의 위치, 즉 인덱스 번호를 확인해주는 메소드가 있다.

연습 1 견본답안 1

NOAA_string()을 실행하여 얻어진 파일의 내용을 보면 7번째 줄에서 온도 정보를 확인할 수 있다. 관건은 7번째 줄에서 14.2를 끄집어 내는 것이다. 그러려면 14.2를 유일하게 특징지울 수 있는 무언가를 찾아야 한다.

방법 1: split 메소드 이용하기

  • 7번째 줄을 자세히 살피면 섭씨 온도 정보는 세 개의 스페이스 뒤에 위치한다. 이 정보를 활용할 수 있다.

In [1]:
import urllib

def NOAA_string():
    url = "http://weather.noaa.gov/pub/data" +\
        "/observations/metar/decoded/RKSG.TXT"
    noaa_data_string = urllib.urlopen(url).read()
    return noaa_data_string

print(NOAA_string())

def NOAA_temperature(s):
    L = s.split('\n')
    Line7 = L[6].split()
    print(str(int(Line7[-2][1:])) + " C")

NOAA_temperature(NOAA_string())


Pyongtaek Ab, Korea, South (RKSG) 36-56N 127-00E 16M
Oct 20, 2015 - 04:55 AM EDT / 2015.10.20 0855 UTC
Wind: from the NW (310 degrees) at 6 MPH (5 KT):0
Visibility: 1 1/2 mile(s):0
Sky conditions: clear
Weather: mist
Temperature: 68 F (20 C)
Dew Point: 66 F (19 C)
Relative Humidity: 93%
Pressure (altimeter): 30 in. Hg (1015 hPa)
Pressure tendency: 0.00 inches (0.0 hPa) higher than three hours ago
ob: RKSG 200855Z 31005KT 1 1/2SM BR CLR 20/19 A3000 RMK SLP162 53000
cycle: 9

20 C

연습 1 견본답안 2

  • 섭씨온도를 유일하게 특징지우는 문자열을 찾아야 한다.
  • " F "가 그런 문자열이다. (F 양 옆으로 스페이스가 있다.)

In [2]:
def NOAA_temperature(s):
    d = s.find(" F ")
    print(s[d+4: d+6] + " C")
    
NOAA_temperature(NOAA_string())


20 C

연습 2

텍스트 파일에 저장된 문장에서 특정 단어의 출현 횟수를 확인해주는 함수 wc_sub(filename, s) 함수를 작성하라. wcWord Count의 줄임말이다.

힌트: count 메소드를 활용한다.

예제 1: data.txt 파일 내용이 아래와 같을 경우

One Two

wc_sub('data.txt', 'One')는 1를 리턴한다.

예제 2: data.txt 파일 내용이 아래와 같을 경우

One Two
Three Four Five

wc_sub('data.txt', 'o')는 2를 리턴한다.

wc_sub 함수를 이용하여 이상한 나라의 앨리스 원작에 'Alice'와 'alice'란 단어가 각각 몇 번 언급되는지 확인하라. 이상한 나라의 앨리스 원작은 아래 링크에서 다운 받을 수 있다.

http://www.gutenberg.org/files/28885/28885-8.txt

위 링크를 누르면 뜨는 화면에서 Plain Text UTF-8 파일을 다운로드 받으면 된다. 아마도 몇 만 단어가 사용되었을 것이다.

단, filename에 해당하는 파일이 열리지 않을 경우 -1을 리턴하도록 오류처리를 해야 한다.

연습 2 견본답안


In [3]:
def wc_sub(filename, s):
    with open(filename, 'r') as f:
        f_content = f.read()
    return f_content.count(s)

print("The word 'Alice' occurs {} times.".format(wc_sub('Alice.txt', 'Alice')))
print("The word 'alice' occurs {} times.".format(wc_sub('Alice.txt', 'alice')))


The word 'Alice' occurs 402 times.
The word 'alice' occurs 0 times.

연습 3

함수 f와 숫자들의 리스트 xs를 인자로 받아 f(x)의 값이 0보다 크게 되는 x의 값만 추출해서 리턴하는 함수 filtering(f, xs)를 정의하라.

예제:

In [1]: def f1(x):
   ...:     return x * 3

In [2]: filtering(f1, [1, -2, 2, -1, 3, 5])
Out[2]: [1, 2, 3, 5]

In [3]: filtering(f1, [-1, -2, -3, -4, -5])
Out[3]: []

연습 3 견본답안


In [4]:
def filtering(f, xs):
    L = []
    for x in xs:
        if f(x) > 0:
            L.append(x)
    return L

def f1(x):
    return x * 3

filtering(f1, [1, -2, 2, -1, 3, 5])


Out[4]:
[1, 2, 3, 5]
참조: 파이썬 내장함수 중에 filter 함수가 비슷한 일을 한다. 어떤 차이점이 있는지 확인해보는 것을 추천한다.

연습 4

함수 f와 숫자들의 리스트 xs = [x1, ..., x_n]를 인자로 받아 f(xn)들의 값의 합을 리턴하는 함수 sum_list(f, xs)를 정의하라. 단, xs = [] 일 경우 0을 리턴한다.

예제:

In [4]: def f2(x):
   ...:     return x ** 2

In [5]: sum_list(f2, [1, -2, 2, -3,])
Out[5]: 18

In [6]: sum_list(f1, [-1, -2, -3, -4, -5])
Out[6]: -45

연습 4 견본답안


In [5]:
def sum_list(f, xs):
    L = 0
    for x in xs:
        L = L + f(x)
    return L

def f2(x):
    return x ** 2

print(sum_list(f2, [1, -2, 2, -3]))
print(sum_list(f1, [-1, -2, -3, -4, -5]))


18
-45

참조: 파이썬 내장함수 중에 sum 함수가 비슷한 일을 한다. 어떤 차이점이 있는지 확인해보는 것을 추천한다.

연습 5

밑변의 길이와 높이가 각각 ah인 삼각형의 면적을 리턴하는 함수 triangle_area(a, h)를 작성하라. 그런데 삼각형의 높이 h는 기본값으로 5를 사용해야 한다. 힌트: 키워드 인자를 사용한다.

예제:

In [7]: triangle_area(3)
Out[7]: 7.5

In [8]: triangle_area(3, 7)
Out[8]: 10.5

연습 5 견본답안


In [6]:
def triangle_area(a, height=5):
    return 1.0/2 * a * height

print(triangle_area(3))
print(triangle_area(3, 7))


7.5
10.5

연습 6

함수 f를 입력 받으면 아래 묘사처럼 작동하는 함수를 리턴하는 함수 fun_2_fun(f)를 정의하라.

fun_2_fun(f)(2) = (f(2)) ** 2
fun_2_fun(f)(3) = (f(3)) ** 3
fun_2_fun(f)(4) = (f(4)) ** 4
...

주의: 함수를 입력받아 함수를 리턴하도록 작성해야 한다.

힌트: 함수 안에서 def 키워드를 이용하여 새로운 함수를 정의할 수 있다. 그 함수는 지역함수가 된다.

연습 6 견본답안 1


In [7]:
def fun_2_fun(f):
    def f_exp(n):
        return (f(n)) ** n
    return f_exp

print(f1(2))
print(fun_2_fun(f1)(2))


6
36

문제 핵심

이 문제의 핵심은 함수를 단순히 인자로만 사용하는 것이 아니라 리턴값으로도 할용하는 것이다. 즉, 함수에 어떤 인자를 넣고 호출하였더니 어떤 함수를 리턴하는 함수를 구현해야 한다. 그리고 리턴값이 함수이므로 그 함수를 적당한 인자를 입력하여 호출할 수 있다.

예를 들어 함수 g를 다음과 같이 정의하자.


In [8]:
def exp2(x):
    return x ** 2

In [9]:
g = fun_2_fun(exp2)

그러면 g는 함수임을 확인할 수 있다.


In [10]:
type(g)


Out[10]:
function

어떤 함수인가? help 를 이용하여 확인하면 다음과 같다.


In [11]:
help(g)


Help on function f_exp in module __main__:

f_exp(n)


In [12]:
g


Out[12]:
<function __main__.f_exp>

즉, 인자를 하나 받는 함수이며 f_exp를 이용해 정외되었음을 알 수 있다. 실제로 g는 아래와 같이 정의되어 있다.

g를 정의하기 위해 fun_2_fun(f) 함수를 호출할 때 사용된 인자 f 대신에 exp2 함수를 삽입하였기 때문에 g가 아래와 같이 정의된 함수임을 알 수 있다.

g(x) = fun_2_fun(exp2)
     = f_exp(x)   # f_exp 를 정의할 때 exp2 가 사용됨에 중의
     = exp2(x) ** x
     = (x**2) ** x
     = x ** (2*x)

연습 6 견본답안 2


In [13]:
def fun_2_fun(f):
    return lambda x: f(x) ** x

print(f1(2))
print(fun_2_fun(f1)(2))


6
36