This is a question that keeps recurring in all of my programming, python and otherwise. I really like to keep my code under 80 chars if at all possible/not horribly ugly. In a l
I second Michael Kent's answer (and I upvoted it).
But also, you should read "PEP 8" and absorb its lessons.
http://www.python.org/dev/peps/pep-0008/
But Python, with its namespaces, powerful features, and object-oriented classes, should let you use conveniently short names for things.
In C, you need to use long identifiers in many cases because names need to be unique within a given scope. Thus:
char *StringFromInt(int x);
char *StringFromFloat(float x);
char *StringFromUnsigned(unsigned int x);
char *str_temp = strdup(StringFromUnsigned(foo_flags));
In Python, all of these would be the builtin str()
:
temp = str(foo_flags)
In C++ you have classes and name spaces, so you should be able to use object-oriented features as in Python, but in C you need globally unique names, so you often have to do stuff like this:
typedef struct s_foo
{
// struct members go here
} FOO;
FooAdd();
FooSubtract();
StringFromFoo();
In Python, you should either add member functions, or overload operators, as appropriate:
class Foo(object):
def __init__(self):
# member variables initialized here
def add(self, x):
# add x to a Foo
def subtract(self, x):
# subtract x from a Foo
def __str___(self):
# return a string that represents a foo
f = Foo()
f.add(x)
f.sub(y)
# the following two both use __str__()
temp = str(f)
print(f)
You may also favor really long variable names for self-documenting purposes. I prefer terseness:
import math
class Circle(object):
"""\
Circle: a class representing a circle in a plane.
Includes the following member functions:
area() -- return the area of the circle"""
def __init__(self, center=Point([0, 0]), radius=0.0):
"""\
Circle(center, radius)
center must be an instance of class Point() or convertible to Point()
radius must be an int or float and must not be negative"""
if radius < 0:
raise ValueError("radius must be >= 0")
self.center = Point(center)
self.radius = float(radius)
def area(self):
"returns area as a float."
return math.pi * self.radius ** 2
c = Circle([23, 45], 0.5)
print(c.area())
class CircleGraphicsObject(object):
def __init__(self, CenterOfTheCircle, RadiusOfTheCircle):
# init code goes here
def AreaOfTheCircle(self):
return math.pi * self.RadiusOfTheCircle ** 2
CircleInstance = CircleGraphicsObject(PointObject([23, 45]), 0.5)
print(CircleInstance.AreaOfTheCircle())
I strongly prefer the first, terse style to the second. As per PEP 8, I like all-lower-case variable names (such as c
for the Circle
instance). In Python, it is also generally recommended to use "Duck Typing" like I did in the terse class: if you want the radius to be a float, then coerce it to a float
in __init__()
rather than checking its type. Likewise, rather than checking to see if you were passed a Point
instance, just coerce whatever you get to a Point
. You are letting Point.__init__()
raise an exception if the argument makes no sense as a Point
; there is no need for an extra check in Circle.__init__()
. Also, your Point.__init__()
function can explicitly check to see if you passed it an instance of Point
and return the instance unchanged, if it is really expensive to init a Point
. (In this example, a Point
is really just a pair of values, so it's probably fast enough to just re-create the point and you don't need the check.)
You might notice the odd way I did the multi-line triple-quoted string. Because of the indenting rules in Python, I needed to indent the triple-quoted string, but I don't want to indent the lines of the string because the indent would be part of the string. Really I want all of the multiple lines to be at the left margin, so I can clearly see how long those lines are getting (and make sure they are all 79 chars or shorter). So I use the backslash escape to allow the first line of the multi-line string to be at the left margin with the other lines, without inserting a newline at the beginning of the multi-line string.
Anyway, the terser style means your variable names and such are easier to type, and it is easier to fit your lines in the 79-column limit recommended by PEP 8.
It wouldn't even be completely horrible to use internal member names that are one letter long, in a class as simple as this. With only two members, you could pretty well use .c
for the center member and .r
for the radius. But that doesn't scale up well, and .center
and .radius
are still easy to type and easy to remember.
It's also a very good idea to put informative docstrings. You can use somewhat terse names, but have longer explanations in the docstring.
class Foo(object):
# init goes here
def area(self):
"returns area as a float."
return self.area
class VerboseFoo(object):
# init goes here
def AreaAsFloat(self):
return self.FloatAreaValue
Namespaces are great. Notice how clear it is when we use math.pi
; you know it is the math constant, and you could have some local variable pi
(for "Program Index" perhaps) and it does not collide with the math constant.