
Python, as Reviewed by a C++ Programmer - ingve
http://www.sgh1.net/b4/python-first-impressions
======
pzh
For me the biggest downside of dynamically typed lanaguages like Python and
Javascript is that a small error in passing a function's parameters can
propagate very far in a complex system. E.g. if you mistakenly interchange two
consecutive function parameters, you could spend several hours debugging the
effect several modules down. This is an error that a C++ compiler would catch
right away.

~~~
makecheck
C++ is not always able to detect common parameter errors, especially for
things like implicit conversions of numbers. Arguably Python’s option of
keyword arguments make certain classes of parameter errors go away, too.

Several years ago I remember someone who (perhaps unwisely) wrote a C++
function with many floating-point values as parameters and a single default
"bool". At some point the function was extended to have another float. The
compiler did not catch calling code that failed to add an extra float; it
simply allowed the formerly-flag arguments to be assigned to the new float
argument instead. In fact, implicit conversion of parameters is such a common
C++ problem that I occasionally define wrapping types for the sole purpose of
being parameter types: then the compiler _has_ to trip over them when they are
used incorrectly and callers _have_ to do some kind of explicit action to
indicate what their values really are.

~~~
mathw
Those implicit conversion rules (largely inherited from C) are one of the bits
of C++ that bit me the most when I was a primary C++ dev.

------
inlineint
The article doesn't mention type annotations described in PEP484 and added to
CPython since Python 3.5.

It is possible to add annotations to your code like

    
    
        class Foo:
            x: int
            # ...
    

and then run type checks using `mypy`, so that for the annotated code
probability of the "passes the checks => won't crash the runtime" case is much
larger.

~~~
striking
Sure, but most python code isn't annotated, right?

So this might be helpful for code you wrote, but not anywhere it interfaces
with other peoples' code (which, in my opinion, is probably the most important
place to check for type errors).

~~~
Rapzid
Plus, many packages dynamically add members, stomp named parameters by
wrapping stuff with __kwargs, etc.

~~~
humanfromearth
So monkey patching is bad you're saying? I agree that it's possible what
you're saying about kwargs, but after about 6 years of python I've never
encountered that in any of the code that I've worked on.

------
tyingq
Interesting, but it's mostly a few observations about interpreted vs compiled
and static vs dynamic typing. And a bit about having a rich collection of 3rd
party libraries.

The article wouldn't have been much different had it been C++ vs
Ruby/Perl/etc.

------
JustSomeNobody
What is a "C++ programmer?"

On any given day, I poop you not, I'm writing either c#, java, c++ or any
number of scrpting languages (perl, bash, python, JavaScript).

Do people seriously only use a single language these days!?

~~~
Twirrim
Why do you jump between multiple languages all the time?

~~~
v1n337
Not, OP, but I've worked for an ad-agency in a software-dev role.

Their primary code base is written in Java, monitoring scripts in Python/Ruby,
and tracking pixel code in JavaScript, so I would have days in which I coded
in all 3, albeit for separate use-cases.

~~~
coldtea
The ad agency couldn't afford different developers for the various systems?

------
Twirrim
For what it's worth, python has been making inroads in the HPC world as well.
In that context it seems like python is being used as the glue to tie highly
optimized, custom written, C/C++ libraries together.
[http://lorenabarba.com/publications/](http://lorenabarba.com/publications/)
[http://dl.acm.org/citation.cfm?id=3019084&CFID=927535872&CFT...](http://dl.acm.org/citation.cfm?id=3019084&CFID=927535872&CFTOKEN=12671239)
[http://dl.acm.org/citation.cfm?id=2830170&CFID=927535872&CFT...](http://dl.acm.org/citation.cfm?id=2830170&CFID=927535872&CFTOKEN=12671239)

It's happening enough that there has been a series of popular conferences for
it, PyHPC
[http://www.dlr.de/sc/desktopdefault.aspx/tabid-11992/21071_r...](http://www.dlr.de/sc/desktopdefault.aspx/tabid-11992/21071_read-48990/)

------
Animats
This reads like it was written 10-15 years ago. But apparently it's new.

~~~
pastaguy1
That's the same feeling I had when I was writing the article!

------
bbody
Looks like the website's bandwidth limit hit its limit. Google Cache link for
those who still want to read it
[http://webcache.googleusercontent.com/search?q=cache:Z6cJ7kw...](http://webcache.googleusercontent.com/search?q=cache:Z6cJ7kwRhQkJ:www.sgh1.net/b4/python-
first-impressions+&cd=2&hl=en&ct=clnk)

------
partycoder
There are package managers for C++, such as Conan. Some IDEs like CLion have
certain degree of integration with it.

[https://www.conan.io](https://www.conan.io)

Then, some systems cannot afford to have garbage collection, because it
usually runs in an unpredictable amount of time. Such systems are for example
real-time systems. In those cases a language like C++ is a good fit.

------
dinnouti
One thing that is a bless and a curse is the use of indentation for code
blocks.

[http://www.secnetix.de/olli/Python/block_indentation.hawk](http://www.secnetix.de/olli/Python/block_indentation.hawk)

~~~
royprins
I read that, and it absolutely does not try to make the point that indentation
is a curse. Maybe it is to some (not to me!), but you would need to cite
something else. This is just an explanation of how it works.

------
sssergey
Good post but I think he'd have a bit more appreciation for Python if he tried
writing in a functional style as opposed to object oriented.

------
golergka
It's incredibly close to my feelings after moving from C# to Javascript.
Especially the heavily leaning on compiler bit.

------
hsivonen
Rust is better than C++ at “if it compiles, it works” and has a great package
manager, so as far as the topics highlighted here go, Rust seems to be the
best of both worlds.

~~~
dom0
One thing where Rust is rather lacking is the missionarism of some people in
the community.

~~~
dsacco
The Rust Evangelism Strike Force is a huge turnoff to the language. It's
gotten to the point where we can't have reasoned discussions about C++ or C,
let alone about their merits, without a newly enlightened user coming in and
trying to direct the conversation to Rust.

It's really _okay_ to have a future where C++ and Rust are both popular,
widely used languages. I'm happy to acknowledge the merits of Rust as a
language and even talk about them without inserting it into every conversation
about low-level computing.

I'm sure the language designers and core developers don't actively endorse
this behavior, but somewhere along the way it became a core part of the
culture. This world domination shit has to stop.

~~~
soulbadguy
> "The Rust Evangelism Strike Force"

Instant classic

~~~
rcarmo
I think it was coined by [http://n-gate.com](http://n-gate.com) (mentioned in
HN a few times last month), but I can't be sure.

What I do know is that a) it's hilariously on point b) Google search now
autocompletes on it for me.

------
markbnj
Interesting perspective on some of python's features, but I hate to see this
"python is neither call by value nor call by reference" silliness perpetuated
with a link to the original silly blog post. I'm surprised a C++ programmer
was caught by that obviously incorrect assertion.

~~~
srean
Claims that Python/C#/Java etc., are call by value where the 'value' is the
value of the pointer does not help. It only muddies things. There really ought
to be different name for such call semantics and there is. Its called call by
object. In C++ lingo call by const pointer comes closest: one cannot change
what the pointer points to. However the pointed object may not be a const

~~~
markbnj
No, no, no there is no "call by object." It is precisely this mistaken idea
which muddies the waters, as you put it. Virtually all modern processors are
stack-based architectures. All arguments to functions are passed on the stack
or in registers. The only thing that can be placed onto the stack or into a
register are numbers. Those numbers can represent either an actual value or an
address in memory. The former is call by value, the latter is call by
reference. All high level languages that allow calling functions or methods
with arguments have to ultimately use this facility to pass those arguments.
Python is most definitely call by reference.

~~~
Al-Khwarizmi
In Java, this code will print the string representation of Lassie:

    
    
      Dog toby = new Dog("Toby");
      
      public static void replaceDogWithToby ( Dog d )
      {
        d = toby;
      }
      
      public static void main ( String[] args )
      {
        Dog d = new Dog("Lassie");
        replaceDogWithToby(d);
        System.out.println(d);
      }
    

In Pascal, this will print Toby:

    
    
      var
        toby:tDog;
      
      procedure replaceDogWithToby ( var d:tDog );
      begin
        d := toby;
      end;
    
      var
        lassie:tDog;
      begin
        {code to initialize toby and lassie here}
        d := lassie;
        replaceDogWithToby(d);
        writeln(getDogName(d));
      end.
    

The first is call by object (or call by sharing, in my book). The second is
call by reference. The behavior is totally different.

~~~
markbnj
I haven't done java in a long time so I won't try to debate the specific
language level semantics with you (the same is true of pascal though it has
been even longer), however assuming that your examples run and behave as you
describe then what is going on in the java example is that 'Dog d' is passed
as a reference to a reference, and then the value pointed to by the argument,
i.e. the address of "toby," is replaced with the address of "lassie."

~~~
E6300
You got it backwards. The Java snippet will print "Lassie". In Java, object
names are references to objects, and passing them to functions copies the
references, so of course modifying the formal parameter (d from
replaceDogWithToby()) doesn't modify the actual parameter (d from main()).

