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

Bla*_*man 6 python java dynamic-languages

对于从静态语言(java/c#)移动到动态语言(如python)的人来说,最重要的是什么?

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

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

aar*_*ing 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
Run Code Online (Sandbox Code Playgroud)

请毫不犹豫地将函数视为常规值:它们确实如此。采用以下解析器。假设我们想像对待所有 header 标签一样对待所有 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
Run Code Online (Sandbox Code Playgroud)

这可以通过在 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'")
Run Code Online (Sandbox Code Playgroud)

与 相对isinstance(arg, Foo)attr1这允许您使用和传入任何对象attr2。例如,这允许您传入包裹在对象周围的跟踪类以进行调试。在 Java 中,您必须修改该类才能执行此操作。

正如 THC4k 所指出的,另一种(更Pythonic)的方法是EAPF惯用法。我不喜欢这样,因为我喜欢尽早发现错误。如果您希望代码很少失败,那么效率会更高。不要告诉任何人我不喜欢它,尽管他们会不再认为我知道如何编写Python。这是 THC4k 提供的示例。

try: 
    foo(arg): 
except (AttributeError, TypeError): 
    raise InvalidArgumentError(foo, arg)
Run Code Online (Sandbox Code Playgroud)

我们是否应该捕获它们AttributeErrorTypeError或者只是让它们传播到知道如何处理它们的地方,这是一个难以抉择的问题,但这只是一个例子,所以我们就让它飞吧。