Usually declaring variables on assignment is considered a best practice in VBScript or JavaScript , for example, although it is allowed.
Why does Python force you to create the variable only when you use it? Since Python is case sensitive can't it cause bugs because you misspelled a variable's name?
How would you avoid such a situation?
Numbers. Python supports three types of numbers - integer, floating point numbers, and complex. We can declare a variable with any length, there is no restriction declares any length of the variable.
Python has no command for declaring a variable. A variable is created the moment you first assign a value to it.
To declare (create) a variable, you will specify the type, leave at least one space, then the name for the variable and end the line with a semicolon ( ; ). Java uses the keyword int for integer, double for a floating point number (a double precision number), and boolean for a Boolean value (true or false).
If you do any serious development you'll use a (integrated) development environment. Pylint will be part of it and tell you all your misspellings. No need to make such a feature part of the langauge.
It's a silly artifact of Python's inspiration by "teaching languages", and it serves to make the language more accessible by removing the stumbling block of "declaration" entirely. For whatever reason (probably represented as "simplicity"), Python never gained an optional stricture like VB's "Option Explicit" to introduce mandatory declarations. Yes, it can be a source of bugs, but as the other answers here demonstrate, good coders can develop habits that allow them to compensate for pretty much any shortcoming in the language -- and as shortcomings go, this is a pretty minor one.
If you want a class with "locked-down" instance attributes, it's not hard to make one, e.g.:
class LockedDown(object):
__locked = False
def __setattr__(self, name, value):
if self.__locked:
if name[:2] != '__' and name not in self.__dict__:
raise ValueError("Can't set attribute %r" % name)
object.__setattr__(self, name, value)
def _dolock(self):
self.__locked = True
class Example(LockedDown):
def __init__(self):
self.mistakes = 0
self._dolock()
def onemore(self):
self.mistakes += 1
print self.mistakes
def reset(self):
self.mitsakes = 0
x = Example()
for i in range(3): x.onemore()
x.reset()
As you'll see, the calls to x.onemore
work just fine, but reset
raises an exception because of the mis-spelling of the attribute as mitsakes
. The rules of engagement here are that __init__
must set all attributes to initial values, then call self._dolock()
to forbid any further addition of attributes. I'm exempting "super-private" attributes (ones starting with __
), which stylistically should be used very rarely, for totally specific roles, and with extremely limited scope (making it trivial to spot typos in the super-careful inspection that's needed anyway to confirm the need for super-privacy), but that's a stylistic choice, easy to reverse; similarly for the choice to make the locked-down state "irreversible" (by "normal" means -- i.e. requiring very explicit workaround to bypass).
This doesn't apply to other kinds of names, such as function-local ones; again, no big deal because each function should be very small, and is a totally self-contained scope, trivially easy to inspect (if you write 100-lines functions, you have other, serious problems;-).
Is this worth the bother? No, because semi-decent unit tests should obviously catch all such typos with the greatest of ease, as a natural side effect of thoroughly exercising the class's functionality. In other words, it's not as if you need to have more unit tests just to catch the typos: the unit tests you need anyway to catch trivial semantic errors (off-by-one, +1 where -1 is meant, etc., etc.) will already catch all typos, too.
Robert Martin and Bruce Eckel both articulated this point 7 years ago in separate and independent articles -- Eckel's blog is temporarily down right now, but Martin's right here, and when Eckel's site revives the article should be here. The thesis is controversial (Jeff Attwood and his commenters debate it here, for example), but it's interesting to note that Martin and Eckel are both well-known experts of static languages such as C++ and Java (albeit with love affairs, respectively, with Ruby and Python), and they're far from the only ones to have discovered the importance of unit-tests... and how a good unit-tests suite, as a side effect, makes a static language's rigidity redundant.
By the way, one way to check your test suites is "error injection": systematically go over your codebase introducing one mis-spelling -- run the tests to make sure they do fail, if they don't add one that does fail, correct the spelling mistake, repeat. Can be fairly well automated (not the "add a test" part, but the finding of potential errors that aren't covered by the suite), as can some other forms of error injections (change every integer constant, one by one, to one more, and to one less; change each <
to <=
etc; swap each if
and while
condition to its reverse; ...), while other forms of error-injection yet require a lot more human savvy. Unfortunately I don't know of publicly available suites of error injection frameworks (for any language) -- might make a cool open source project;-).
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