1

我已经阅读了一周的 Python 知识,只是想通过创建一个税级计算器来尝试一下。我还没有完成,但我想知道我是否走在正确的轨道上,或者就 python 编程而言。我之前只做过一点 C++ 编程,感觉就像它显示(好/坏?)

#There are six brackets define by the IRS as of 2009
#Schedule X - Single
first_bracket = 8350
second_bracket = 33950
third_bracket = 82250
fourth_bracket = 171550
fifth_bracket = 372950

def b1(a):
    a = a * .10
    return a
def b2(a):
    a = a * .15
    return a
def b3(a):
    a = a * .25
    return a
def b4(a):
    a = a * .28
    return a
def b5(a):
    a = a * .33
    return a
def b6(a):
    a = a * .35
    return a

if __name__ == '__main__': #importing is fun

    #Ask for salary
    salary = float(raw_input("Enter your salary\n"))    

    #First bracket
    if salary >= 0 and salary <= first_bracket:
        taxed = b1(salary)
        #print "You make less than $", float(first_bracket), "so your tax is $", taxed
        print taxed

    #Second bracket
    elif salary > first_bracket and salary <= second_bracket:
        taxed = b1(first_bracket) + b2(salary-first_bracket)
        #print "You make between $", first_bracket+1, "and $", second_bracket, "so your tax is $", taxed
        print taxed

    #Thrid bracket  
    elif salary > second_bracket and salary <= third_bracket:
        taxed = b1(first_bracket) + b2(second_bracket-first_bracket) + b3(salary-second_bracket)
        print taxed
4

7 回答 7

13

使用列表和对而不是每个括号的限制和速率的单独变量可能有一种更有效的方法。例如,考虑以下情况:

# List of (upper-limit, rate) pairs for brackets.
brackets = [ (8350, .10), (33950, .15), (82250, .25), (171550, .28), (372950, .33) ]

if __name__ == '__main__':

    salary = float(raw_input("Enter your salary\n"))

    accounted_for = 0 # Running total of the portion of salary already taxed
    taxed = 0 # Running total of tax from portion of salary already examined

    for (limit, rate) in brackets:
        if salary < limit:
            taxed += ( (salary - accounted_for) * rate )
            accounted_for = salary
            break # We've found the highest tax bracket we need to bother with
        else:
            taxed += ( (limit - accounted_for) * rate )
            accounted_for = limit

    # If we went over the max defined tax bracket, use the final rate
    if accounted_for < salary:
        taxed += ( (salary - accounted_for) * 0.35 )

    print taxed

这个想法是我们不想重复我们不必仅仅因为我们有多个相似数据项可以使用的代码。除了不同的税率和限制之外,税级的功能都相同,因此我们希望这些作为标准计算的输入,而不是它们自己的单独功能。

于 2009-08-01T11:23:11.520 回答
5

特别是在处理财务价值时,您应该考虑使用十进制模块来确保输出中没有浮点错误。

当您只是制作玩具来学习语言时,这没什么大不了的,但很高兴知道以供将来参考:)

于 2009-08-01T14:49:24.633 回答
2

4个空格缩进!查看此文档,以及

import this
输出更多。不过对我来说看起来不错,很容易阅读。

于 2009-08-01T12:14:14.153 回答
2

您可以像这样更改行:

if salary >= 0 and salary <= first_bracket:

对此:

if 0 <= salary <= first_bracket:

就像你在数学中所做的那样。它通常使代码更具可读性。

于 2009-08-01T12:26:13.440 回答
1

由于这些功能相当简单,您可以执行以下操作:

def b1(a):
    return a * .10

您还可以创建一个统一的征税功能:

def tax_me(salary, rate):
    return salary * rate

好像戴夫把你修好了:)

玩得开心 Python,它是一门很棒的语言。

于 2009-08-01T15:20:47.843 回答
1

将收入和税率数据结构化为表格(元组列表或元组的元组)是一个巨大的改进。如该示例所示,它允许使用表格驱动的方法来处理任务的其余部分(向上遍历表格以找到给定工资的最高费率,然后从该点向下遍历累积税款并计算总工资) .

为了使所有这些成为我的“Pythonic”,我们将定义功能以及if __name__==行上方的税率表。这将隐式允许我们将文件导入任何其他代码并使用该函数。

if __name__ ==行下面的部分是一个驱动程序,它使用给定的任何输入调用功能(或可用于保存单元测试,以便可以调用任何模块来测试它自己的功能)。

所以我们的代码可能看起来像:

#!/usr/bin/env python
tax_table = (
(8350, 0.10),
...
)

def compute(salary):
'''Compute taxes for a given salary'''
result = 0
accounted_for = 0
...
return result

if __name__ == "__main__":
import sys
try:
sal = float(raw_input("Please enter salary: ")
except EnvironmentError, err:
print >> sys.stderr, "Error with your input, aborting"
print >> sys.stderr, "The error was:", err
sys.exit(1)
print compute(sal)

请注意,我们现在已经将可重用功能与我们的使用分开......这允许我们重用代码......但也促进了测试驱动的开发和重构。我们可以使用相同的 API 编写非交互式测试套件(到目前为止只是调用compute()函数),这将使我们能够自信地重构(并且无需触及下面的用法 --- 这是我们的“应用程序”在这种情况下)。

目前尚不清楚此特定代码是否会因重构为一个或多个类而受益。当然,用不同的税表实例化一个类的能力会很方便。然后税率可以存储在其他地方(从文件中读取、从 Web 服务器中提取或从数据库中查询;Python 使所有这些几乎同样容易)。

但是,我们不必去“OO”来将该功能添加到我们的compute()函数中。

我们可以向计算函数添加一个可选参数,这样如果我们提供一个,它将使用不同的税率表,或者默认为我们硬编码到模块中的那个。为此,我们简单地将初始函数定义行更改为:def compute(salary, table=tax_table):...我们修复了一些上限处理(将 0.35 速率从函数中分解到表中,将“sys.maxint”作为我们的限制或“无”对象)。

对于这样一个简单的练习,不值得担心。但一般来说,最好先投入大量精力来定义我们想要的 API。如果您能提出一个健壮、灵活的 API,那么任何符合您的初始要求(正确性和可接受的性能)的符合实现都将允许您交付您的应用程序。

更重要的是,您可以随意重新实现。也许需要使用bisect模块之类的东西来搜索一个非常复杂的税表,因为线性搜索需要很长时间才能找到最高税率,或者某些类型的所得税抵免和扣除或受抚养人的数量需要传递到计算中()功能等。理想情况下,此类更改可以透明地完成。您现有的任何用法都不必更改,因为您已经重新实现了我们模块的内部结构。即使您添加了功能,您也不必担心现有的使用情况(可选参数和“关键字”参数(在可选参数之后传递的字典)让我们为函数执行此操作,并且类可以添加属性和方法而不会干扰任何适当的现有用法。(是的,子类化用法可能会因某些更改而被破坏;但这通常不是问题)。

在 Python 中,可以将一些东西写成一个简单的 Python 模块,然后将其重新实现为一个包,或者将其重新实现为一个已编译的 C 模块或包含一些 C 模块的包……所有这些都不会影响使用。从用户的角度来看, import语句在 Python 模块、包和编译模块(“共享对象”或 DLL)上的工作方式相同。

从历史上看,这一直是 Python 在自身开发中的巨大优势。他们已经能够为现有库添加大量功能,并且很少被迫通过“弃用/重命名”扭曲。由于这个原因,Python 3.0 的相当多的功能能够被添加到 Python 2.7 中。

于 2009-08-01T20:50:45.983 回答
0

PyLint这样的工具可以捕捉到很多错误和不良做法,包括错误的命名约定。PyChecker也不错。

于 2009-08-01T12:35:02.023 回答