Yes, but also Lisp, awk, R, and Prolog. Or something; you can't be Mr. All-Java and then Mr. All-PHP and be in a position to adequately judge programing languages.
I would say that python isn't a perfect tool for tackling large problems on their own, but for largely different reasons.
You'll notice that Ruby implements objects in a very nontraditional OO way, seemingly similar to python on some levels. But typical OO restrictions create anti-patterns (excuse me, 'design' patterns), instead of direct access or on the fly coding.
The consenting adult argument is compelling for nontraditional semi-encapsulated object implementations, and simply requires a different type of programmer or team to do successfully.
I've been spoon-fed OO since 13 (C++/Java) but am now seeing the good in taking away the boilerplate. Just as OO replaced procedural and (Temporarily) functional paradigms, we will see hybrid languages replacing traditional OO as time comes along (Ruby seems to be a mix of OO, functional, and imperative).
Ruby is very similar to "traditional" OO languages such as Smalltalk. C++ and Java are not OO -- they are simply procedural, with a bit of pretty syntax and some renamed concepts ("procedure" => MARKETING DEPARTMENT => "method").
I will admit I haven't had experience with Smalltalk, and by "traditional" as you correctly pointed out, I am probably referring merely to my background.
In any case your insight makes me ask - is mainstream OO just a poor outfit for procedural programmers trying to stay relevant?
I can say that C++ was used as a gimmick at least once instead of C on a professional project and everyone hated the code.
> In any case your insight makes me ask - is mainstream OO just a poor outfit for procedural programmers trying to stay relevant?
Essentially, yes. C++ was invented because large companies wanted to add the "object-oriented" buzzword to their products. Needless to say, the language is a disaster.
Java was an attempt to fix some of the problems with C++ -- primarily, the complete incompatibility of manual memory management and exceptions. Java was a success because any C or C++ developer can sit down with a library reference and begin working, and the resulting programs usually worked better than if the same developer had used C++.
Next came C#, which is an incremental improvement over Java in the same way Java is an improvement over C++. It adds a few useful features from more advanced languages (closures, true generics, properties) and restores some C++ features removed from Java (unsigned integers, operator overloading, preprocessing). Again, its most important feature is that it's not very differing -- a C++ or Java developer can be up and running with C# in a matter of hours.
I've had all these same complaints about Python, and this summarizes them quite eloquently.
Python sorta kinds tries to be half way include objects and functional programming, but not really. I especially agree that having to type "self." for every single member instance reference anywhere in your program is just as annoying as much of the boiler plate Java requires. I tried using objects in Python for a while, but found that it just made things more verbose than writing procedurally.
"However, these libraries are inherently static. This means that if the library doesn't do what you want it to, you are screwed. There is no diagnosing or fixing errors in the library. If they happen, pack up and try a different language."
Ermmm.... I think someone misinformed him. In Python, not only can you use the standard library, but you can also use third party libraries as well. And Python's got a ton of those.
Personally, I think the author can make a case that he doesn't like python, but I don't see anything here that makes Python bad. Different strokes for different folks.
I never got the argument about one-line lambdas... Every time I needed a lambda, it was either one line, or deserved a new function (even if nested). Are there some serious cases where it's not enough?
And it's not even correct. Python's lambda can contain an arbitrary number of lines, as long as they're a single expression. Considering that lambda is "borrowed" from functional languages, which are inherently single-expression, I've never seen what anybody's problem is with them.
The problem is that in functional languages you have a lot of tools build on higher order functions, so you can easily leverage functions as expressions. On the other hand, its standard practice to use statement forms (if, while, for, try etc) to describe a lot of the processing.
As statements are not allowed in lambdas this means you either are stuck writing a local named function and writing the code in idiomatic python or writing some helper functions to allow you to write code in a functional but non-idiomatic python style.
It comes down to a matter of style.
My personal theory is that once a python programmer discovers the magic of itertools they are about 3 months from looking for a new language that supports the functional style more naturally.
Multi-line, multi-statement closures are tremendously useful in Smalltalk. They're the "secret sauce" that makes Don't Repeat Yourself easy to pull off. You can use them to implement your own control structures, your own notion of transactions, etc. And all (or most) of the above esoteric hackery looks like ordinary Smalltalk.
People are down on I statement Lambdas because they don't do all of the above so well.
The example given (I know it's synthetic, but still) can be written easily as a lambda:
button.onClick(lambda bar, fram: baz(foo(bar, fram)))
The problem with embedding procedure definitions within parameter lists is indentation. Languages such as JavaScript or Ruby use explicit syntax for indentation, which allows a degree of flexibility in how procedure literals are defined. Python uses only whitespace, so trying to extend the grammar to support arbitrary procedure literals would be very difficult (according to Guido).
for the same reasons of style and clarity, I prefer my imaginary syntax to the lambda you've defined. And if you want to make it impossible, just imagine it's "print baz(z)".
Anyway, I'm familiar with why Guido doesn't want them, and I totally respect it, and I write 99% of my personal code in python, so I clearly don't think it's a huge deal. It's just something I wish python did have, is all.
I see the problem when using third-party libraries, but if I was designing my own... Objects are pretty cheap in python:
class Somebutton(Button):
def onClick(self):
.....
def onSomethingElse(self):
.....
only one line of overhead (class line). And I'm pretty sure you can hack __dict__ in init, or use metaclasses so that the events are chained automatically, even without calling `Button.onClick(self)`. You can construct / add the object to it's container the same way (Somebutton(), instead of Button())
"So I get that it's never necessary, but I find it sometimes limiting as an author who cares strongly about how his code is organized."
Nothing other than an if statement, a goto, and some basic arithmetic is needed in a programming language. It's all syntactic sugar. I agree that such a construct would be useful. However, it's more about if it's worth complicating the language over. I don't necessarily know how complex that would make things, but I can definitely see that a case can be made that it would be more trouble than it's worth considering the way indentation is handled.
I only ever use short-lambdas in map functions (common lisp), or long-lambdas (for the :callbacks) again in lispworks (a common-lisp implementation) CAPI (GUI from the company that made LispWorks).
Once you have good syntax established for using lamdba-s in any form - they would be used. First users would be as I've put above - callbacks of sort (GUI, IO, etc.)
I really like the "Classes in Python are more like dictionary objects with functions attached than classes." part though. It's exactly what I expect from objects. There aren't that many situations when we need anything more.
Plus it reminds me of coding javascript, which I have only recently gained a great appreciation for. I love how everything is an Object (even functions), and Objects are just dictionaries. It's awesome.
I think his point is a bit deeper than "I don't like it". His point relates to the distinction Alan Kay makes [1] between programming languages which are either an "agglutination of features" or a "crystallization of style".
In terms of features, Python is definitely strongly of the former variety: it has objects, but not in "opinionated" sense that Smalltalk or even Java do. It has lambdas, but limits them to one line. It has closures, but until py3, they clashed with the implicit declaration syntax. There isn't "one obvious way of doing a lot of things" more complicated than iteration.
dustin's py-github [2] is an especially poignant example which comes to mind: I would never have used classes for something like that, and Python doesn't give a clear reason to use them or not.
> It has closures, but until py3, they clashed with the implicit declaration syntax.
Could you elaborate on what you mean, here? The only issue I know of with Python 2's closures is that there's no scoping keyword for non-local, non-global variables. But that only matters if you're trying to re-define variables in a parent procedure's scope, which is probably not a good idea.
It's a great idea if you want to make small callable objects with limited (hidden) state, in a way that's easy to translate between any languages which support closures. For example, in JS:
function gencycle() {
var args = Array.prototype.slice.apply(arguments),
i = 0;
return function cycle() {
i = (i+1) % args.length;
return args[i];
}
}
I can then use gencycle("red", "green", "blue") when I want a function which gives me a rotation of colors.
The preferred way to do that in Python is as a co-routine (AKA generator). Besides being easier to read and reason about, generators implement common protocols, such as the iteration protocol. This means you can use generators in for-loops, as a parameter to list(), or anywhere else that accepts an iterator.
Here's an example of cycle() as a co-routine:
def cycle(*args):
i = 0
while True:
i = (i + 1) % len (args)
yield args[i]
for arg in cycle("red", "green", "blue"):
print (arg)
Alternatively, if you really want to use a callable:
I think his point is a bit deeper than "I don't like it".
How so? Everything in this article -- and nearly any point one could make about a programming language -- comes down to a matter of taste.
Take your example -- Python "has objects, but not in an 'opinionated' sense." What you see as a lack of purity, I see as just the right amount of pragmatism. To me, "un-opinionated" classes is a positive point, not a negative one. Where Zidek sees "inherently static" standard libraries, I see inherently stable ones. Where he sees a distressing lack of encapsulation I see a refreshing relaxing of constraints.
I'd go on, but I think you get the point.
You know what's awesome, though? If you don't like Python you don't have to use it!
But you know what isn't awesome? When you complain about this free thing that nobody's forcing you to use. You're just shitting all over someone else's hard work... for what? Page views?
Hacker News -- hell, the whole Internet -- would be a better place if people just shut the hell up about whatever's got their undies in a twist this time.
"I think his point is a bit deeper than "I don't like it". His point relates to the distinction Alan Kay makes [1] between programming languages which are either an "agglutination of features" or a "crystallization of style"."
Sorry, but this is flat out wrong. I mean, Python's syntax is pretty consistent over all (aside from a few quirks). Even still, Kay's archetypical example of a "style language" (Lisp) has definitely evolved more over the years than Python has.
The point isn't that the language has to be perfect. It's just that it has to have a "feel" to it. Python definitely has its own flavor (I mean idiomatic code is called "Pythonic" after all). The other part of the Python philosophy is "practicality beats purity". Therefore, there are times when the Python developers decided to just implement something practical and simple over something that's ideologically consistent.
Therefore, there are times when the Python developers decided to just implement something practical and simple over something that's ideologically consistent.
Which cannot be stressed enough.
Python acknowledges that the programmer is a human more than any other language I have seen. That's why you can get stuff done and keep it maintainable so easily in python. It gives you just enough rope to be very flexible, but tries very hard to not extend it to the length that people normally use to hang themselves.
I am quite unimpressed by these arguments. This blog post is a joke filled with inaccuracies.
- Encapsulation. Encapsulation in every language such as Java and Python is by convention. There are always ways to break it. Even in C++. Somehow the blogger missed out on learning "__" notation.
- Batteries. Nearly all the Python libraries are pure Python files which you can edit or debug. You can even debug the C modules with a C debugger if you like since they are just dynamic/shared libraries. You can delete libraries that you never use from your installation.
- This. This is probably the only legitimate complaint, but it all boils down to syntactical sugar.
- Members. Another blatant lack of knowledge. It is possible to enforce static members with the "__slots__" metamember. You can override the default object behavior by implementing the "__getattribute__" and "__setattribute__" members to suit this blogger's preferences.
- Lambda. Another syntactical sugar complaint. Python functions are first class variables.
Conclusion: The blogger's failed attempt to bash Python reveals his own lack of knowledge about the language.
The article's a few sentences of useful text, wrapped in heaping mounds of "clever" storytelling. Here's the meat of it, with comments:
The first bits of Python all point to this: the purpose of python is to have a language like c or Perl but to make it easy to read, easy to use, and short. The short part almost overrode everything else. This was your objective, your mandate from heaven.
Python is readable and expressive, not short. If you want short, use Perl, J, or APL. Many aspects of Python's syntax and semantics are quite verbose, in the interest of making the resulting code easier to read.
There is no encapsulation. There are three tiers to OO. One of them is encapsulation. Having OO without encapsulation is [useless].
Python does have encapsulation. Attributes are named according to their exposure: non-public attributes are prefixed with "_", and internal with "__". There's even a (hack-ish) name mangler, which prevents clients from accidentally depending on internal attributes.
Note the word "accidental". In a language such as Python, there is no way to completely prevent clients from accessing internal state. Even C++ or Java allow sufficiently knowledgeable / desperate clients to poke around wherever they like. Python's philosophy is that since clients will access internal state anyway, it's best to have a sane, documented mechanism.
As the saying goes, "Batteries are included," but as the saying fails to tell you, try to change your batteries and you are completely screwed. [...] if the library doesn't do what you want it to, you are screwed. There is no diagnosing or fixing errors in the library. If they happen, pack up and try a different language.
This reads like he believes the standard library is the only library, which (considering he uses C++ and Java) is a truly bizarre belief. If he doesn't like the standard HTTP library, it's trivial to either distribute a modified version, or use somebody else's (eg, libcurl). Many large Python projects distribute variants of standard library modules to work around errors or missing features in legacy versions of Python.
And then you omitted the implied this. [...] [Python] doesn't really take care of anything for you. You have to have "this" as the first argument to every function in a class. Once in a function, you have to use "this" to access any variables or other functions.
The problem with an implicit "self", aside from it violating the Python Zen, is that it makes a number of cases nastily ambiguous. For example, consider the following method:
class Foo:
def something():
a = True
b = False
In this code, the only way to know the scope of 'a' and 'b' is to read the entire class definition. Using explicit scoping prevents ambiguity.
Another advantage, though much less, is that it discourages excessive numbers of attributes. Somebody coming from a Java background probably likes having a few hundred attributes floating around in various states as his objects run, but I hate having to deal with code that has so many "moving parts". Adding a "tax" of five characters per attribute access/modification makes code much easier to read and debug.
To add insult to injury, python has no explicit support for member definition. A class's members are created by setting them equal to something. There is no way to explicitly define them in the class definition. Anybody, anywhere, can add (or remove) members variables from a given object.
There are many ways to define members in a class definition. The most heavy-handed is the "__slots__" mechanism, but you can also use properties or simple "foo = None" statements depending on the level of control clients should be allowed.
If the author doubts that Python can restrict attribute modification, he should try assigning to a tuple's attributes.
> The problem with an implicit "self", aside from it violating the Python Zen, is that it makes a number of cases nastily ambiguous. For example, consider the following method:
However, the syntax for the explicit self is somewhat awkward. Instead of:
def f(self, a, b): ...
it could have been
def self.f(a, b): ...
[This isn't original to me - Guido has mentioned it when he gets tired of hearing about explicit self.]
With the second, the structure of the argument list in the definition looks like the structure of the argument list in the call and the "self" is where the instance comes from relative to the method name.
Placing 'self' in the parameter list allows external procedures to be monkey-patched into a class, without needing to wrap it up in a 'partial'. For example:
I have found it very useful when writing unit tests for a particular method. I don't have to instantiate the class for which the method is a member of; instead I can easily pass a mock object as self that only contains the properties the method is supposed to test.
Furthermore the claim that python doesn't support objects cleanly or easily is unfounded: 1) everything is an object in python (http://diveintopython.org/getting_to_know_python/everything_...), including classes. 2) properties of an object are accessed in just the same way as in Java (obj.property), I don't understand where the confusion lies.
I took "short" to mean small which python use to be but is growing too large. Too many new constructs are being added to the base language (ternary operators for instance).
Encapsulation is the wrong answer to some problems. When it's the right answer (large, disperse, avg or lower ability developers aka "enterprise") go use a language built for that environment such as Java.
Same with self.
[to OA] Not all languages should be applicable to all problems. Quit trying to change Python into your language and leave it as my language.
Just to add to:
"" This reads like he believes the standard library is the only library, which (considering he uses C++ and Java) is a truly bizarre belief. If he doesn't like the standard HTTP library, it's trivial to either distribute a modified version, or use somebody else's (eg, libcurl). Many large Python projects distribute variants of standard library modules to work around errors or missing features in legacy versions of Python."""
I regularly monkey-patch builtin standard libraries. Bug in httplib? Easy - I overwrite the built in version, or I do some other trick. It's just Python, get a class that needs a method or an attribute? Just add it.
That's the nice part of "nothing is truly private" in python - and a great argument against bondage and chains style of encapsulation/privacy. If you need to reach in and "fix" something, you can.
It all started with your lists. I think that was when I really fell in love. You see in a language like Java or php if you want to get the last element of the list you have to write something like $a[count($a) - 1]. But python was different: just write a[-1].
Don't take this as hostile. Rather as an observation of the shifted expectations of programmer subculture.
So a cryptic negative index counts as "elegant?" Wouldn't it be more straightforward just to ask a list for "last?"
Here's the equivalent Smalltalk:
list last
In Ruby:
list.1ast
Laypeople would have an immediate inkling of either. The negative array index stuff would cause at least some python prompt exploration or the shift to some sort of reference.
But then you are throwing all the readability gains of list.last vs. list[-1] right out the window and we are back to square one.
I don't think anyone finds Lisp's car and cdr (much less cadr and friends) particularly intuitive when they are first introduced to whichever dialect it happens to be.
You get used to it, and when needed, write specific-case functions for readability that are simple wrappers to those combo functions. Which I think is probably best no matter whether you have last or [-1], this argument is kind of pointless. Step back and think about why you need that item, write a small wrapper function to grab that it and name the wrapper well so it provides a little semantic context to whoever ends up reading the code later.
That's another demonstration of my point. Many, many people out there in the non-tech world would expect that the first element would have an index of "1". First = "1st" = "#1." On the other hand, we often experience the convenience of pointer arithmetic (or similar) with zero-indexed arrays.
Yet another programmer/techy and ordinary person divide.
If you want something for non-techies, you pick something like Applescript.
0-based indexing is noob friendly because most cs algorithms use it so you can do a straightforward translation. Would it be better to go with 1-based and make this harder for novice programmers? I don't think so.
But: when I see code that refers to first and last, I expect that the first and last elements are special.
When I see integers, it leads me to think that all of the elements are about equally important.
I also find it easier to read the text form rather than the integers; I don't have to look carefully to see if it's 1, 11, 7; code reading goes more smoothly.
Having both forms allows me to express, and parse, intention better.
I programmed exclusively in Java while getting my BS in CS, and I have programmed nearly exclusively in PHP since.
How does this person have the audacity to criticize Python? And why are we all reading it?
In a language whose core mantra is "make is simple, make it short" throwing away the implied "this" seems particularly disgusting.
Author: If you want to learn Python's real mantra, try typing "import this" in the interactive shell. One of the lines you'll read is "Explicit is better than implicit," which should give you a clue as to why there is no "implied this" in Python.
In general, you should be more of an expert on programming languages than Guido if you want to write this type of critique of the language -- especially in such a condescending tone.
Working professionally for less than 2 years with a pseudo-rant like this?, he must be in the young-smug-know-it-all phase. I feel like this could be the case because I was in that phase not too long ago.
It's pretty funny what he's actually putting in that page. I just learned that he writes "Object Oriented PHP", regularly writes SQL queries, and is one of those innovative people to use HTML/CSS/JS to make web pages.
> Author: If you want to learn Python's real mantra, try typing "import this" in the interactive shell. One of the lines you'll read is "Explicit is better than implicit," which should give you a clue as to why there is no "implied this" in Python.
Among other things being that he's calling it this which means he's breaking loose convention and making other Python programmers who read his code say, at least briefly "Huh? This?".
That said, one point of huge value to the explicit self variable is that it makes it INCREDIBLY easy at any given time to glance at a method and say "Oh, this method attached to this object IS|ISNT an instance method".
How does this person have the audacity to criticize Python?
Has a blog and an opinion, whatever its merits. Wasn't the great thing about the wide open web that you can do this without it being an exercise in 'audacity' and without knowing more about anything than some guy named Guido?
And why are we all reading it?
Someone upvoted it to the front page of HN, I think.
I wouldn't say that anyone posting about anything is a great thing about the web. Finding good information more easily is an advantage.
"without knowing more about anything than some guy named Guido?"
That's an exaggeration and it doesn't bring the discussion anywhere. It's very well possible to post a good analysis of a language without "knowing as much as Guido." In this case, experience with languages other than PHP and Java would help.
Anyone can talk about why they don't like something (even though a lot of the reasons he mentioned have been refuted here). What's so annoying about this person is the fluffy bullshit (ex: "it completely destroyed its potential.")
You can't confuse not impressing you in the meager amount of time you spent working with it and complete failure.
Those were pretty much non-reasons. I'm supposed to be outraged that Python doesn't give you an implicit "this"? Whatever.
There _are_ some things that are really wrong. The biggest of these is that Python is slow. This limits where you can use, and pushes developers toward using C libraries. Which can solve the slowness, but tends to make for less stable applications. After all those years with "Pure Java", this is a pain I don't feel I should have to endure. I don't care so much about purity, but other languages have managed to be both reliable and somewhat fast...
The other thing that bugs me about Python is the arbitrariness of the features. It has beautiful list and generator comprehensions, but weird support for lambdas. It has a "dicts all the way down" approach to names, but weird closure bugs. Etc. I've read the "Zen of Python" but I still find myself scratching my head. (Then again, I think the same thing about many other languages.)
It's still a good language, though, on the scale of languages. I'd rather write Python than Java (usually).
I know anonymous functions are idiomatic in javascript from using jquery, but I rarely use them in python. Does anyone have a good example of leveraging lambda in python?
71 comments
[ 3.1 ms ] story [ 123 ms ] threadYes, but also Lisp, awk, R, and Prolog. Or something; you can't be Mr. All-Java and then Mr. All-PHP and be in a position to adequately judge programing languages.
You'll notice that Ruby implements objects in a very nontraditional OO way, seemingly similar to python on some levels. But typical OO restrictions create anti-patterns (excuse me, 'design' patterns), instead of direct access or on the fly coding.
The consenting adult argument is compelling for nontraditional semi-encapsulated object implementations, and simply requires a different type of programmer or team to do successfully.
I've been spoon-fed OO since 13 (C++/Java) but am now seeing the good in taking away the boilerplate. Just as OO replaced procedural and (Temporarily) functional paradigms, we will see hybrid languages replacing traditional OO as time comes along (Ruby seems to be a mix of OO, functional, and imperative).
In any case your insight makes me ask - is mainstream OO just a poor outfit for procedural programmers trying to stay relevant?
I can say that C++ was used as a gimmick at least once instead of C on a professional project and everyone hated the code.
Essentially, yes. C++ was invented because large companies wanted to add the "object-oriented" buzzword to their products. Needless to say, the language is a disaster.
Java was an attempt to fix some of the problems with C++ -- primarily, the complete incompatibility of manual memory management and exceptions. Java was a success because any C or C++ developer can sit down with a library reference and begin working, and the resulting programs usually worked better than if the same developer had used C++.
Next came C#, which is an incremental improvement over Java in the same way Java is an improvement over C++. It adds a few useful features from more advanced languages (closures, true generics, properties) and restores some C++ features removed from Java (unsigned integers, operator overloading, preprocessing). Again, its most important feature is that it's not very differing -- a C++ or Java developer can be up and running with C# in a matter of hours.
Python sorta kinds tries to be half way include objects and functional programming, but not really. I especially agree that having to type "self." for every single member instance reference anywhere in your program is just as annoying as much of the boiler plate Java requires. I tried using objects in Python for a while, but found that it just made things more verbose than writing procedurally.
Ermmm.... I think someone misinformed him. In Python, not only can you use the standard library, but you can also use third party libraries as well. And Python's got a ton of those.
Personally, I think the author can make a case that he doesn't like python, but I don't see anything here that makes Python bad. Different strokes for different folks.
As statements are not allowed in lambdas this means you either are stuck writing a local named function and writing the code in idiomatic python or writing some helper functions to allow you to write code in a functional but non-idiomatic python style.
It comes down to a matter of style.
My personal theory is that once a python programmer discovers the magic of itertools they are about 3 months from looking for a new language that supports the functional style more naturally.
People are down on I statement Lambdas because they don't do all of the above so well.
Sometimes, for reasons of style and clarity, I want to define a function inline, but python doesn't allow me to. It forces me to do:
When in some cases, I would like to express it as: So I get that it's never necessary, but I find it sometimes limiting as an author who cares strongly about how his code is organized.Anyway, I'm familiar with why Guido doesn't want them, and I totally respect it, and I write 99% of my personal code in python, so I clearly don't think it's a huge deal. It's just something I wish python did have, is all.
In my experience (mostly JS and AS) they rather usually lead to little pieces of logic scattered all over the place and insufficient decoupling.
Nothing other than an if statement, a goto, and some basic arithmetic is needed in a programming language. It's all syntactic sugar. I agree that such a construct would be useful. However, it's more about if it's worth complicating the language over. I don't necessarily know how complex that would make things, but I can definitely see that a case can be made that it would be more trouble than it's worth considering the way indentation is handled.
Once you have good syntax established for using lamdba-s in any form - they would be used. First users would be as I've put above - callbacks of sort (GUI, IO, etc.)
I have had fun scripting with it however.
I really like the "Classes in Python are more like dictionary objects with functions attached than classes." part though. It's exactly what I expect from objects. There aren't that many situations when we need anything more.
Yeah, that was my favorite part... my response was "yes... yes they are." Everything else with classes just seems to be syntactic sugar.
I'm not saying that is good or bad, but in Python, just about everything is a dict.
In terms of features, Python is definitely strongly of the former variety: it has objects, but not in "opinionated" sense that Smalltalk or even Java do. It has lambdas, but limits them to one line. It has closures, but until py3, they clashed with the implicit declaration syntax. There isn't "one obvious way of doing a lot of things" more complicated than iteration.
dustin's py-github [2] is an especially poignant example which comes to mind: I would never have used classes for something like that, and Python doesn't give a clear reason to use them or not.
1. http://gagne.homedns.org/~tgagne/contrib/EarlyHistoryST.html
2. http://github.com/dustin/py-github
Could you elaborate on what you mean, here? The only issue I know of with Python 2's closures is that there's no scoping keyword for non-local, non-global variables. But that only matters if you're trying to re-define variables in a parent procedure's scope, which is probably not a good idea.
In py26, I'd write it as:
In Python 3, I'd have to choose between the two versions.Here's an example of cycle() as a co-routine:
Alternatively, if you really want to use a callable: Either way, it'll be cleaner than an explicitly stateful object.How so? Everything in this article -- and nearly any point one could make about a programming language -- comes down to a matter of taste.
Take your example -- Python "has objects, but not in an 'opinionated' sense." What you see as a lack of purity, I see as just the right amount of pragmatism. To me, "un-opinionated" classes is a positive point, not a negative one. Where Zidek sees "inherently static" standard libraries, I see inherently stable ones. Where he sees a distressing lack of encapsulation I see a refreshing relaxing of constraints.
I'd go on, but I think you get the point.
You know what's awesome, though? If you don't like Python you don't have to use it!
But you know what isn't awesome? When you complain about this free thing that nobody's forcing you to use. You're just shitting all over someone else's hard work... for what? Page views?
Hacker News -- hell, the whole Internet -- would be a better place if people just shut the hell up about whatever's got their undies in a twist this time.
Sorry, but this is flat out wrong. I mean, Python's syntax is pretty consistent over all (aside from a few quirks). Even still, Kay's archetypical example of a "style language" (Lisp) has definitely evolved more over the years than Python has.
The point isn't that the language has to be perfect. It's just that it has to have a "feel" to it. Python definitely has its own flavor (I mean idiomatic code is called "Pythonic" after all). The other part of the Python philosophy is "practicality beats purity". Therefore, there are times when the Python developers decided to just implement something practical and simple over something that's ideologically consistent.
Which cannot be stressed enough.
Python acknowledges that the programmer is a human more than any other language I have seen. That's why you can get stuff done and keep it maintainable so easily in python. It gives you just enough rope to be very flexible, but tries very hard to not extend it to the length that people normally use to hang themselves.
- Encapsulation. Encapsulation in every language such as Java and Python is by convention. There are always ways to break it. Even in C++. Somehow the blogger missed out on learning "__" notation.
- Batteries. Nearly all the Python libraries are pure Python files which you can edit or debug. You can even debug the C modules with a C debugger if you like since they are just dynamic/shared libraries. You can delete libraries that you never use from your installation.
- This. This is probably the only legitimate complaint, but it all boils down to syntactical sugar.
- Members. Another blatant lack of knowledge. It is possible to enforce static members with the "__slots__" metamember. You can override the default object behavior by implementing the "__getattribute__" and "__setattribute__" members to suit this blogger's preferences.
- Lambda. Another syntactical sugar complaint. Python functions are first class variables.
Conclusion: The blogger's failed attempt to bash Python reveals his own lack of knowledge about the language.
Note the word "accidental". In a language such as Python, there is no way to completely prevent clients from accessing internal state. Even C++ or Java allow sufficiently knowledgeable / desperate clients to poke around wherever they like. Python's philosophy is that since clients will access internal state anyway, it's best to have a sane, documented mechanism.
This reads like he believes the standard library is the only library, which (considering he uses C++ and Java) is a truly bizarre belief. If he doesn't like the standard HTTP library, it's trivial to either distribute a modified version, or use somebody else's (eg, libcurl). Many large Python projects distribute variants of standard library modules to work around errors or missing features in legacy versions of Python. The problem with an implicit "self", aside from it violating the Python Zen, is that it makes a number of cases nastily ambiguous. For example, consider the following method: In this code, the only way to know the scope of 'a' and 'b' is to read the entire class definition. Using explicit scoping prevents ambiguity.Another advantage, though much less, is that it discourages excessive numbers of attributes. Somebody coming from a Java background probably likes having a few hundred attributes floating around in various states as his objects run, but I hate having to deal with code that has so many "moving parts". Adding a "tax" of five characters per attribute access/modification makes code much easier to read and debug.
There are many ways to define members in a class definition. The most heavy-handed is the "__slots__" mechanism, but you can also use properties or simple "foo = None" statements depending on the level of control clients should be allowed.If the author doubts that Python can restrict attribute modification, he should try assigning to a tuple's attributes.
However, the syntax for the explicit self is somewhat awkward. Instead of: def f(self, a, b): ... it could have been def self.f(a, b): ...
[This isn't original to me - Guido has mentioned it when he gets tired of hearing about explicit self.]
With the second, the structure of the argument list in the definition looks like the structure of the argument list in the call and the "self" is where the instance comes from relative to the method name.
Furthermore the claim that python doesn't support objects cleanly or easily is unfounded: 1) everything is an object in python (http://diveintopython.org/getting_to_know_python/everything_...), including classes. 2) properties of an object are accessed in just the same way as in Java (obj.property), I don't understand where the confusion lies.
Encapsulation is the wrong answer to some problems. When it's the right answer (large, disperse, avg or lower ability developers aka "enterprise") go use a language built for that environment such as Java.
Same with self.
[to OA] Not all languages should be applicable to all problems. Quit trying to change Python into your language and leave it as my language.
I regularly monkey-patch builtin standard libraries. Bug in httplib? Easy - I overwrite the built in version, or I do some other trick. It's just Python, get a class that needs a method or an attribute? Just add it.
That's the nice part of "nothing is truly private" in python - and a great argument against bondage and chains style of encapsulation/privacy. If you need to reach in and "fix" something, you can.
I know it's not your fault, but it really struck me. HN should really be a bit more helpful in terms of comment formatting...
Don't take this as hostile. Rather as an observation of the shifted expectations of programmer subculture.
So a cryptic negative index counts as "elegant?" Wouldn't it be more straightforward just to ask a list for "last?"
Here's the equivalent Smalltalk:
In Ruby: Laypeople would have an immediate inkling of either. The negative array index stuff would cause at least some python prompt exploration or the shift to some sort of reference.I don't think anyone finds Lisp's car and cdr (much less cadr and friends) particularly intuitive when they are first introduced to whichever dialect it happens to be.
You get used to it, and when needed, write specific-case functions for readability that are simple wrappers to those combo functions. Which I think is probably best no matter whether you have last or [-1], this argument is kind of pointless. Step back and think about why you need that item, write a small wrapper function to grab that it and name the wrapper well so it provides a little semantic context to whoever ends up reading the code later.
ermmm, I apparently forgot to add the <sarcasm> tag.
Ruby also provides arr[-1], arr[-2], etc. But there's a subtle difference when I read arr.last vs. arr[-1].
Makes sense to me.
Yet another programmer/techy and ordinary person divide.
0-based indexing is noob friendly because most cs algorithms use it so you can do a straightforward translation. Would it be better to go with 1-based and make this harder for novice programmers? I don't think so.
Me too.
But: when I see code that refers to first and last, I expect that the first and last elements are special.
When I see integers, it leads me to think that all of the elements are about equally important.
I also find it easier to read the text form rather than the integers; I don't have to look carefully to see if it's 1, 11, 7; code reading goes more smoothly.
Having both forms allows me to express, and parse, intention better.
How does this person have the audacity to criticize Python? And why are we all reading it?
In a language whose core mantra is "make is simple, make it short" throwing away the implied "this" seems particularly disgusting.
Author: If you want to learn Python's real mantra, try typing "import this" in the interactive shell. One of the lines you'll read is "Explicit is better than implicit," which should give you a clue as to why there is no "implied this" in Python.
In general, you should be more of an expert on programming languages than Guido if you want to write this type of critique of the language -- especially in such a condescending tone.
http://www.zideck.com/blog/about.php
Working professionally for less than 2 years with a pseudo-rant like this?, he must be in the young-smug-know-it-all phase. I feel like this could be the case because I was in that phase not too long ago.
Among other things being that he's calling it this which means he's breaking loose convention and making other Python programmers who read his code say, at least briefly "Huh? This?".
That said, one point of huge value to the explicit self variable is that it makes it INCREDIBLY easy at any given time to glance at a method and say "Oh, this method attached to this object IS|ISNT an instance method".
Has a blog and an opinion, whatever its merits. Wasn't the great thing about the wide open web that you can do this without it being an exercise in 'audacity' and without knowing more about anything than some guy named Guido?
And why are we all reading it?
Someone upvoted it to the front page of HN, I think.
"without knowing more about anything than some guy named Guido?"
That's an exaggeration and it doesn't bring the discussion anywhere. It's very well possible to post a good analysis of a language without "knowing as much as Guido." In this case, experience with languages other than PHP and Java would help.
Anyone can talk about why they don't like something (even though a lot of the reasons he mentioned have been refuted here). What's so annoying about this person is the fluffy bullshit (ex: "it completely destroyed its potential.")
You can't confuse not impressing you in the meager amount of time you spent working with it and complete failure.
I complete agree to your infallible logic and invite you to read an article I wrote about how wonderful ad hominem attacks are:
http://www.zideck.com/blog/article.php?id=4
There _are_ some things that are really wrong. The biggest of these is that Python is slow. This limits where you can use, and pushes developers toward using C libraries. Which can solve the slowness, but tends to make for less stable applications. After all those years with "Pure Java", this is a pain I don't feel I should have to endure. I don't care so much about purity, but other languages have managed to be both reliable and somewhat fast...
The other thing that bugs me about Python is the arbitrariness of the features. It has beautiful list and generator comprehensions, but weird support for lambdas. It has a "dicts all the way down" approach to names, but weird closure bugs. Etc. I've read the "Zen of Python" but I still find myself scratching my head. (Then again, I think the same thing about many other languages.)
It's still a good language, though, on the scale of languages. I'd rather write Python than Java (usually).
Until you meet a nested class. Or the implied objects that use this in JavaScript callbacks.
This white-space lambda encapsulates batteries.
intlist=range(0,16)
filter(lambda x: x % 3 == 0, intlist)
vs.
[x for x in intlist if x % 3 == 0]
Should be faster too: http://stackoverflow.com/questions/1247486/python-list-compr...
I know anonymous functions are idiomatic in javascript from using jquery, but I rarely use them in python. Does anyone have a good example of leveraging lambda in python?