从静态lang(java / c#)移动到动态语言(如python)的人最常见的问题

时间:2010-09-13 19:29:52

标签: java python dynamic-languages

从静态语言(java / c#)移动到动态语言(如python)的人有哪些最重要的问题?

如何完成任务似乎很酷,但重命名方法或添加/删除参数似乎风险很大!

是为每种方法编写测试的唯一解决方案吗?

3 个答案:

答案 0 :(得分:3)

  

“是为每种方法编写测试的唯一解决方案吗?”

你是说你没有为Java中的每个方法编写测试吗?

如果你用Java编写了每个方法的测试,那么 - 好吧 - 什么都没有改变,是吗?

  

重命名方法,似乎风险很大!

正确。不要这样做。

  

添加/删除参数似乎风险很大!

什么?你在谈论可选参数吗?如果是这样,那么在Java中使用多个重载名称似乎存在风险和混乱。有可选参数似乎更简单。


如果你在SO上搜索最常见的Python问题,你会发现有些东西是慢性问题。

  • 如何更新PYTHONPATH

  • 为什么某些随机浮点计算与数学抽象可能表明的不同。

  • 使用Python 3并从Python 2教程中键入代码。

  • 为什么Python没有超复杂的protectedprivatepublic声明。

  • 为什么Python没有枚举类型。

#1慢性问题似乎是使用可变对象作为函数的默认值。简单地避免这种情况。

答案 1 :(得分:2)

第一次尝试使用Python时遇到的一些事情(来自主要的Java背景):

  1. 编写 Pythonic 代码。使用推荐用于Python的习语,而不是使用旧的Java / C方式。这不仅仅是一个化妆或教条问题。实际上,Pythonic代码在实践中实际上比C代码快得多。事实上,恕我直言,许多“Python很慢”的概念浮出水面是因为没有经验的编码员试图用Python编写Java / C并最终获得了巨大的性能影响并且认为Python是非常慢。尽可能使用列表推导和map / filter / reduce。

  2. 对功能是真正的对象的想法感到满意。将它们作为回调传递,使函数返回函数,了解闭包等。

  3. 你可以在Python中做很多很酷且几乎神奇的东西,比如你提到的重命名方法。这些东西很适合展示Python的功能,但如果你不需要它们,那就没必要了。事实上,正如S. Lott指出的那样,最好避免看似有风险的事情。

答案 2 :(得分:2)

我想说,第一个问题是尝试用动态语言编写静态类型代码。

不要犹豫,使用标识符指向字符串,然后使用自包含代码段中的列表

keys = 'foo bar foobar' # Imagine this coming in as an argument
keys = keys.split() # Now the semantically chose name for the argument can be 
                    # reused As the semantically chosen name for a local variable

毫不犹豫地将函数视为常规值:它们是。采取以下解析器。假设我们想要处理所有标头标签和ul标签,如ol标签。

class Parser(HTMLParser):
    def __init__(self, html):
        self.feed(html)

    def handle_starttag(self, tag, attrs):
        parse_method = 'parse_' + tag    
        if hasattr(self, parse_method):  
            getattr(self, parse_method)(attrs)


    def parse_list(self, attrs):
        # generic code

    def parse_header(self, attrs):
       # more generic code

    parse_h1 = parse_h2 = parse_h3 = parse_h4 = parse_h5 = parse_h6 = parse_header
    parse_ol = parse_ul = parse_list

这可以通过在像{java}这样的语言中使用handle_starttag方法中较不通用的代码来完成,方法是跟踪哪些标记映射到同一个方法但是如果您决定要处理div标记,那么必须将其添加到调度逻辑中。在这里,您只需添加方法parse_div,就可以了。

请勿进行类型检查!鸭型!

def funtion(arg):
    if hasattr(arg, 'attr1') and hasattr(arg, 'attr2'):
         foo(arg):
    else:
         raise TypeError("arg must have 'attr1' and 'attr2'")

而不是isinstance(arg, Foo)。这样,您就可以使用attr1attr2传入任何对象。这允许您例如传入包裹在对象周围的跟踪类以进行调试。您必须修改类才能在Java AFAIK中执行此操作。

正如THC4k指出的那样,另一种(更加pythonic)方式是EAPF成语。 我不喜欢这个,因为我喜欢尽早发现错误。如果您希望代码很少失败,那么效率会更高。不要告诉任何人我不喜欢它虽然我们他们会不再认为我知道如何编写python。这是THC4k的一个例子。

try: 
    foo(arg): 
except (AttributeError, TypeError): 
    raise InvalidArgumentError(foo, arg)

如果我们应该抓住AttributeErrorTypeError或者让它们传播到知道如何处理它们的地方,这是一个折腾,但这只是一个例子,所以我们会让它飞。