Python 高手编程系列三千四百三十六 :命名和使用

Python 高手编程系列三千四百三十六 :命名和使用 常量用来定义程序所依赖的一组值例如默认配置文件名。好的做法是将所有常量集中放在包中的一个文件内。举个例子Django 采用的就是这种方法。一个名为 settings.py 的模块提供所有常量如下所示config.pySQL_USER ‘tarek’SQL_PASSWORD ‘secret’SQL_URI ‘postgres://%s:%slocalhost/db’ % (SQL_USER, SQL_PASSWORD)MAX_THREADS 4另一种方法是使用可以被 ConfigParser 模块或类似 ZConfigZope 中用于描述其配置文件的解析器之类的高级工具解析的配置文件。但有些人认为对于 Python 这种文件能够像文本文件一样轻松编辑和修改的语言来说使用另一种文件格式可能是过分之举。对于表现得像标记的选项通常的做法是将它们和布尔运算结合起来就像 doctest和 re 模块所做的那样。doctest 中的模式很简单如下所示OPTIONS {}def register_option(name):return OPTIONS.setdefault(name, 1 len(OPTIONS))def has_option(options, name):return bool(options name)现在定义选项BLUE register_option(‘BLUE’)RED register_option(‘RED’)WHITE register_option(‘WHITE’)你将会得到下列结果我们来尝试一下SET BLUE | REDhas_option(SET, BLUE)Truehas_option(SET, WHITE)False在创建这样一组新的常量时应避免对它们使用共同的前缀除非模块中有多组常量。模块名称本身就是一个共同的前缀。另一种解决方法是使用内置 enum 模块的 Enum 类并且依赖于 set 集合类型而不是二进制运算符。不幸的是Enum 类在面向旧 Python 版本的代码中应用有限因为 enum 模块由 Python 3.4 版提供。公有和私有变量对于可变的且可以通过导入自由访问的全局变量如果它们需要被保护那么应该使用带一个下划线的小写字母。但这种变量不经常使用因为如果它们需要被保护模块通常会提供 getter 和 setter 来处理。在这种情况下一个前缀下划线可以将变量标记为包的私有元素如下所示_observers []def add_observer(observer):_observers.append(observer)def get_observers():““确保_observers 不能被修改。””return tuple(_observers)位于函数和方法中的变量遵循相同的规则并且永远不会被标记为私有因为它们对上下文来说是局部变量。对于类或实例变量而言只在将变量作为公有签名的一部分不会带来任何有用信息或者冗余的情况下才必须使用私有标记符前缀下划线。换句话说如果变量在方法内部使用用来提供公有功能并且只具有这个功能那么最好将其设为私有。例如支持 property 的属性是很好的私有成员如下所示class Citizen(object):definit(self):self._message ‘Rosebud…’def _get_message(self):return self._messagekane property(_get_message)另一个例子是用来记录内部状态的变量。这个值对其他代码没有用处但却参与了类的行为如下所示class UnforgivingElephant(object):definit(self, name):self.name nameself._people_to_stomp_on []def get_slapped_by(self, name):self._people_to_stomp_on.append(name)print(‘Ouch!’)def revenge(self):print(‘10 years later…’)for person in self.people_to_stomp_on:print(‘%s stomps on %s’ % (self.name, person))下面是在交互式会话中的运行结果joe UnforgivingElephant(‘Joe’)joe.getslappedby(‘Tarek’)Ouch!joe.getslapped_by(‘Bill’)Ouch!joe.revenge()10 years later…Joe stomps on TarekJoe stomps on Bill