First, when I ask about units I mean units of measurement like inches, feet, pixels, cells. I am not referring to data types like int and float.
Wikipedia refers to this as logical data type rather than physical data type.
I'd like to know the best way to name variables.
Here is some code to walk through what I'm asking:
board_length=8 #in inches
board_length=8*12 #Convert from feet to inches
Notice that these are both integers (or floats, I don't care), yet I’ve changed units. I’ve also kept the variable name the same. I could establish a convention, and that’s the purpose of this question. Without guidance, I might do something like this:
board_length=8
board_length_inches=8*12
I would consider this an ad-hoc way of doing things. Or, I might establish a convention:
Fboard_length=8
Iboard_length=8*12
Or other variants that I equally dislike. How might I name variables in a descriptive way, yet stay as close to PEP-08 as possible?
Just to be as clear as I can, the variables may have different data types, yet the units would be the same (inches would have the same naming regardless of if it was stored as and integer or a float)
Python naming conventions for variable names are same as function names. There are some rules we need to follow while giving a name for a Python variable. Rule-1: You should start variable name with an alphabet or underscore (_) character. Rule-2: A variable name can only contain A-Z,a-z,0-9 and underscore (_).
Python does not support privacy directly. This naming convention is used as a weak internal use indicator. Should follow the above naming conventions. Should use a leading underscore (_) to distinguish between "public" and "private" variables. For more read the official python documentation.
There are certain rules we need to follow while naming a global variable. Rule-1: You should use all lowercase while deciding a name for a Object. Rule-2: If there are multiple words in your global variable name then they should be separated by an underscore (_). What is Snake_case naming style Python?
Not begin with the special characters like e.g. & (ampersand), $ (dollar) If the name contains multiple words, it should be separated by underscores (_) e.g. json_string Avoid one-character variables e.g. a, b class Student age = None ... Python does not support privacy directly. This naming convention is used as a weak internal use indicator.
While you could come up with a naming convention, you might be better served by building an object representing "distance" with properties to read/write in different units. For instance:
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
You could even make it more generic, so that you could easily extend with new conversions. (Note: Edited this to memoize based upon comments)
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)
I'd go further and have separate object types providing type safety rather than simply rely on naming conventions. Otherwise you could pass a variable representing inches into a method requiring miles.
I think that relying on naming conventions is going to be problematic to maintain long term and making use of types will give you much more flexibility and safety (e.g. providing conversions etc. built into the object types)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With