1

是否存在与列表常量或任何其他可变对象相关的“陷阱”?

目前,我的上下文与将传递给调用的常量有关,但我一般地问这个问题,因为我认为该主题不会对问题产生有意义的影响。

考虑这个示例代码:

#!/usr/bin/env python
# This file was not tested before posting.

import subprocess

LS_FLAGS = ['-l', '-a']

def main():
    subprocess.call(['ls'] + LS_FLAGS)

if __name__ == '__main__':
    main()

我问这个是因为我非常清楚函数定义中的可变对象引起的问题;而且,即使据我所知,也不应该有任何事情对受人尊敬的常数进行分配或突变;并且“常量”并不是真正的东西:我问,并进一步问,是否有一些约定可以在语义上保护自身而不是意外突变?

4

2 回答 2

2

不必担心变异可以使代码更容易推理,因此,它是纯函数式编程的核心原则之一。

在这种特定情况下,这似乎不是一个严重的问题,甚至可能被认为是一个特性。LS_FLAGS如果您认为没有理由对其进行修改,您始终可以将其定义为元组,但您的代码的用户始终可以根据需要LS_FLAGS完全重新声明。

于 2015-02-20T23:48:55.670 回答
0

您可以通过从类似字典的对象访问“常量”来防止突变。''喜欢''的东西,也许:

class Config:
    _config = dict(
        LS_FLAGS=['-l', '-a']
    )
    def __getitem__(self, idx):
        return Config._config[idx].copy()  # Use copy.deepcopy 
                                           # instead if required

CONFIG=Config()

甚至:

class Config:
    def __getitem__(self, idx):
        if idx == 'LS_FLAGS':
            return ['-l', '-a']

        raise KeyError(idx)

CONFIG=Config()

然后CONFIG像这样使用对象:

print(CONFIG['LS_FLAGS'])

这远非完美(也不是很性感),但这将防止意外1 破坏您的“常量”:

# Try to mutate the constant config
ls_flags = CONFIG['LS_FLAGS']
ls_flags.append('/home')

print(CONFIG['LS_FLAGS']) # unchanged

CONFIG['LS_FLAGS'] = ['-ls']

将提高TypeError: 'Config' object does not support item assignment


¹当然,由于 Python 没有“真正的”常量,因此无法保护您免受恶意代码的侵害。例如,一个可以完全替换CONFIG对象...

于 2015-02-21T00:08:47.970 回答