Rob*_*ugg 8 python pep8 naming-conventions
首先,当我询问单位时,我的意思是测量单位,如英寸,英尺,像素,单元格.我不是指像int和float这样的数据类型.
维基百科将此称为逻辑数据类型而非物理数据类型.
我想知道命名变量的最佳方法.
这里有一些代码可以解决我的问题:
board_length=8 #in inches
board_length=8*12 #Convert from feet to inches
Run Code Online (Sandbox Code Playgroud)
请注意,这些都是整数(或浮点数,我不在乎),但我已经更改了单位.我还保持变量名称相同.我可以建立一个公约,这就是这个问题的目的.没有指导,我可能会这样做:
board_length=8
board_length_inches=8*12
Run Code Online (Sandbox Code Playgroud)
我认为这是一种特殊的做事方式.或者,我可以建立一个约定:
Fboard_length=8
Iboard_length=8*12
Run Code Online (Sandbox Code Playgroud)
或者我同样不喜欢的其他变体.我如何以描述性方式命名变量,但尽可能接近PEP-08?
为了尽可能清楚,变量可能有不同的数据类型,但单位将是相同的(英寸将具有相同的命名,无论它是否存储为整数或浮点数)
虽然您可以提出一个命名约定,但通过构建一个表示"距离"的对象可以更好地服务,该对象具有以不同单位读/写的属性.例如:
class Distance(object):
def __init__(self):
self._inches = 0
@property
def inches(self):
return self._inches
@inches.setter
def inches(self, value):
self._inches = value
@property
def feet(self):
return self._inches/12
@feet.setter
def feet(self, value):
self._inches = value * 12
Run Code Online (Sandbox Code Playgroud)
您甚至可以使它更通用,以便您可以轻松扩展新的转换.(注:编辑此内容根据评论进行记忆)
from collections import defaultdict
class Distance(object):
_conversion_map = defaultdict(lambda: {'to' : None, 'from' : None})
def __init__(self, **kwargs):
self._memo = {}
if kwargs:
unit, value = kwargs.iteritems().next()
if unit == 'inches':
self.inches = value
else:
setattr(self, unit, value)
else:
self.inches = 0
def __getattr__(self, name):
if name in self._conversion_map:
try:
return self._memo[name]
except KeyError:
converter = self._conversion_map[name]['to']
if converter is None:
raise AttributeError
converted = converter(self.inches)
self._memo[name] = converted
return converted
else:
raise AttributeError
def __setattr__(self, name, value):
if name == '_memo':
super(Distance, self).__setattr__(name, value)
else:
# Clear memoized values if setting the value of the object
self._memo = {}
if name == 'inches':
super(Distance, self).__setattr__(name, value)
if name in self._conversion_map:
converter = self._conversion_map[name]['from']
if converter is None:
raise AttributeError
self._memo[name] = value
self.inches = converter(value)
else:
raise AttributeError
@classmethod
def converter(cls, func):
direction, unit = func.__name__.split('_', 1)
cls._conversion_map[unit][direction] = func
return func
@Distance.converter
def to_feet(value):
return value / 12
@Distance.converter
def from_feet(value):
return value * 12
board_1_length = Distance(feet=2)
board_2_length = Distance(inches=14)
board_1_length.inches # 24
board_2_length.feet # 1 (integer division)
Run Code Online (Sandbox Code Playgroud)
我会更进一步,使用单独的对象类型来提供类型安全,而不是简单地依赖命名约定。否则,您可以将代表英寸的变量传递到需要英里的方法中。
我认为依赖命名约定将难以长期维护,而使用类型将为您提供更大的灵活性和安全性(例如,提供内置于对象类型中的转换等)