【问题标题】:How to pass a constant variable to a function如何将常量变量传递给函数
【发布时间】:2020-12-20 08:10:34
【问题描述】:

在以下场景中哪一个是更好的设计,为什么?

答:

stop_words = ['com1', 'com2'] 
    
def clean_text(text_tokens, stop_words):
    return [token for token in text_tokens if token not in stop_words]

clean_text(['hello', 'world', 'com1', 'com2'], stop_words)

乙:

def clean_text(text_tokens):
    stop_words = ['com1', 'com2']
    return [token for token in text_tokens if token not in stop_words]

clean_text(['hello', 'world', 'com1', 'com2'])

C:

STOP_WORDS = ['com1', 'com2'] 
    
def clean_text(text_tokens):
    return [token for token in text_tokens if token not in STOP_WORDS]

clean_text(['hello', 'world', 'com1', 'com2'])

根据@MisterMiyagi 的回答添加了 C 版本。

注意1:在这种情况下,stop_words 是固定的,不会改变。

注意 2:stop_words 可以是一个很小的列表,也可以是一个很大的列表。

【问题讨论】:

  • 如果它没有改变,你不需要它的参数。如果您想面向未来,请使用 A 和 stop_words=None anf if stop_words is None: stop_words = ['com1', 'com2']
  • 要完成,还有“中间”的做法:默认参数:clean_text(text_tokens, stop_words=['com1', 'com2']):。它不会污染全局范围,但表达式只计算一次。考虑在问题中将其设为 D 选项:-)

标签: python python-3.x pep8


【解决方案1】:

更喜欢在全局范围内创建常量。全局作用域被评估一次,而函数局部作用域被评估每个函数调用。

对于非常大的搜索,由于其 O(1) 查找比 list O(n) 查找更喜欢使用 set。旨在作为constants should be named with ALL_CAPS_NAMES 的值。函数应该直接引用常量iff它们不会被替换。

STOP_WORDS = {'com1', 'com2'}  # constant set of words
    
def clean_text(text_tokens):
    return [token for token in text_tokens if token not in STOP_WORDS]
    #                             directly access constant ^

clean_text(['hello', 'world', 'com1', 'com2'])

对于小的常量,将它们作为文字提供可能是有利的。甚至 CPython 也能够将内联文字优化为实际常量。

def clean_text(text_tokens):
    return [
        token
        for token in text_tokens
        if token not in {'com1', 'com2'}
        #               ^ compiled as LOAD_CONST (frozenset({'com2', 'com1'}))
    ]

clean_text(['hello', 'world', 'com1', 'com2'])

当前优化器将list 和tuple 文字转换为tuple 常量,并将set 和frozenset 文字转换为frozenset 常量

【讨论】:

  • “总是喜欢在全局范围内创建常量” - 这太强了(从 my 的角度来看)。它具有您描述的优点。但也有一些缺点,例如它可能(取决于实际上下文)污染全局范围,可能会被意外修改等。
【解决方案2】:

中间立场:使用参数的默认值。

def clean_text(text_tokens, stop_words={'com1', 'com2'}):
    return [token for token in text_tokens if token not in stop_words]

clean_text(['hello', 'world', 'com1', 'com2'])

现在常量{'com1', 'com2'}只被创建一次(当函数被定义时);它不会污染全局范围;如果你最终想要,你可以选择在调用clean_text时传递不同的stop_words。

【讨论】:

    【解决方案3】:

    如果您想在每次调用函数时将 stop_words 的不同列表作为参数传递,场景 A 会更好,而场景 B 仅针对 ['com1','com2'] 测试它,这意味着您仅在编辑时更改此列表函数本身。

    结论:场景 A 最好测试不同的列表并将它们作为参数传递给函数。

    【讨论】:

      猜你喜欢
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      相关资源
      最近更新 更多