April 26, 2005Python keeps rubbing me the wrong wayIn response to Luke Hutteman's post on continuations, someone offered the following Python snippet to illustrate filtering: values = range(10) for nr in (nr for nr in values if nr%2==0): print nrThere are several things that bother me with this code:
Here is a Ruby way of doing the same thing: (0..10)
.find_all { |it|
it %2 == 0
}
.each { |it|
puts it;
}What I like about it:
The latter solution feels much more natural and intuitive to me, whereas most of my time in Python is typically spent
I guess I'm too young for Python and spoiled by modern languages :-) Posted by cedric at April 26, 2005 03:22 PMComments
Amen brotha Posted by: Jonathan Aquino at April 26, 2005 08:20 PMYou can be elegant without being OO and vice versa... the python code is much easier on my eyes. Posted by: Jonathan Ellis at April 26, 2005 09:23 PMI really just don't want to think about you rubbing your Python, Cedric. Posted by: Patrick Calahan at April 26, 2005 09:42 PMOr yet simpler (Ruby) : (0..10).each {|it| puts it if it % 2 == 0 } I like this language. yes, I gave up on python as soon as I saw the "self" keyword. It just made me feel really uncomfortable. I think these experiments with languages are really great. Something good is going to come out of it. At some point I may even feel like learning Ruby or Groovy. But learning a new language is a lot of work, especially when I can get the above easily in java with class tmp { I think it's just a matter of what you're used to. For me as a Python and Java programmer, the Ruby code you show looks just as unnatural and weird as the Python code looks to you. What I suggest, if you want to get a better feel for Python, is to do the Python tutorial (available at www.python.org, also available in any Python distribution you download) which takes you on a (really quick) trip through Python's features. Shouldn't take more than a couple hours. It's definitely a mis-characterization when you say "Python does support some object orientation". Complete object orientation was built in from the start, and it goes further than Java does in a lot of ways : Python allows multiple inheritance and operator overloading, for instance. Did you forgot groovy? But Henry - you example is not filtering; it's simply iterating through a list with an index increment of 2. Or in python if you want to cheat with the filtering (increment of 2) - for x in range(10)[::2]: try this: for nr in filter(lambda arg: arg%2 == 0, range(10)): print nr As someone who is familiar with neither Python nor Ruby I find the Ruby code easier to understand. (BTW I program mostly in Java) Posted by: James Stauffer at April 27, 2005 05:33 AMMy python code was not about filtering as much as it was about generators and the fact that because they are useful, sometime you can use expression syntax aka expedite and yet be lazy. I'm not sure I see those four semantically different uses of nr. There are two for loops. In both cases "for nr" declares the nr variable. The "nr" at the start of the list comprehension expression and the nr in "nr % 2 == 0" are both the number (taken from values) for the current iteration of the for loop - exactly the same as the nr in "print nr" in the outer for loop. So that's two meanings for the string "nr": declaration of a variable, and accessing the value it contains. That would be the same number of meanings as "it" has in your Ruby code, right? What did I miss? You seems to object to the fact that Python doesn't force every possible operation into the obj.function(arg) syntax pigeonhole. I'm not sure that's a bad thing. Seriously though, I wonder if an utterly trivial rearrangement of the Python code would make you feel better about the filtering/writing separation: values = range(10) for nr in filtered: Here is a totally different code: values = range(10)
even = lambda x: x%2 == 0
As far as comic OO design goes: class RubyList(list):
And here's the same thing a few ways in perl: print for ( grep { $_ % 2 == 0 } ( 0 .. 10 ) ); for ( 0 .. 10 ) { foreach my $value ( 0 .. 10 ) { Here's what I like about them: - I can use shortcuts if I want (that scary $_ is really just a form of "it") - I can use more the often more readable form of post-conditions if I want ("print it if this is true") - I can use functional constructs alongside everything else (grep filters a list from right to left using a block or regex) And I don't think I've heard Derrida brought up in discussions of combining paradigms before, nice. (But I'm probably just not in on the right discussions...) Posted by: Chris Winters at April 27, 2005 09:17 PMRe: Chris Winters' comment above: I prefer this one with fewer parentheses: print for grep {$_ % 2 == 0} 0..10; Another perl variant: map {print} grep {$_ % 2 == 0} 0..10; Posted by: Prakash Kailasa at May 3, 2005 08:37 AMI really recommend Jython(JavaPython). You can write Python code if you have to as a simple scripting glue over your Java frameworks plus you don't have to get too deep inside of Python if you don't want to. It really makes coding a lot smoother. Posted by: Berlin Brown at May 4, 2005 04:11 AMYou can separate out the filtering and printing: evens = [n for n in range(10) if n%2==0] But yeah, Python does have its warts. In boo ( http://boo.codehaus.org/ ) the "self" is optional. The colon at the end of lines is redundant and could be made optional too. This is better: for nr in range(10): dont call both variables nr and your problem is solved as to the ruby example, I think it is nowhere near as "obvious" as the python code.
You can write unreadable code in any language... Doesn't mean you have to, though. Posted by: Paul at May 9, 2005 06:28 AMWhat have happened to Pythons "Only one obvious way to do it"-slogan? As more and more constructs get added to Python the more time I use to find the optimal. for nr in range(10): Wonderful, and what made me love python! Easy to read and obvious even to non python programmers. I'm worried as I cant recommend Python to beginners as much as I used to. Posted by: Fredrik C at May 9, 2005 08:05 AMPython: Ruby: Please observe that nobody has a leg to stand on in this argument. I think everyone missed the most straight forward solution in Python: for number in range(0,10,2): print number Using a generator for the expression in a for loop is quite awkward, no doubt. I never ever do that. So identifying and critisizing that awkwardness is not particularly insightful, since it's entirely resolveable. Python is resistent to confusing programming structures, but certainly not invulnerable. Anyway, generally Python style is that you give objects names if things seem confusing, in this case "evens = (n for n in values if n % 2 == 0)". There's your abstract logic. Then "for n in evens: print n" is your display logic. Separate them into functions if you want more abstraction, they are quite ammeniable to such separation and reuse. The OO equivalent of adding an "evens" method to all sequences is rather absurd (at least if you care about large systems, localized changes, and safe integration of multiple libraries). I general for this kind of code OO is inappropriate; OO offers little improvement to algorithmic code. The critique of self here doesn't even apply; self doesn't appear anywhere in the Python code, and the Ruby code doesn't use any construct where Python would use self either. It seems like "self" is the new irrational reason to dislike Python these days, now that significant whitespace seems to have gained some degree of acceptance. While its presence in method signatures is largely superfluous, I think it is very justifiable in code bodies; that Ruby shortens it to "@" doesn't change much. Leaving out any localized distinction between globals functions/variables, and instance methods/variables (as in, say, C++), is (IMHO, as always) far more confusing. Posted by: Ian Bicking at May 9, 2005 11:26 AMRuby's equivalent of "self" is not a keyword in Python, it is a convention. What is built-in to Python is that every instance method defined in the body of a class definition (which is any function that isn't explicitly made into a class method or whatever) has as its first argument the instance that the method is called on. The convention is to use the name "self" for this argument. But you could just as well use "bob" as long as you are consistent. So basically you like ruby because their list/sequence types have a method called 'find_all' and 'each'. Where 'find_all' accepts and expression ('it %2 == 0') and 'each' accepts another method ('puts'). 'Cause that's what I see happening in the Ruby code. Although I don't speak ruby. Posted by: edwardam at May 9, 2005 03:58 PMclass slist(list): if __name__ == "__main__": I am fascinated that you spend so much time complaining about Python. Is someone making you use it for a job? There is a reason that there are so many programming languages - and that is that there are many ways of expressing these concepts. Python clearly doesn't suit the way you think or your sense of aesthetics. That doesn't mean that there is anything wrong with you or Python. Anyhow, seing the first complain was about unclear syntax. Python promotes clarity, but certainly does not enforce it. In any real application this is how you should do def listfilter(argument): unfilteredlist = range(10) for item in filteredlist: One-liners are never pretty, there is always a way to make things obfuscated. Take a look at this C code example and see if its clear :D http://remus.rutgers.edu/~rhoads/Obfuscated_C/pi.c Posted by: Stefan at May 10, 2005 01:03 PMTo preserve formatting: Why don't do it like this? for nr in range(0,10,2): Why not for nr in range(0,10,2): Come on folks, you must compare the most beautiful way in a language to another language. I am in love with Ruby, but the original post of cedric is really unfair if there are more beautiful and still short ways to achieve something in Python. Posted by: shev at September 30, 2005 01:30 AMhref Posted by: Charge Back at November 14, 2005 06:26 AMin c# 3.0: It is truly beautiful but needs some extension methods to be included. Posted by: exe at April 20, 2007 10:06 PMin c# 3.0: It is truly beautiful but needs some extension methods to be included. Posted by: exe at April 20, 2007 10:06 PMobviously it is ボイストレーニング nt32.Range(0,20).WhereIndexIs(i=>i.Even()).ForEach(v=>Console.WriteLine(v)); It is truly beautiful but needs some extension methods to be included. obviously it is Posted by: nguyen at July 9, 2009 07:06 AMPost a comment
|