5 ms·
I'm not saying you're wrong: I have been using python for so long, there are undoubtedly problems with it which I am so used to I just don't see them. But I'm
by Estragon 16y ago
I'm not saying you're wrong: I have been using python for so long, there are undoubtedly problems with it which I am so used to I just don't see them. But I'm curious about why python has a reputation in the ruby world as ugly.
And yes, installing scipy from scratch is a bear. If you're using a modern linux distribution, you probably want to install a python scipy package.
- gvnonor 16y agoI think len() being a function instead of a method, explicitly specifying self for each method and other inconsistencies(albeit small) lead rubyists to think of python as ugly. I'm no rubyist(I prefer expediency to elegance, hence python over ruby), so take this with a grain of salt.
- tef__ 16y agothe thing is, self being explicit makes it more consistent unlike 'self' in other languages as a keyword, 'self' is just a variable with the same scoping. i.e self always refers to the most inner scope in other languages (a special variable), meanwhile self in python is wherever self was bound in the current scope. and fwiw: len is a holdover from earlier python (you can define a method __len__ if you want...)
- artsrc 16y agoOnce you make a parameter special, subsequent effort to hide that it is special seems odd. The self parameter looked different in the call to the function.
- masklinn 16y ago> len is a holdover from earlier python No. len is basically a multimethod. > (you can define a method __len__ if you want…) You have to, it's part of the length protocol, `len()` will not work if you don't. Because `len(o)` calls `o.__len__()`). If you start calling underscore-methods directly (outside of a super() access), you're heading for trouble with your coworkers.
- gxti 16y agoThere are two nice things that you get with an explicit "self": * You can nest classes and methods. This is ugly, so I never use it except in testsuites where declaring a mock class right in the test method is the best way to do it, but it's great to have "self" be the testcase and "xself" be the mocked method. * There's no such thing as a magic variable. Every name you can reach is declared somewhere, either locally, globally, or from `__builtins__`. If self were automatic, then it would be invisible like the builtins, but it would change depending on where you used it from. The consistency is worth the minor inconvenience, IMHO.
- baddox 16y agoI think the relationship between lists, iterators, and generators is one of the greatest features of Python. I think len makes sense as a function in the same way the sum function makes sense as a function. Both do an operation on any eager iterable, including ones that don't store or "know" their own length. The explicit self for methods comes straight out of the Python "rule" that explicit is better than implicit. Python is purposefully putting explicitness ahead of beauty, and I agree it's not particularly beautiful. Something that I find even less beautiful in Python is its super syntax: super(theClass, self).method() I'm still relatively new to Python, but I would argue that the super syntax goes a bit too far in explicitness (and I think it's fair to argue the same thing for the "self" in methods). Incidentally, there is a PEP (Python Enhancement Proposal) from 2007 to make super just work as super().method(). http://www.python.org/dev/peps/pep-3135/ http://www.python.org/dev/peps/pep-3135/
- jerf 16y agoIronically for people still criticizing "len" as a function, it is now the more acceptable way of accomplishing the task than what Ruby is doing in many circles. In Python, len is a generic function that can call anything that implements a certain interface. This is more correct that baking the "len" function in somewhere in the object hierarchy, or implementing it relatively randomly throughout the hierarchy with a series of "len" methods that may or may not actually be connected. (len isn't the best example since it's in the "standard set", but in general just because two methods have the same name doesn't mean, well, anything in particular, really.) Favoring interfaces over inheritance leads you to the Python solution, not the Ruby solution. Python's arguably not merely "OK" but more right than Ruby here, if you are really going to be an OO purist (of certain flavors). Python then actually ends up taking advantage of this by having len able to use any of several interfaces. It may call double-underscore-len, but it may also traverse an iterator. It could potentially do other things as well. It's actually a straightforward application of the "prefer interfaces over inheritance" to the dynamic language case. You can criticize the spelling of the double-underscore methods (which if you are really grumpy, can actually be fixed by a metaclass, though I think the cost/benefit tradeoff is bad unless you are the only person who will ever use that code), but if you haven't used them you may not realize just how finely tuned they are, and how well they work with the functions that actually search over the interfaces to find the best one to use in a way somewhat difficult to replicate directly with a "method".
- djacobs 16y agoI don't think I'd call len pure for OOP. Rather, having a top-level definition--len(array) instead of array.length--gives us functional purity. That is, it discards (or hides) the concept of message passing and treats top-level methods like mathematical functions. Lately I've heard a lot of chatter about Ruby Interfaces. They could be useful to achieve better unity. Though the Ruby collection API is already pretty consistent.
- jamesbritt 16y agoPython's arguably not merely "OK" but more right than Ruby here, if you are really going to be an OO purist (of certain flavors). Ruby's flavor is primarily that of sending messages to receivers (hence parens being optional). Python seems more about invoking methods on objects.
- djacobs 16y agoI only know a little bit of Python so far, but I think it's things like the "underscore methods" (__len__, __cmp__, __init__) and the lack of blocks (which give Ruby a kind of elegant unity). I do think, though, that Python's list comprehensions are quite beautiful, and I'm looking forward to using them.
- tef__ 16y agoTo some extent: the underscore methods represent 'magic behaviour' i.e. this gets called implicitly by something else, you never call this directly. i.e you write 4+2 to add things not 4.add(2)
- philwelch 16y agoIs this kind of magic irreversibly baked into Python, or can you make your own magic? One of the things I love about Ruby is that you can make your own magic, because a lot of the "magical" methods that you define (initialize and <=>, for instance) are just, by convention, the methods called by some module or class or whatnot, and you can write your own mixins or do metaprogramming to change up that behavior.
- orangecat 16y agoSure, you can do most of Ruby's wacky tricks in Python, it's just not usually recommended: >>> class Foo: ... def __init__(self, name): ... self.name=name >>> a1 = Foo('Alice') >>> a2 = Foo('Alice') >>> a1==a2 False >>> Foo.__eq__ = lambda self,other: self.name==other.name >>> a1==a2 True
- prodigal_erik 16y agoBlocks are indisputably useful, but beautiful? There's no shortage of rants on the bizzare inconsistencies between blocks and proc and lambda (do I use call or yield? can I use return? why does arity checking rarely work?)
- utku_karatas2 16y ago
- steveklabnik 16y agoI can't speak for the 'Ruby world', but the loss of blocks is significant. Significant whitespace makes code ugly sometimes. "There should only be one way to do it." is wrong. Basically, Ruby values _flexibility_ above all else, and Python introduces unnecessary rigidity, which feels 'wrong' to a Rubyist. And that's another difference between the two communities: Gems are always installed through Rubygems, no exceptions. Distribution's packaging systems (I'm looking at you, Debian) have always just screwed things up, and so Rubyists tend to just remove any system Ruby, install rvm from source (which entails running one bash script), and doing it all through there. Then, everything works great.
- sigzero 16y agoThat quote isn't quite correct. The PEP quote is: "There should be one-- and preferably only one --obvious way to do it." The "obvious" portion of that makes it a little less strict than your quotation. I think it is a "good" axiom to try and aim for. The problem is people think differently and you can't force that really. I like Perl, where almost anything goes, though. :)
- jamesbritt 16y agoThe "obvious" portion of that makes it a little less strict than your quotation. The "obvious" portion is what makes it such a problem. If you have one library for a task, then the choice really is obvious. If you have two libraries, each very good but offering different takes on servicing a task, then "obvious" becomes a problem, and if "obvious" is a goal then one of those libraries becomes a problem. "Obvious" is a problematic goal much like "fair" and "equal" are problematic goals in society. You end up sacrificing much that is good and valuable in pursuit of what is often a vague and situational ideal.
- j_baker 16y agoYes, obviousness is subjective. However, we're discussing what makes a programming language good. Goodness is subjective too, is it not?
- clyfe 16y agoI shunned py because: each(list) vs list.each def(self, args) __ugh__ can't do templates (erb?) dislike object model (objects != functions etc)