Oh Steven, you've really outdone yourself this time with the
theatrics. I hope you scored some "cool points" with your
minions. Heck, you almost had me convinced until i slapped
myself and realized your whole argument is just pure BS. For
the sake of the lemmings, i must dissect your BS and expose
it's methane emitting innards for all to smell.
Many
languages provide a function, method, or statement by which users can
write easily to stdout, and Python is no exception with it's own "print"
function. However, whilst writing to stdout via "print" is slightly less
verbose than calling the "write" method of "sys.stdout", we don't really
gain much from this function except a few keystrokes... is this ALL
print should be? A mere syntactical sugar?
Perhaps you should read the docs before asking rhetorical questions,
because the actual answer is, No, print is not mere syntactical sugar
saving a few keystrokes.
[...]
And perhaps you should read a dictionary and obtain (at
minimum) a primary school level education in English before
making such foolish statements, because, OBVIOUSLY you don't
know the definition of "syntactical sugar"... shall i
educate you?
############################################################
# Wikipedia: "syntactic sugar" #
############################################################
# In computer science, syntactic sugar is syntax within a #
# programming language that is designed to make things #
# easier to read or to express. It makes the language #
# "sweeter" for human use: things can be expressed more #
# clearly, more concisely, or in an alternative style that #
# some may prefer[...] #
############################################################
The print function is the very definition of a "syntactic sugar".
For example:
print("some sting")
is much more readable than:
sys.stdout.write("some string"+"\n")
or:
sys.stderr.write("some string"+"\n")
or:
streamFoo.write("blah")
But wait, there's more!
############################################################
# Wikipedia: "syntactic sugar" (continued) #
############################################################
# [...]Specifically, a construct in a language is called #
# syntactic sugar if it can be removed from the language #
# without any effect on what the language can do: #
# functionality and expressive power will remain the same. #
############################################################
Again, the removal of a print function (or print statement)
will not prevent users from calling the write method on
sys.stdout or sys.stderr (or ANY "stream object" for that matter!)
The only mistake i made was to specify stdout.write
specifically instead of generally referring to the print
function as a sugar for "stream.write()".
I've found that many subtle bugs are caused by not limiting the inputs
to sane values (or types). And with Python's duct typing [...]
and implicit
casting to Boolean, you end up with all sorts of misleading things
happening! Maybe you're testing for truth values and get a string
instead; which screws everything up!!!
Only if you're a lousy programmer who doesn't understand Python's truth
model.
I understand the Python truth model quite well, i just don't
happen to like it. Implicit conversion to Boolean breaks the
law of "least astonishment".
Many times you'll get a result (or an input) that you expect
to be a Boolean, but instead is a string. A good example of
poor coding is "dialog box return values". Take your
standard yes/no/cancel dialog, i would expect it to return
True|False|None respectively, HOWEVER, some *idiot* decided
to return the strings 'yes'|'no'|'cancel'.
If you tried to "bool test" a string (In a properly designed
language that does NOT support implicit Boolean conversion)
you would get an error if you tried this:
py> string = " "
py> if string:
... do_something()
ERROR: Cannot convert string to Boolean!
However, with Python's implicit conversion to Boolean, the
same conditional will ALWAYS be True: because any string
that is not the null string is True (as far as Python is
concerned). This is an example of Python devs breaking TWO
Zens at once:
"explicit is better than implicit"
"errors should NEVER pass silently"
And even though Python does not raise an error, it should!
No no no, that's not how you do it. It should be:
if DEBUG == True == True:
Wait, no, I got that wrong. It should be:
if DEBUG == True == True == True:
Hang on, I've nearly got it!
if DEBUG == True == True == True == True:
Or, you could program like a professional, and say:
if DEBUG:
Obviously you don't appreciate the value of "explicit enough".
if VALUE:
is not explicit enough, however
if bool(VALUE)
or at least:
if VALUE == True
is "explicit enough". Whereas:
if VALUE == True == True
is just superflous. But that's just one example. What about this:
if lst:
I don't like that because it's too implict. What exactly
about the list are we wanting to test? Do we want to know if
we have list object or a None object, OR, do we want to know
if we have a list object AND the list has members? I prefer
to be explicit at the cost of a few keystrokes:
if len(lst) > 0:
Covers the "has members" test and:
if lst is not None
covers the "existence" test.
I know Python allows me to be implicit here, however, i am
choosing to be explicit for the sake of anyone who will read
my code in the future but also for myself, because being
explicit when testing for truth can catch subtle bugs.
Consider the following:
What if the symbol `value` is expected to be a list,
however, somehow it accidentally got reassigned to another
type. If i choose to be implicit and use: "if value", the
code could silently work for a type i did not intend,
therefore the program could go on for quite some time before
failing suddenly on attribute error, or whatever.
However, if i choose to be explicit and use:
"if len(VALUE) > 0:
then the code will fail when it should: at the comparison
line. Because any object that does not provide a __len__
method would cause Python to raise NameError.
By being "explicit enough" i will inject readability and
safety into my code base. (that's twice you've been schooled
in one reply BTW!)
By the way, why is DEBUG a constant? Doesn't that defeat the purpose?
Hmm, I agree!. You're actually correct here. We should not
be reassigning constants should we? (<--rhetorical) In
correcting me you've exposed yet another design flaw with
Python. Sadly Python DOES allow reassignment of CONSTANTS.
And of course you have profiled your application, and determined that the
bottleneck in performance is the calls to debugprint, because otherwise
you are wasting your time and ours with premature optimization.
Life is hard. Sometimes you have to choose between performance and
debugging.
Only if your language does not provide a proper debugprint
function or provide the tools to create a proper debug print
function. I detest true global variables, however, there are
some legitimate reasons for true globals in every language.
This "debugprint" problem is one of those reasons.
If you really care about this premature optimization, you can do this:
if __debug__:
print("whatever")
That's hideous! Two lines of code to make a single debug
message, are you joking? I realize Python will allow me to
place the entire statement on one line, however i refuse to
do that also. I am very strict about my block structure and
styles, and even the consistent inconsistency of the great
GvR will not sway me away from adherence to my consistent
readable style.
You then globally disable these print calls by running Python with the -O
switch.
Python does not work like that. Perhaps you should learn how to program
in Python before telling us how it should be improved?
And perhaps you should listen to diverse ideas and be open
to change instead of clinging to your guns and religion.
So, it will be utterly useless then, since __LOCALDEBUG__ has no effect,
and __GLOBALDEBUG__ overrides it. Great.
Of course global debug overrides local debug, what's the
purpose of global switching if it cannot override local
switching? "__GLOBALDEBUG__ = False" would disables ALL
debug messages EVERYWHERE. Yes, you are correct on this
issue. It would be the same as setting a command line switch.
However, you misunderstand __LOCALDEBUG__. When global
debugging is "on" "__LOCALDEBUG__ = False" will disable
debug messages ONLY in the module for which it was declared.