Генератор палиндромов

Очень неопытен в python и программировании в целом.

Я пытаюсь создать функцию, которая генерирует список палиндромных чисел до указанного предела.

Когда я запускаю следующий код, он возвращает пустой список []. Не уверен, почему это так.

def palin_generator():
    """Generates palindromic numbers."""

    palindromes=[]
    count=0
    n=str(count)

    while count<10000:
        if n==n[::-1] is True:
            palindromes.append(n)
            count+=1
        else:
            count+=1

    print palindromes  

person Chris    schedule 02.07.2013    source источник


Ответы (3)


Ваше утверждение if не делает то, что вы думаете.

Вы применяете цепочку операторов и тестируете 2 вещи:

(n == n[::-1]) and (n[::-1] is True)

Это всегда будет False, потому что '0' is True не True. Демо:

>>> n = str(0)
>>> n[::-1] == n is True
False
>>> n[::-1] == n 
True

Из документации по сравнениям:

Сравнения могут быть произвольно связаны, например, x < y <= z эквивалентно x < y and y <= z, за исключением того, что y оценивается только один раз (но в обоих случаях z вообще не оценивается, когда x < y оказывается ложным).

Вам не нужно проверять здесь is True; Оператор Python if вполне способен проверить это сам:

if n == n[::-1]:

Ваша следующая проблема заключается в том, что вы никогда не меняете n, поэтому теперь вы добавите в свой список 1000 строк '0'.

Лучше использовать цикл for поверх xrange(1000) и устанавливать n на каждой итерации:

def palin_generator():
    """Generates palindromic numbers."""

    palindromes=[]

    for count in xrange(10000):
        n = str(count)
        if n == n[::-1]:
            palindromes.append(n)

    print palindromes  

Теперь ваша функция работает:

>>> palin_generator()
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '11', '22', '33', '44', '55', '66', '77', '88', '99', '101', '111', '121', '131', '141', '151', '161', '171', '181', '191', '202', '212', '222', '232', '242', '252', '262', '272', '282', '292', '303', '313', '323', '333', '343', '353', '363', '373', '383', '393', '404', '414', '424', '434', '444', '454', '464', '474', '484', '494', '505', '515', '525', '535', '545', '555', '565', '575', '585', '595', '606', '616', '626', '636', '646', '656', '666', '676', '686', '696', '707', '717', '727', '737', '747', '757', '767', '777', '787', '797', '808', '818', '828', '838', '848', '858', '868', '878', '888', '898', '909', '919', '929', '939', '949', '959', '969', '979', '989', '999', '1001', '1111', '1221', '1331', '1441', '1551', '1661', '1771', '1881', '1991', '2002', '2112', '2222', '2332', '2442', '2552', '2662', '2772', '2882', '2992', '3003', '3113', '3223', '3333', '3443', '3553', '3663', '3773', '3883', '3993', '4004', '4114', '4224', '4334', '4444', '4554', '4664', '4774', '4884', '4994', '5005', '5115', '5225', '5335', '5445', '5555', '5665', '5775', '5885', '5995', '6006', '6116', '6226', '6336', '6446', '6556', '6666', '6776', '6886', '6996', '7007', '7117', '7227', '7337', '7447', '7557', '7667', '7777', '7887', '7997', '8008', '8118', '8228', '8338', '8448', '8558', '8668', '8778', '8888', '8998', '9009', '9119', '9229', '9339', '9449', '9559', '9669', '9779', '9889', '9999']
person Martijn Pieters    schedule 02.07.2013

Перебирать все числа довольно неэффективно. Вы можете генерировать палиндромы следующим образом:

#!/usr/bin/env python
from itertools import count

def getPalindrome():
    """
        Generator for palindromes.
        Generates palindromes, starting with 0.
        A palindrome is a number which reads the same in both directions.
    """
    yield 0
    for digits in count(1):
        first = 10 ** ((digits - 1) // 2)
        for s in map(str, range(first, 10 * first)):
            yield int(s + s[-(digits % 2)-1::-1])

def allPalindromes(minP, maxP):
    """Get a sorted list of all palindromes in intervall [minP, maxP]."""
    palindromGenerator = getPalindrome()
    palindromeList = []
    for palindrome in palindromGenerator:
        if palindrome > maxP:
            break
        if palindrome < minP:
            continue
        palindromeList.append(palindrome)
    return palindromeList

if __name__ == "__main__":
    print(allPalindromes(4456789, 5000000))

Этот код намного быстрее, чем код выше.

См. также: замечания по Python 2.x.

person Martin Thoma    schedule 08.11.2013

Ваш блок if проверяет, является ли n палиндромом, и значение n никогда не меняется. Он назначается только один раз.

Кроме того, вы можете удалить часть is True, потому что она избыточна.

Но это не корень вашей проблемы сейчас. На самом деле причина, по которой ваш if не работает, заключается в приоритете оператора. То, что вы сейчас написали, эквивалентно if n==(n[::-1] is True):, то есть if n==False:, чего никогда не будет.

person recursive    schedule 02.07.2013
comment
@MartijnPieters: Верно. Я добавил объяснение о is. - person recursive; 03.07.2013