Python에서 'tuple' object is not callable 라고 나오는군요.

chocoheim의 이미지

'Learning Python'책을 보고 있는데,
8장 마지막 즈음(원서:240p)에 timing.py 란 소스코드 실행이 안되네요.

소스코드 :

(makezeros.py)
def lots_of_appends() :
    zeros = []
    for i in range(10000) :
        zeros.append(0)

def one_multiply() :
    zeros = [0] * 10000 

(timings.py)
import time, makezeros

def do_timing(num_times, *funcs) :
    totals = {}
    for func in funcs : totals[func] = 0.0
    for x in range(num_times) :
        for func in funcs : 
            starttime = time.time()
            stoptime = time.time()
            #apply(func)
            elapsed = stoptime-starttime
            totals[func] = totals[func] + elapsed 
        for func in funcs : 
            print "Running %s %d times took %.3f seconds" % (func.__name__, num_times, totals[func])

do_timing(100, (makezeros.lots_of_appends(), makezeros.one_multiply()))

는 이렇구요. 실행결과는

Traceback (most recent call last):
  File "timings.py", line 16, in ?
    do_timing(100, (makezeros.lots_of_appends(), makezeros.one_multiply()))
  File "timings.py", line 14, in do_timing
    print "Running %s %d times took %.3f seconds" % (func.__name__, num_times, totals[func])
AttributeError: 'tuple' object has no attribute '__name__'

라고 나오는군요.
왜 그럴까요? :idea:
책에 쓰인 python은 1.5x 이고, 제컴에 깔린넘은 2.2.1 임다

saemaro의 이미지

이렇게 해보세요.

timing.py:

import time, makezeros

def do_timing(num_times, *funcs) :
    totals = {}
    for func in funcs : totals[func] = 0.0
    for x in range(num_times) :
        for func in funcs :
            starttime = time.time()
            apply(func)
            stoptime = time.time()
            elapsed = stoptime-starttime
            totals[func] = totals[func] + elapsed
    for func in funcs :
        print "Running %s %d times took %.3f seconds" % (func.__name__, num_times, totals[func])

do_timing(100, makezeros.lots_of_appends, makezeros.one_multiply)

def do_timing(...)에서 *funcs를 funcs로 고치거나, 아래 do_timing(100, ..)에서 두 함수 사이의 괄호를 빼야 합니다. 책 소스의 버그죠. 이 상황에서 *funcs는 do_timing의 나머지 argument들을 tuple로 씌워서 받은 것이니까요.

그리고 책 소스를 치실 때 들여쓰기 주의하세요 :)

chocoheim의 이미지

괄호를 뺐봤었는데, 이렇게 나오거든요.

Traceback (most recent call last):
  File "timings.py", line 16, in ?
    do_timing(100, makezeros.lots_of_appends(), makezeros.one_multiply())
  File "timings.py", line 14, in do_timing
    print "Running %s %d times took %.3f seconds" % (func.__name__, num_times, totals[func])
AttributeError: 'NoneType' object has no attribute '__name__'

튜플로 씌워서 받는 다는건 잘 모르고 있었네요. ^^; 감사.
감사받은 김에 이것도 해결해주세요~ :lol:

WaitplzplzWait

saemaro의 이미지

위쪽 제가 올린 소스를 참고하세요. 원래 소스와 다른 곳이 더 있습니다.

do_timing(100, makezeros.lots_of_appends(), makezeros.one_multiply()) 여기에서 두 '()' 를 빼주셔야 <procedure>가 전달됩니다. 그래야 apply(func)가 먹혀듭니다. '()'를 붙이면 저 <procedure>가 실행되어 return한 결과(여기서는 None)이 전달되거든요.