代码之家  ›  专栏  ›  技术社区  ›  jjnguy Julien Chastang

初学者想知道他的代码是不是“蟒蛇”[结束]

  •  23
  • jjnguy Julien Chastang  · 技术社区  · 16 年前

    这确实是我用python编写的第一件事。我来自Java背景。我不想仅仅学习如何用Python语法编写java代码。我想学习如何在蟒蛇的范例中编程。

    你们能评论一下我如何使下面的代码更像蟒蛇吗?

    from math import sqrt
    
    # recursively computes the factors of a number
    def factors(num):
        factorList = []
        numroot = int(sqrt(num)) + 1
        numleft = num
        # brute force divide the number until you find a factor
        for i in range(2, numroot):
            if num % i == 0:
                # if we found a factor, add it to the list and compute the remainder
                factorList.append(i)
                numleft = num / i
                break
        # if we didn't find a factor, get out of here!
        if numleft == num: 
            factorList.append(num)
            return factorList
        # now recursively find the rest of the factors
        restFactors = factors(numleft)
        factorList.extend(restFactors)
    
        return factorList
    
    # grabs  all of the twos in the list and puts them into 2 ^ x form
    def transformFactorList(factorList):
        num2s = 0
        # remove all twos, counting them as we go
        while 2 in factorList:
            factorList.remove(2)
            num2s += 1
        # simply return the list with the 2's back in the right spot
        if num2s == 0: return factorList
        if num2s == 1:
            factorList.insert(0, 2)
            return factorList
        factorList.insert(0, '2 ^ ' + str(num2s))
        return factorList
    
    print transformFactorList(factors(#some number))
    
    12 回复  |  直到 16 年前
        1
  •  22
  •   unmounted    16 年前

    大卫·古德格有一本优秀的入门读物叫做“像蟒蛇一样的代码” here

    • joined_lower 对于函数、方法, 属性

    • 加入了_-lower 或者所有的 常量

    • StudlyCaps

    • camelCase 只为了符合 现有公约

        2
  •  21
  •   Thomas Wouters    16 年前

    只需使用'import math'和'数学.sqrt()'而不是'from math import sqrt'和'sqrt()';您只通过导入'sqrt'不会赢得任何东西,而且代码很快就会因导入过多而变得笨拙。此外,当您大量使用from import时,诸如reload()和模拟测试的情况会更快地中断。

    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中所做的那样),则必须将对factors()的调用包装在list()中。

        3
  •  17
  •   Jason Baker    16 年前

    另一个你可能想看的东西是docstring。例如,此函数的注释:

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

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

    这样做并不是百分之百的必要,但这是一个很好的习惯,以防你开始使用类似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
    
        4
  •  8
  •   Dan Udey    16 年前

    一些评论:

    1. 我会替换 range() xrange() ,它一次分配整个范围,而当您在 每次返回一个结果。
    2. if num2s -- 0: return factorList
    3. 不要害怕使用模块。这个 [sympy][1]
    4. Python的字符串格式简单而有效。

    例如:

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

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

    总而言之,我不认为你的代码完全不是蟒蛇式的。只要确定你想用 floor division ,因为默认情况下整数值会发生这种情况。否则,您将需要修复除法运算符:

    from __future__ import division
    

    有时令人沮丧的语言警告。

        5
  •  4
  •   Torsten Marek    16 年前
    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
    

    • PEP-8 兼容命名
    • 切片(并指定给切片)
    • 迭代器

    该函数假定输入是有序的,这是由因子实现的。

    编辑

        6
  •  4
  •   Beni Cherniavsky-Paskin    15 年前

    根据克里斯的回答,略作简化:

    • 内部的,同时保持重复使用同一除数的能力
    • 使用itertools.groupby大大简化了compress()

    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'
    
        7
  •  3
  •   Nope    16 年前

    不要害怕清单理解。从Java转换到Python并发现它们是一个好日子。

    对于因子函数,可能是这样的:

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

    祝Python好运,它是一门很棒的语言。

        8
  •  3
  •   chris chris    15 年前

    我就是这样做的。。。

    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)
    
        9
  •  2
  •   Evan Fosmark    16 年前

    检查所有的东西 PEP-8 . 当我遇到代码格式问题时,它帮了我很大的忙。

        10
  •  2
  •   jjnguy Julien Chastang    15 年前

    我突然意识到:

    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]

        11
  •  2
  •   Claudiu    15 年前

    我会用列表理解法把他们俩弄出来:

    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
    
        12
  •  1
  •   fortran    14 年前

    平的比嵌套的好

    有疑问时,试试看 import this

    更新

    """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