Если ваша проблема ожидает загрузки файла ... Я использую это:
Dim FilePath As String, FileName As String, FindIt As String
FilePath = wb.Path & "\"
FileName = FilePath & "yourfilename"
FindIt = Dir(FileName )
While Len(FindIt) = 0
FindIt = Dir(FileName )
Wend
Просто используйте «import math» и «math.sqrt ()» вместо «from math import sqrt» и «sqrt ()»; вы ничего не выиграете, просто импортировав 'sqrt', и код быстро становится громоздким из-за слишком большого числа операций импорта from. Кроме того, такие вещи, как reload () и макетирование для тестов, ломаются намного быстрее, когда вы часто используете from-import.
Функция divmod () - это удобный способ выполнять деление и по модулю. Вы можете использовать for / else вместо отдельной проверки на numleft. Ваша функция факторов - естественный кандидат на генератор. xrange () уже упоминался в другом ответе. Вот как все это делается:
import math
# recursively computes the factors of a number as a generator
def factors(num):
numroot = int(math.sqrt(num)) + 1
# brute force divide the number until you find a factor
for i in xrange(2, numroot):
divider, remainder = divmod(num, i)
if not remainder:
# if we found a factor, add it to the list and compute the
# remainder
yield i
break
else:
# if we didn't find a factor, get out of here!
yield num
return
# now recursively find the rest of the factors
for factor in factors(divider):
yield factor
Использование генератора означает, что вы можете перебрать результат только один раз; если вы просто хотите получить список (как вы делаете в translateFactorsList), вам придется заключить вызов factor () в list ().
Еще одной вещью, на которую Вы могли бы хотеть посмотреть, является docstring. Например, комментарий для этой функции:
# recursively computes the factors of a number
def factors(num):
Мог быть преобразован в это:
def factors(num):
""" recursively computes the factors of a number"""
не на действительно 100% необходимо сделать это этот путь, но это - хорошая привычка войти в случае, если Вы когда-либо начинаете использовать что-то вроде pydoc.
можно также сделать это:
"""This is a docstring"""
>>> import docstring
>>> help(docstring)
Help on module docstring:
NAME
docstring - This is a docstring
FILE
/Users/jason/docstring.py
Несколько комментариев:
range()
xrange()
; когда Вы звоните range()
, это выделяет весь диапазон внезапно, тогда как, когда Вы выполняете итерации [более чем 116], это возвращает каждый результат по одному, сохраняя память. if num2s -- 0: return factorList
). Это делает его тяжелее для наблюдения сразу, что это делает (что это - блок). [sympy][1]
модуль уже имеет код для вычисления факторов, которые могут упростить код путем устранения большей части из него. , Например:
factorList.insert(0, '2 ^ ' + str(num2s))
мог быть изменен на [1 117]
factorlist.insert(0, '2 ^ %s' % num2s)
, В целом, я не нахожу, что Ваш код экстенсивно un-pythonic. Просто удостоверьтесь, что Вы хотите использовать подразделение пола , потому что это - то, что имеет тенденцию происходить по умолчанию с целочисленными значениями. Иначе необходимо будет согласовать оператор деления:
from __future__ import division
А иногда расстраивающий протест языка.
from itertools import takewhile
def transform_factor_list(factor_list):
num_2s = len(list(takewhile(lambda e: e == 2, factor_list)))
if num_2s > 1:
factor_list[:num_2s] = ["2 ^ %i" % (num_2s, )]
return factor_list
Это - то, что я сделал бы из второй функции.
Большинство изменений pythonic:
, функция предполагает, что вход заказан, который выполняется факторами.
Редактирование : удаленные особые случаи для некоторых списков, более компактных этот путь
Не бойтесь пониманий списка. Переключение от Java до Python и обнаружение их были хорошим днем.
Для функции факторов, возможно, что-то вроде этого:
def factors(num):
return [i for i in xrange(1, num+1) if num % i == 0]
, Вероятно, не лучший код, но это коротко и легко понять.
Удача с Python, это - большой язык.
Вот как бы я это сделал ...
import itertools
import collections
def factorize(n):
# ideally an iterator of prime numbers
# this'll work though
divisors = itertools.count(2)
divisor = divisors.next()
while True:
if divisor**2 > n:
yield n
break
a,b = divmod(n, divisor)
if b == 0:
yield divisor
n = a
else:
divisor = divisors.next()
def compress(factors):
summands = collections.defaultdict(lambda: 0)
for factor in factors:
summands[factor] += 1
return [(base, summands[base]) for base in sorted(summands)]
def tostring(compressed):
return ' * '.join("%d**%d" % factor for factor in compressed)
Так как это сообщение, кажется, возрождено Кейси (lol), добавлю я в своих 2 центах.
Пробегаются через все в PEP-8. Это выручило меня существенно, когда у меня были проблемы форматирования кода.
Вот что на меня бросается:
def transformFactorList(factorList):
oldsize = len(factorList)
factorList = [f for f in factorList if f != 2]
num2s = oldsize - len(factorList)
if num2s == 0:
return []
if num2s == 1:
return [2]+factorList
return ['2 ^ %s' % num2s] + [factorList]
Форма [f for f in factorList if f != 2]
называется списочным пониманием.
Существует превосходная краткая информация David Goodger, позвонившего "Код Как Pythonista" здесь . Несколько вещей от того текстового именования ре (заключение в кавычки):
joined_lower
для функций, методов, атрибуты
joined_lower
или ALL_CAPS для констант
StudlyCaps
для классов
camelCase
только для приспосабливания существующим ранее соглашениям
Основываясь на ответе Криса, немного упрощено:
HTH:
import itertools
def factorize(n):
# ideally an iterator of prime numbers
# this'll work though
divisors = itertools.count(2)
for divisor in divisors:
# This condition is very clever!
# Note that `n` is decreasing, while `divisor` is increasing.
# And we know that `n` is not divisible by anything smaller,
# so this stops as soon as the remaining `n` is obviously prime.
if divisor**2 > n:
yield n
break
while n % divisor == 0:
yield divisor
n //= divisor
def compress(factors):
for (factor, copies) in itertools.groupby(factors):
# The second object yielded by groupby is a generator of equal factors.
# Using list() to count its length.
power = len(list(copies))
yield (factor, power)
def tostring(compressed):
return ' * '.join("%d**%d" % (factor, power) for (factor, power) in compressed)
# test
assert tostring(compress(factorize(12))) == '2**2 * 3**1'
Использование рекурсии (где нет необходимости) не является питоническим. На питоне нет элиминации рекурсии хвоста, и flat лучше, чем вложенная .
В случае сомнений попробуйте импортировать это
обновление: по популярному запросу идет итеративная факторизация (вздох):
"""returns an iterator of tuples (factor, power) such that
reduce(operator.mul, (factor**power for factor, power in factors(n))) == n """
def factors(n):
i = 2
while n > 1:
p = 0
while n > 1 and n % i == 0:
p += 1
n /= i
if p:
yield (i, p)
i += 1
Я бы использовал понимание списка, чтобы вывести двойки:
def transformFactorList(factorList):
twos = [x for x in factorList if x == 2]
rest = [x for x in factorList if x != 2]
rest.insert(0, "2 ^ %d" % len(twos))
return rest
Обратите внимание, что это даст вам 2^0
и 2^1
, чего ваш код не дал. То, что вы делаете с двойками, кажется арбитражным (иногда вы получаете строку, иногда число, иногда ничего), так что я подумал, что это было бы неплохо. Вы можете легко это изменить, если хотите:
def transformFactorList(factorList):
twos = [x for x in factorList if x == 2]
rest = [x for x in factorList if x != 2]
if twos:
rest.insert(0, 2 if len(twos)==1 else "2 ^ %d" % len(twos))
return rest