Новичок (Python 3.6.1): Почему этот скрипт не работает?

Имейте в виду, что я начал изучать Python (первый язык) всего несколько дней назад.

Я пытаюсь найти наибольший простой множитель заданного (и потенциально большого) целого числа «а». Я начну с определения функции prime(n), которая проверяет, является ли целое число n простым или нет. Затем я нахожу множители 'n' числа 'a' от наибольшего к наименьшему и проверяю каждый с помощью простого числа (n). Если найдено простое n, оно распечатывается, и я использую break для завершения процесса. Если n=1 — единственный найденный простой делитель, то «a» — простое число, и поэтому его наибольший простой делитель — это он сам.

Этот скрипт полностью не работает. Переменная n_prime возвращается к тому значению, которое я впервые присвоил ей, даже после того, как Prime(n) должен изменить ее на True или False. Если я начну с None, после Prime(n) он всегда останется None.

Я надеюсь, что это не слишком беспорядочно, и что с моим кодом не слишком много проблем.

def prime(n): 
if n == 1:
    n_prime = False

if n == 2:
    n_prime = True

if n == 3:
    n_prime = True

if n % 2 == 0 and n_prime != True:
    n_prime = False

else:
    for i in range(3, n, 2):
        if i != n:
            if n % i == 0:
                n_prime = False
                break
        else:
            n_prime = True



n_prime = None
a = int(input())

for n in range (a-1, 1, -1):

     if a % n == 0:
          prime(n)
          if n_prime==True:
               if n != 1:
                   print(n, ' is the greatest prime factor of ', a)
                   break
               else:
                   print(a, 'is the greatest prime factor of ', a)
                   break

person mskr    schedule 22.07.2017    source источник
comment
Я не знаю, была ли это опечатка в вашей копии сообщения, но весь блок кода, следующий за def prime(n):, должен иметь отступ.   -  person ifconfig    schedule 22.07.2017
comment
Ваши отступы выглядят не так.   -  person sayan    schedule 22.07.2017
comment
В моем коде все в порядке. Это проблема копипаст.   -  person mskr    schedule 22.07.2017
comment
Вы должны использовать return вместо глобальной переменной, чтобы получить результат prime.   -  person Paul    schedule 22.07.2017
comment
Поскольку в Python отступы имеют большое значение, вам действительно следует исправить эту проблему с копированием и вставкой (иначе трудно сказать, когда заканчивается функция и начинается другой код).   -  person Blckknght    schedule 22.07.2017


Ответы (1)


Ваш код не работает, потому что ваша функция prime не изменяет глобальную переменную n_prime так, как вы ожидаете. Вы можете заставить его работать, добавив оператор global вверху функции: global n_prime. Но это не лучший подход. Изменение глобальных переменных внутри функции лишает многих преимуществ, которые дает функция.

Лучший способ — return значение, которое вы хотите использовать в вызывающем коде:

def prime(n): 
    if n == 2 or n == 3: # We can reorder and combine some of the conditions up here
        return True # return instead of trying to assign to the global variable!

    if n == 1 or n % 2 == 0:
        return False

    for i in range(3, n, 2): # The end value of a range is not used in the iteration.
        if n % i == 0:       # So the logic that was checking `i != n` is unnecessary.
            return False

    return True  # if the loop finished without returning, we know our value is prime

Вот как я бы использовал эту функцию в алгоритме наибольшего простого фактора, который вы показали:

a = int(input())

for n in range (a-1, 1, -1): # This loop stops at 2. It doesn't ever reach 1, but that's OK!
    if a % n == 0 and prime(n): # Test the return value from the function here!
        print(n, ' is the greatest prime factor of ', a)
        break
else: # This else block is attached to the loop. It runs only if the loop didn't `break`.
    print(a, 'is the greatest prime factor of ', a)

Обратите внимание, что нет необходимости сравнивать логическое значение с другим (например, с n_prime == True. Просто используйте логическое значение непосредственно в if (или с логическим оператором, таким как and или or).

Я также хотел бы отметить, что вы можете избавиться от особого случая в конце (когда a является простым числом) и просто изменить цикл, чтобы он начинался с a вместо a-1. Поскольку вы проверяете, является ли n простым, увидев, что это делитель, сообщение будет выведено только в том случае, если функция prime подтвердит, что a не имеет делителей (кроме самого себя и единицы).

person Blckknght    schedule 22.07.2017