这是我在python中编写的第一件事.我来自Java背景.我不想只学习如何用Python语法编写java代码.我想学习如何用pythonic范例编程.
你能不能评论我如何使下面的代码更pythonic?
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))
Run Code Online (Sandbox Code Playgroud)
Tho*_*ers 21
只需使用'import math'和'math.sqrt()'代替'from math import sqrt'和'sqrt()'; 你只是导入'sqrt'就不会赢得任何东西,并且代码很快会因为太多的导入而变得笨拙.此外,当你大量使用from-import时,reload()和mock for out等测试会更快地破解.
divmod()函数是执行除法和模数的便捷方式.您可以使用/ 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
Run Code Online (Sandbox Code Playgroud)
使用生成器意味着您只能迭代结果一次; 如果您只想要一个列表(就像在translateFactorsList中那样),则必须将调用包装在lists()中的factors()中.
Jas*_*ker 17
您可能想要看的另一件事是文档字符串.例如,此函数的注释:
# recursively computes the factors of a number
def factors(num):
Run Code Online (Sandbox Code Playgroud)
可以转换成这个:
def factors(num):
""" recursively computes the factors of a number"""
Run Code Online (Sandbox Code Playgroud)
这样做并不是真的100%必要,但如果你开始使用pydoc的东西,这是一个很好的习惯.
你也可以这样做:
"""This is a docstring"""
Run Code Online (Sandbox Code Playgroud)
>>> import docstring
>>> help(docstring)
Run Code Online (Sandbox Code Playgroud)
Help on module docstring:
NAME
docstring - This is a docstring
FILE
/Users/jason/docstring.py
Run Code Online (Sandbox Code Playgroud)
一些评论:
range()为xrange(); 当你调用时range(),它会同时分配整个范围,而当你迭代时xrange(),它会一次返回一个结果,从而节省内存.if num2s -- 0: return factorList)上.它使得一眼就能看到它正在做什么变得更加困难(这是一个障碍).[sympy][1]模块已经具有计算因子的代码,这可以通过消除大部分代码来简化代码.例如:
factorList.insert(0, '2 ^ ' + str(num2s))
Run Code Online (Sandbox Code Playgroud)
可以改为
factorlist.insert(0, '2 ^ %s' % num2s)
Run Code Online (Sandbox Code Playgroud)
总而言之,我发现你的代码并不是广泛的非pythonic.只要确保你想要使用地板划分,因为这是默认情况下会发生的整数值.否则,您需要修复除法运算符:
from __future__ import division
Run Code Online (Sandbox Code Playgroud)
有时令人沮丧的语言警告.
这是我突然想到的:
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]
Run Code Online (Sandbox Code Playgroud)
这种形式[f for f in factorList if f != 2]称为列表理解。