Новичок, задающийся вопросом, является ли его кодом [закрытый] 'Pythonic'

Если ваша проблема ожидает загрузки файла ... Я использую это:

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
23
задан GEOCHET 25 September 2008 в 18:20
поделиться

12 ответов

Просто используйте «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 ().

21
ответ дан 29 November 2019 в 00:42
поделиться

Еще одной вещью, на которую Вы могли бы хотеть посмотреть, является docstring. Например, комментарий для этой функции:

# recursively computes the factors of a number
def factors(num):

Мог быть преобразован в это:

def factors(num):
    """ recursively computes the factors of a number"""

не на действительно 100% необходимо сделать это этот путь, но это - хорошая привычка войти в случае, если Вы когда-либо начинаете использовать что-то вроде pydoc.

можно также сделать это:

docstring.py

"""This is a docstring"""

в командной строке:

>>> import docstring
>>> help(docstring)

результаты:

Help on module docstring:

NAME
    docstring - This is a docstring

FILE
    /Users/jason/docstring.py
17
ответ дан 29 November 2019 в 00:42
поделиться

Несколько комментариев:

  1. я заменил бы range() xrange(); когда Вы звоните range(), это выделяет весь диапазон внезапно, тогда как, когда Вы выполняете итерации [более чем 116], это возвращает каждый результат по одному, сохраняя память.
  2. не помещают выражения после условных выражений на той же строке (if num2s -- 0: return factorList). Это делает его тяжелее для наблюдения сразу, что это делает (что это - блок).
  3. не боятся использовать модули. [sympy][1] модуль уже имеет код для вычисления факторов, которые могут упростить код путем устранения большей части из него.
  4. строковое форматирование Python является простым и эффективным.

, Например:

factorList.insert(0, '2 ^ ' + str(num2s))

мог быть изменен на [1 117]

factorlist.insert(0, '2 ^ %s' % num2s)

, В целом, я не нахожу, что Ваш код экстенсивно un-pythonic. Просто удостоверьтесь, что Вы хотите использовать подразделение пола , потому что это - то, что имеет тенденцию происходить по умолчанию с целочисленными значениями. Иначе необходимо будет согласовать оператор деления:

from __future__ import division

А иногда расстраивающий протест языка.

8
ответ дан 29 November 2019 в 00:42
поделиться
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:

  • PEP-8 совместимое именование
  • разрезание (и присвоение частям)
  • итераторы
  • строка, форматирующая

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

Редактирование : удаленные особые случаи для некоторых списков, более компактных этот путь

4
ответ дан 29 November 2019 в 00:42
поделиться

Не бойтесь пониманий списка. Переключение от Java до Python и обнаружение их были хорошим днем.

Для функции факторов, возможно, что-то вроде этого:

def factors(num):
    return [i for i in xrange(1, num+1) if num % i == 0]

, Вероятно, не лучший код, но это коротко и легко понять.

Удача с Python, это - большой язык.

3
ответ дан 29 November 2019 в 00:42
поделиться

Вот как бы я это сделал ...

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)
3
ответ дан 29 November 2019 в 00:42
поделиться

Так как это сообщение, кажется, возрождено Кейси (lol), добавлю я в своих 2 центах.

Пробегаются через все в PEP-8. Это выручило меня существенно, когда у меня были проблемы форматирования кода.

2
ответ дан 29 November 2019 в 00:42
поделиться

Вот что на меня бросается:

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] называется списочным пониманием.

2
ответ дан 29 November 2019 в 00:42
поделиться

Существует превосходная краткая информация David Goodger, позвонившего "Код Как Pythonista" здесь . Несколько вещей от того текстового именования ре (заключение в кавычки):

  • joined_lower для функций, методов, атрибуты

  • joined_lower или ALL_CAPS для констант

  • StudlyCaps для классов

  • camelCase только для приспосабливания существующим ранее соглашениям

22
ответ дан 29 November 2019 в 00:42
поделиться

Основываясь на ответе Криса, немного упрощено:

  • для того, чтобы вместо внешнего, в то время как
  • внутреннего, сохранить возможность повторного использования одного и того же делителя
  • , использовать итертуалы. groupby упрощает сжатие() с помощью
  • исправляет небольшую ошибку в tstring()

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'
4
ответ дан 29 November 2019 в 00:42
поделиться

Использование рекурсии (где нет необходимости) не является питоническим. На питоне нет элиминации рекурсии хвоста, и 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
1
ответ дан 29 November 2019 в 00:42
поделиться

Я бы использовал понимание списка, чтобы вывести двойки:

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
2
ответ дан 29 November 2019 в 00:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: