数字Guesser:请复习并使其更加Pythonic

时间:2010-08-12 21:16:52

标签: python

我正在学习python,这是一个简单的程序,我写道:

def guesser(var, num1,possible):
    if var == 'n':
        cutoff = len(possible)/2
        possible = possible[0:cutoff]
        cutoff = possible[len(possible)/2]
        #print possible

        if (len(possible) == 1):
             print "Your Number is:", possible
        else:
            var = raw_input("Is Your Number Bigger Than %s? (y/n): " %cutoff)
            guesser(var, cutoff,possible)


    elif var == 'y':
        cutoff = len(possible)/2
        possible = possible[cutoff:len(possible)]
        cutoff = possible[len(possible)/2]
        #print possible
        #print cutoff

       if (len(possible) == 1):
           print "Your Number is:", possible
       else:
            var = raw_input("Is Your Number Bigger Than %s? (y/n): " %cutoff)
            guesser(var, cutoff,possible)


    else:
        var = raw_input("Is Your Number Bigger Than 50? (y/n): ")
        guesser(var, 50, possible)

possible = []
possible = range(1,101)

guesser('a', 50, possible)

4 个答案:

答案 0 :(得分:4)

通常情况下,我会尝试帮助您处理代码,但是您已经将它变得非常复杂,以至于我认为查看某些代码会更容易。

def guesser( bounds ):
    a, b = bounds
    mid = ( a + b ) // 2

    if a == b: return a

    if input( "over {0}? ".format( mid ) ) == "y":
        new_bounds = ( mid, b )
    else:
        new_bounds = ( a, mid )

    return guesser( new_bounds )

在深入研究之前,您应该考虑算法如何以抽象的方式工作。

编辑:以简洁为代价简化代码。

答案 1 :(得分:2)

在做更多pythonic之前我可能会让它更简单......算法比必要的复杂得多。当两个整数足够时,无需使用列表。

def guesser(low = 0, up = 100):
    print("Choose a number between %d and %d" % (low, up-1))
    while low < up - 1:
        mid = (low+up)//2
        yn = raw_input("Is Your Number Smaller Than %s? (y/n): " % mid)
        if yn not in ['y', 'n']: continue
        low, up =  (low, mid) if yn == 'y' else (mid, up)
    print "Your Number is:", low


guesser()

答案 2 :(得分:2)

更多pythonic使用bisect模块 - 当然还有class:)

import bisect    
hival= 50

class Guesser(list):
    def __getitem__(self, idx):
        return 0 if raw_input("Is your number bigger than %s? (y/n)"%idx)=='y' else hival

g=Guesser()
print "Think of a number between 0 and %s"%hival
print "Your number is: %s"%bisect.bisect(g,0,hi=hival)

以下是python库中bisect.bisect的定义。如您所见,大多数算法都是为您实现的

def bisect_right(a, x, lo=0, hi=None):
    """Return the index where to insert item x in list a, assuming a is sorted.

    The return value i is such that all e in a[:i] have e <= x, and all e in
    a[i:] have e > x.  So if x already appears in the list, a.insert(x) will
    insert just after the rightmost x already there.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]: hi = mid
        else: lo = mid+1
    return lo

bisect = bisect_right   # backward compatibility

答案 3 :(得分:0)

这不像katrielalex的递归那么优雅,但它说明了一个基本类。

class guesser:
    def __init__(self, l_bound, u_bound):
        self.u_bound = u_bound
        self.l_bound = l_bound
        self.nextguess()

    def nextguess(self):
        self.guess = int((self.u_bound + self.l_bound)/2)
        print 'Higher or lower than %i?' % self.guess

    def mynumberishigher(self):
        self.l_bound = self.guess
        self.nextguess()

    def mynumberislower(self):
        self.u_bound = self.guess
        self.nextguess()