Why Python is the best programming language in the world

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Why Python is the best programming language in the world

Postby jestingrabbit » Mon Sep 16, 2013 4:58 am UTC

lunar wrote:Has this been mentioned already? I don't think anyone could, with awareness of this fundamental issue, be able to call Python the best programming language in the world, until the issue has been solved:

http://www.jeffknupp.com/blog/2012/03/3 ... t-problem/


Looks like its been solved.

https://us.pycon.org/2013/schedule/presentation/37/
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Why Python is the best programming language in the world

Postby Jplus » Mon Sep 16, 2013 6:42 am UTC

Also, the article already stated quite clearly than the GIL is not inherent to Python as not all interpreters have it.

lunar wrote:However, once it was, I think I would easily jump on this bandwagon, as it is a pleasure to work with the language in every other capacity compared to almost every other language I can think of. The closest contender for me might be C# (when leveraging its newest features, not at all in the sense of the C# 1 code you still see all over the place).

Just a question out of curiosity: what languages other than Python and C# do you know?
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

lalop
Posts: 210
Joined: Mon May 23, 2011 5:29 pm UTC

Re: Why Python is the best programming language in the world

Postby lalop » Mon Sep 16, 2013 11:31 am UTC

Diadem wrote:Python isn't the best programming language in the world, because it's not a programming language at all. It's a scripting language.



Wikipedia wrote:A scripting language is a programming language that supports the writing of scripts


It does seem hard to say something is not a programming language when people use it to, well, program.

I don't really think there's anything unique to python that can't be done similarly in other languages. In part, this is because many of the newer languages have been learning from one another, a really good thing. Also, python's zen (that there should be only one, obvious, way of doing it) does seem to limit it somewhat. If it is the "best language", it's probably due to its more reabable syntax and being reasonably powerful - say, high-medium to low-high on the language spectrum.

Here's a quick implementation of minimax, I guess:

Code: Select all

import random
from collections import namedtuple

class Node(namedtuple('Node',['points','children'])):
    "Tuple extension for minimax problem"
    def __new__(self, points = None, children = []):
        "Initialization with default values"
        return super(Node, self).__new__(self,points,children)

    @property
    def isLeaf(self):
        "Checks if this Node has no children"
        return not self.children

def max_node(node):
    "Given a node in a minimax game, returns the max possible node that can be achieved"
    if node.isLeaf:  #this is the last node
        return node

    return max(min_node(child) for child in node.children)

def min_node(node):
    "Given a node in a minimax game, returns the min possible node that can be achieved"
    if node.isLeaf:  #this is the last node
        return node

    return min(max_node(child) for child in node.children)


I thought it was pretty cool how you could tersely create new data types, and get it working with the default operators. Between this pattern and clojure's maps, I have a newfound appreciation for tuples.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Why Python is the best programming language in the world

Postby troyp » Mon Sep 16, 2013 7:40 pm UTC

Diadem wrote:Python isn't the best programming language in the world, because it's not a programming language at all. It's a scripting language.

It's a scripting language and a programming language. I use both web and desktop apps written in Python every day (youtube, reddit, calibre, devede...)

PM 2Ring wrote:That Switch class is cute, but it's also a bit scary. I don't think I'd ever be tempted to use it. :)
I don't really miss a Switch statement in Python. Most of the time I'm happy enough to use if/elif/else although I do occasionally use a dict of functions (&/or lambdas) to achieve Switch functionality. In situations where you don't want the case code to be a function I guess you could exec an element of a dict of compiled code blocks, although I generally try to avoid using exec & eval.

Oh, I never actually use syntax hacks I write (although sometimes I think I should - in certain cases). I'm usually okay with if/elif blocks for blocks of imperative code, but it annoys me when I want to write, say, a function with several cases returning different expressions (which is the situation that class was written to address, although not seriously).

I've never explicitly thought of a dict of functions as an alternative to if/elif. I mean, it obviously is, but since the dict is an object and the if/elif block is just "dumb code", they exist at totally different "levels" for me. Even if I refactor from one to the other, I think of it as more a change in program structure than in syntax. Now I'm imagining a "reified if/elif block" that takes a name and produces a mapping that can be introspected and modified dynamically. I could write such a reified if/else, but I can't of course because Python doesn't have macros *grumble* *grumble*...

lunar wrote:Has this been mentioned already? I don't think anyone could, with awareness of this fundamental issue, be able to call Python the best programming language in the world, until the issue has been solved:

http://www.jeffknupp.com/blog/2012/03/3 ... t-problem/

Getting rid of the GIL in Python would have consequences "as transformative" as a reasonable poly-time algorithm for an NP problem?? I think he's gotten a bit carried away here.

Anyway, as people have said, this is a CPython problem, not a problem with every Python interpreter. But even in CPython, I don't think this is such a fundamental problem. Python has libraries for both parallelism (eg. multiprocessing) and lightweight concurrency (eg. greenlet). Plus, any truly performance critical code is likely to be written in C.

Volcano99
Posts: 56
Joined: Wed Dec 16, 2009 10:10 pm UTC
Location: 350 km SW of The Castle

Re: Why Python is the best programming language in the world

Postby Volcano99 » Mon Sep 16, 2013 10:58 pm UTC

Code: Select all

class Node(namedtuple('Node',['points','children'])):
    def __new__(self, points = None, children = []):
        "Initialization with default values"
        return super(Node, self).__new__(self,points,children)


This code is buggy if more than one node is initialized without the children parameter. The default values for parameters are initialzed once, on function declaration. This means all Nodes share the same instance of the list, and this will cause problems.

The correct way to do it is:

Code: Select all

class Node(namedtuple('Node',['points','children'])):
    def __new__(self, points = None, children = None):
        "Initialization with default values"
        if children is None:
            children = []
        return super(Node, self).__new__(self,points,children)


I'd prefer the first version if it weren't buggy.

Maelstrom.
Posts: 76
Joined: Tue Oct 21, 2008 12:18 pm UTC

Re: Why Python is the best programming language in the world

Postby Maelstrom. » Wed Sep 18, 2013 6:34 am UTC

Volcano99 wrote:This code is buggy if more than one node is initialized without the children parameter. The default values for parameters are initialzed once, on function declaration. This means all Nodes share the same instance of the list, and this will cause problems.

The correct way to do it is:

Code: Select all

class Node(namedtuple('Node', ['points', 'children'])):
    def __new__(self, points = None, children = None):
        "Initialization with default values"
        if children is None:
            children = []
        return super(Node, self).__new__(self,points,children)


It is only a problem if you mutate the list in place, which would mutate all the lists as you say. If the default value was instead the empty tuple - tuples being immutable - there would be no problem:

Code: Select all

class Node(namedtuple('Node',['points','children'])):
    def __new__(self, points=None, children=()):
        "Initialization with default values"
        return super(Node, self).__new__(self, points, children)


Of course, this then brings up the problem of never being able to add children to leaf nodes, but that sounds like a bad idea anyway.

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Why Python is the best programming language in the world

Postby phlip » Wed Sep 18, 2013 7:15 am UTC

Maybe so in that specific case, but still, in general terms,

Code: Select all

def foo(bar=someexpr):
  ...
will only evaluate "someexpr" once, at the point the function is defined, rather than every time the function is called without a parameter. Aliasing, when someexpr evaluates to a mutable object, is only the most obvious problem this causes... another is that you can't make parameters dependent on each other:

Code: Select all

def foo(bar, baz=bar): # Nope.
  ....

The standard trick to get around all this is:

Code: Select all

def foo(bar=None):
  if bar is None:
    bar = someexpr
  ...
but then that means you can't explicitly pass None. If that needs to be an option, you need to make your own out-of-band value:

Code: Select all

noparameter = object()
def foo(bar=noparameter):
  if bar is noparameter:
    bar = someexpr
  ...
which is just ugly. You can twerk it a little:

Code: Select all

def foo(bar=object()):
  if bar is foo.func_defaults[0]:
    bar = someexpr
  ...
but that's really not much better.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Carlington
Posts: 1588
Joined: Sun Mar 22, 2009 8:46 am UTC
Location: Sydney, Australia.

Re: Why Python is the best programming language in the world

Postby Carlington » Wed Sep 18, 2013 8:11 am UTC

Wait, is there no way to do switch...case statements in Python? I thought there was, but maybe I'm wrong.

EDIT: Read the docs before posting, Carlington. Apparently there is no way to do that other than if/elif in Python. Now I'm confused, because Python is the only language I actually know how to write anything in, so where else would I be getting that from? Unless it was when I was learning to tinker with Bash, maybe.
Kewangji: Posdy zwei tosdy osdy oady. Bork bork bork, hoppity syphilis bork.

Eebster the Great: What specifically is moving faster than light in these examples?
doogly: Hands waving furiously.

Please use he/him/his pronouns when referring to me.

xGeovanni
Posts: 36
Joined: Thu Oct 06, 2011 7:03 pm UTC

Re: Why Python is the best programming language in the world

Postby xGeovanni » Wed Sep 18, 2013 8:56 am UTC

Please do avoid having this thread turn in to another religious war. We all want to share interesting code here. I have some kinda-kinda-interesting code to share.

Here's a function to "invert" a 2D list (Turn it from

Code: Select all

[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
to

Code: Select all

[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
). It only works when all the sub-lists are the same length, so it's really limited, but it's somewhat cool that you can do it so simply:

Code: Select all

def invert(list2D):
   return zip(*list2D)


I invite you all to outdo me, with support for varying sub-list lengths and support for all sorts of edge cases.

User avatar
Carlington
Posts: 1588
Joined: Sun Mar 22, 2009 8:46 am UTC
Location: Sydney, Australia.

Re: Why Python is the best programming language in the world

Postby Carlington » Wed Sep 18, 2013 9:35 am UTC

Here be my five-minute attempt, but it doesn't work. I'm getting IndexErrors, and I can't be bothered figuring out why. Feel free to modify and improve, though.

Code: Select all

def Invert(Matrix):
   Columns = len(Matrix[0])-1 #Number of columns in the input matrix
   Rows = len(Matrix)-1 #Number of rows " " " "
   Inverted = [] #Inverted matrix - this is what we will return
   for x in range(Columns):
      for y in range(Rows):
         Inverted[y][x] = Matrix[x][y]
   
   return Inverted
Kewangji: Posdy zwei tosdy osdy oady. Bork bork bork, hoppity syphilis bork.

Eebster the Great: What specifically is moving faster than light in these examples?
doogly: Hands waving furiously.

Please use he/him/his pronouns when referring to me.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Why Python is the best programming language in the world

Postby jestingrabbit » Wed Sep 18, 2013 12:58 pm UTC

Carlington wrote:Here be my five-minute attempt, but it doesn't work. I'm getting IndexErrors, and I can't be bothered figuring out why. Feel free to modify and improve, though.

Code: Select all

def Invert(Matrix):
   Columns = len(Matrix[0])-1 #Number of columns in the input matrix
   Rows = len(Matrix)-1 #Number of rows " " " "
   Inverted = [] #Inverted matrix - this is what we will return
   for x in range(Columns):
      for y in range(Rows):
         Inverted[y][x] = Matrix[x][y]
   
   return Inverted


First up, your ranges are going to be one less than you want. Remember: range(n) = [0, 1, 2, ..., n-1] ie its built to so that range(len(a_list)) indexes a_list. Secondly, after you declare Inverted as a 0 length list, you can't start talking about elements, you could maybe work out some sort of appending that would work ie append an empty list in the outer "for", fill it up with appends in the inner.

An alternative:

Code: Select all

def transpose(Matrix):
""" when you swap rows for columns, that's a transpose."""
   return [ [Matrix[i][j] for i in xrange(len(Matrix))] for j in xrange(len(Matrix[0]))  ]


But, apart from getting the name of the function right, I don't think this is any better than Geovanni's.
Last edited by jestingrabbit on Wed Sep 18, 2013 1:00 pm UTC, edited 1 time in total.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Carlington
Posts: 1588
Joined: Sun Mar 22, 2009 8:46 am UTC
Location: Sydney, Australia.

Re: Why Python is the best programming language in the world

Postby Carlington » Wed Sep 18, 2013 1:00 pm UTC

I think it's a step in the right direction, funtionality-wise, simply because (if I'd implemented it properly) it can handle matrices of arbitrary height and width (although still only in two dimensions.) OTOH, on balance it may lose out, simply because it's a pretty poor attempt. I think I'll make a real attempt at this that takes more than 30 seconds' planning.
Last edited by Carlington on Wed Sep 18, 2013 1:04 pm UTC, edited 1 time in total.
Kewangji: Posdy zwei tosdy osdy oady. Bork bork bork, hoppity syphilis bork.

Eebster the Great: What specifically is moving faster than light in these examples?
doogly: Hands waving furiously.

Please use he/him/his pronouns when referring to me.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Why Python is the best programming language in the world

Postby jestingrabbit » Wed Sep 18, 2013 1:03 pm UTC

Carlington wrote:I think it's a step in the right direction, funtionality-wise, simply because (if I'd implemented it properly) it can matrices of arbitrary height and width (although still only in two dimensions.)


I think you're talking about the fact that Geovanni's uses tuples as the rows, and a list as the container for the rows. Yeah, that feels dodgy.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
Carlington
Posts: 1588
Joined: Sun Mar 22, 2009 8:46 am UTC
Location: Sydney, Australia.

Re: Why Python is the best programming language in the world

Postby Carlington » Wed Sep 18, 2013 1:10 pm UTC

Handle. I forgot to verb, my attempt can handle matrices of arbitrary width and height (can I call this "dimensions", or does that imply 2-D versus n-dimensional?). I was mainly referring to the fact that Geovanni's function could only deal with square matrices. Also, it seems like it is just an inbuilt function or a function from a library that is being called inside of a function that Geovanni defined for...some reason? What I'm saying it, it seems as though it's equivalent to saying "I just wrote a really neat function for finding the square root of a number" and then posting:

Code: Select all

import math

def SquareRoot(num): #Takes the square root of a number.
   x = num
   return math.sqrt(x)



EDIT BECAUSE DOUBLE POSTING IS BAD BUT I REALISED SOMETHING. I didn't understand you properly. You were saying that the code-snippet you posted wasn't much better than Geovanni's. Now I see.
Also, the switch statement idea I was hung up on before was just confusion with try...catch. For some reason.
Kewangji: Posdy zwei tosdy osdy oady. Bork bork bork, hoppity syphilis bork.

Eebster the Great: What specifically is moving faster than light in these examples?
doogly: Hands waving furiously.

Please use he/him/his pronouns when referring to me.

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Why Python is the best programming language in the world

Postby phlip » Wed Sep 18, 2013 1:34 pm UTC

Carlington wrote:I was mainly referring to the fact that Geovanni's function could only deal with square matrices.

No, it'll handle rectangular matrices:

Code: Select all

>>> a = [[1,2,3],[4,5,6]]
>>> zip(*a)
[(1, 4), (2, 5), (3, 6)]
It's not exactly like your sqrt example in that this isn't really what the "zip" operator is intended for, it's just that with the semi-abusive syntax of using the star notation there, the "zip" and "transpose" operations are, at some level, the same thing (except for awkwardly returning a list of tuples, as mentioned).

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Why Python is the best programming language in the world

Postby jestingrabbit » Wed Sep 18, 2013 1:44 pm UTC

Carlington wrote:I was mainly referring to the fact that Geovanni's function could only deal with square matrices.


Nah, his will work fine with rectangular matrices. And zip is a builtin, and in the documentation (which I just looked up) this example is pretty strongly suggested. But the fact that the rows are tuples and the total container is a list feels like a problem.

Carlington wrote:Also, it seems like it is just an inbuilt function or a function from a library that is being called inside of a function that Geovanni defined for...some reason? What I'm saying it, it seems as though it's equivalent to saying "I just wrote a really neat function for finding the square root of a number" and then posting:

Code: Select all

import math

def SquareRoot(num): #Takes the square root of a number.
   x = num
   return math.sqrt(x)



There's more cunning than that going on, with the *-magic and whatnot.

EDIT BECAUSE DOUBLE POSTING IS BAD BUT I REALISED SOMETHING. I didn't understand you properly. You were saying that the code-snippet you posted wasn't much better than Geovanni's. Now I see.


Yeah, mine isn't amazing or anything, but it'll also do the right thing with rectangular matrices, and list comprehensions are pythonic whereas the *-magic is deprecated.

ninja'd.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

Maelstrom.
Posts: 76
Joined: Tue Oct 21, 2008 12:18 pm UTC

Re: Why Python is the best programming language in the world

Postby Maelstrom. » Wed Sep 18, 2013 9:45 pm UTC

Passing a tuple to list creates a list with the same contents, and list is a callable like any other. Combine this with map, and you can get:

Code: Select all

m = [[1,2,3], [4,5,6]]
def transpose(m):
    return map(list, zip(*m))

transpose(m)
# [[1, 4], [2, 5], [3, 6]]

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Why Python is the best programming language in the world

Postby troyp » Wed Sep 18, 2013 10:11 pm UTC

Carlington wrote:Also, it seems like it is just an inbuilt function or a function from a library that is being called inside of a function that Geovanni defined for...some reason? What I'm saying it, it seems as though it's equivalent to saying "I just wrote a really neat function for finding the square root of a number" and then posting:

To be fair, he said "kinda kinda interesting" which is a bit different from "really neat". And I'm sure it's interesting to some people if only as an illustration of what zip does (or argument expansion for that matter).

I wouldn't write a transpose function that turns the rows of a list into tuples, but I have certainly written functions that do nothing other than employ argument expansion, eg:

Code: Select all

def enlist(*l): return list(l)
def entuple(*tup): return tup
...and the latter doesn't even call a builtin function!

Incidentally, for a transpose function without the list-tuple conversion, I would use:

Code: Select all

def tr(l): return map(enlist, *l)

– or, using Python builtins:

Code: Select all

def tr(l): return map(lambda *x: list(x), l)


edit:
jestingrabbit wrote:*-magic is deprecated

Hold on, what!?
That seems outrageous - are you sure? I just googled, but I can't find anything... I did discover tuple parameters are removed in Py3*. Were you thinking of that?

* which is disappointing, but apparently they were a PITA for function introspection, so fair enough I guess. You can still destructure the args in an assignment, just not from the parameter list itself.

User avatar
jestingrabbit
Factoids are just Datas that haven't grown up yet
Posts: 5967
Joined: Tue Nov 28, 2006 9:50 pm UTC
Location: Sydney

Re: Why Python is the best programming language in the world

Postby jestingrabbit » Thu Sep 19, 2013 12:07 am UTC

troyp wrote:
jestingrabbit wrote:*-magic is deprecated

Hold on, what!?
That seems outrageous - are you sure? I just googled, but I can't find anything... I did discover tuple parameters are removed in Py3*. Were you thinking of that?


I think I got it into my head when I started to run pylint on my code... I probably shouldn't take advice on how to code from programs that are so hypercritical. I need a more supportive style dealie.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Why Python is the best programming language in the world

Postby phlip » Thu Sep 19, 2013 1:27 am UTC

Yeah, there's no way that the * and ** syntaxes are deprecated... hell, apply() was deprecated in Py2 and removed in Py3 because the * and ** syntaxes were preferred.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
skeptical scientist
closed-minded spiritualist
Posts: 6142
Joined: Tue Nov 28, 2006 6:09 am UTC
Location: San Francisco

Re: Why Python is the best programming language in the world

Postby skeptical scientist » Thu Sep 19, 2013 1:46 am UTC

jestingrabbit wrote:I think I got it into my head when I started to run pylint on my code... I probably shouldn't take advice on how to code from programs that are so hypercritical. I need a more supportive style dealie.

I like the hypercriticality. But yeah, don't be shy about ignoring/silencing lint warnings you disagree with.
I'm looking forward to the day when the SNES emulator on my computer works by emulating the elementary particles in an actual, physical box with Nintendo stamped on the side.

"With math, all things are possible." —Rebecca Watson

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Why Python is the best programming language in the world

Postby phlip » Thu Sep 19, 2013 1:54 am UTC

skeptical scientist wrote:But yeah, don't be shy about ignoring/silencing lint warnings you disagree with.

Oh, God yes. I love Python, and I think it's a great language, but PEP 8 can go die in a hole somewhere.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

Maelstrom.
Posts: 76
Joined: Tue Oct 21, 2008 12:18 pm UTC

Re: Why Python is the best programming language in the world

Postby Maelstrom. » Thu Sep 19, 2013 2:56 am UTC

phlip wrote:
skeptical scientist wrote:But yeah, don't be shy about ignoring/silencing lint warnings you disagree with.

Oh, God yes. I love Python, and I think it's a great language, but PEP 8 can go die in a hole somewhere.

I actually quite like the pep8 linter. I turn off warnings about line length (but try to keep lines <80 anyway), but otherwise obey it. It has made my coding habits very consistent and clean. It took me a while to break out of some habits I had gathered from other languages, but overall pep8 makes python nice IMO.

I found pylint to be waaaay to critical. It goes so far as to warn about 'map(func, list)', declaring list comprehension '[func(x) for x in list]' better. It also completely falls over when dealing with metaclass magic, which abounds in Django models.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Why Python is the best programming language in the world

Postby EvanED » Thu Sep 19, 2013 4:04 am UTC

I actually mostly like PEP8 as well. My main objections are (1) the 80-column rule (which I hate everywhere, though less so with Python than C++), (2) a few things that PEP8 allows that I dislike and would prohibit (e.g. I would put a near-absolute ban on \ line continuations, and the two examples it gives of where it's "appropriate" I disagree with, especially saying it can be OK in an assert), and (3) I think there are quite a few scenarios where I think that vertically aligning operators (or commas separating arguments) across lines is beneficial to reading (while PEP8 prohibits it).

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Why Python is the best programming language in the world

Postby phlip » Thu Sep 19, 2013 4:13 am UTC

My main gripe with PEP8 is the tabs vs spaces thing... That and the 80-columns thing (the existence of which is probably a large part of why they mandate a specific indent width). A lot of the things they recommend make sense, but those two are just... ugh.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Why Python is the best programming language in the world

Postby troyp » Thu Sep 19, 2013 4:27 am UTC

re: Pylint:
I've never really seen much point to using pylint, etc. I can understand using a linter to check coding style when you have many people contributing to a project and want to enforce some kind of standard, but if it's just you...it seems superfluous. I write in what I consider a good style, so if pylint were to complain, it would be either because we disagree about style or because I've decided an exception is warranted. I don't tend to make "style errors" the way I make logic errors: however I've coded a program is doubtless how I wanted to, so why would I need to be informed of my own decisions?

Maelstrom's comment about habits from other languages makes sense, I guess. If you learn languages by starting to code actual applications before you've learned your way around the language, I can see how a linter would be really handy. But once you're comfortable with a language, your judgement is going to be better than any linter's.

I don't know...I might be missing something. Maybe I should try using one for a while and see if I find any value in it. (Although it'd need to be pretty configurable for me to tolerate it: it's one thing to have it blindly enforcing my own style rules; blindly enforcing someone else's would be infuriating.)

enumerate:
I was going rewrite jr's index-based transpose to illustrate the enumerate function, which I often use to avoid monstrosities involving "for n in xrange(len(ls))". I ended up with something halfway there: it uses indexing along one axis and direct iteration along the other.

Code: Select all

def tr(l): return [[r[n] for r in l] for (n,_) in enumerate(l[0])]
(I'd prefer the straight "map and *" based implementation I posted before (or Maelstrom's map/zip/*) - this is just an example of enumerate.)

Maelstrom.
Posts: 76
Joined: Tue Oct 21, 2008 12:18 pm UTC

Re: Why Python is the best programming language in the world

Postby Maelstrom. » Thu Sep 19, 2013 6:10 am UTC

When I started using pep8, I was fairly new to Python. I had used multiple other languages before then, but nothing like Python. I figured that if there actually was a blessed style in Python then who was I to question it? I already had to adapt to no braces, and significant whitespace, so adopting some style guides on top of a syntax that was completely new to me was not much extra effort. Plus I work in a team of people who all use Python so having a single standard - defined by Pyhton itself, not some random opinion - counts as a Good Thing.

Nyktos
Posts: 138
Joined: Mon Mar 02, 2009 4:02 pm UTC

Re: Why Python is the best programming language in the world

Postby Nyktos » Fri Sep 20, 2013 1:09 am UTC

phlip wrote:My main gripe with PEP8 is the tabs vs spaces thing... That and the 80-columns thing (the existence of which is probably a large part of why they mandate a specific indent width). A lot of the things they recommend make sense, but those two are just... ugh.
PEP 8 (the actual PEP, I don't know about the tool) has become a little more lenient on the 80 characters thing recently:
Some teams strongly prefer a longer line length. For code maintained exclusively or primarily by a team that can reach agreement on this issue, it is okay to increase the nominal line length from 80 to 100 characters (effectively increasing the maximum length to 99 characters), provided that comments and docstrings are still wrapped at 72 characters.
This is obviously still incredibly conservative, but it's a little better?

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Why Python is the best programming language in the world

Postby Jplus » Fri Sep 20, 2013 7:38 am UTC

I hate it when I'm forced to scroll sideways in order to read code, whether "scroll" means "turn my head" or "pan using the mouse". I think 80 characters is entirely reasonable even today. However I do not understand the limit of 79 characters. Why did they do that?!?
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
PM 2Ring
Posts: 3715
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Why Python is the best programming language in the world

Postby PM 2Ring » Fri Sep 20, 2013 8:18 am UTC

From http://www.python.org/dev/peps/pep-0008 ... ine-length

Limiting the required editor window width makes it possible to have several files open side-by-side, and works well when using code review tools that present the two versions in adjacent columns.

The default wrapping in most tools disrupts the visual structure of the code, making it more difficult to understand. The limits are chosen to avoid wrapping in editors with the window width set to 80, even if the tool places a marker glyph in the final column when wrapping lines. Some web based tools may not offer dynamic line wrapping at all.
(bolding mine)

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Why Python is the best programming language in the world

Postby EvanED » Fri Sep 20, 2013 8:28 am UTC

Jplus wrote:I hate it when I'm forced to scroll sideways in order to read code, whether "scroll" means "turn my head" or "pan using the mouse". I think 80 characters is entirely reasonable even today. However I do not understand the limit of 79 characters. Why did they do that?!?

Some editors
use the 80th
column for
things like
line continu-
ation charact-
ers and stuff
like that, so
you'll get a
wrap at 80
characters
instead of
81. :-)

(Sorry, I'm apparently feeling like being an asshole at the moment... Also PM 2Ring already said that, but I originally posted this reply in the wrong thread and want to leave it. So there.)

There are a couple of reasons I don't like the 80 character limit, and I think it's because I see the code as more of a 2D thing than a lot of people do. For instance, I like to align things between lines that have parallel structure. For example, if I have this:

Code: Select all

foo(-x,  y)
foo(-x, -y)
foo( x,  y)
foo( x, -y)

I would rather lay it out as above than

Code: Select all

foo(-x, y)
foo(-x, -y)
foo(x, y)
foo(x, -y)

which a lot of style guides (e.g. PEP8) require. It makes it much easier to see what the relation is between the four lines, and to make sure that every case is covered. But if that appeared indented a few times1 and with a longer name (maybe window.mainArea().drawRectangle instead of foo) or something and pretty soon you'll be forced to wrap at 80 characters, and can no longer show correspondences between lines.

In C++ in particular, it is so easy to get to 80 characters that I always feel just way too cramped. A somewhat wider line length -- like 100 or 120 characters -- doesn't require noticeably more horizontal scrolling if you have a realistic display, and it makes it much easier to take advantage of laying things out so that it makes more sense (IMO).

1 My style of indenting namespace contents makes this much more likely to occur, but at the moment that's what I do.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Why Python is the best programming language in the world

Postby Jplus » Fri Sep 20, 2013 8:42 am UTC

@PM 2Ring: Thanks. I understand the reasoning, but I disagree about me needing to adjust because somebody else might have chosen to use a poorly designed editor. Editors are tools, not audience, and if they cause problems they should be replaced.

@EvanED: I like to align lines too, but I think you just shouldn't allow them to become longer than 80 characters. 120 characters might not take more scrolling but it does take more head-turning and eye-straining. If you can't align within 80 columns, you're either using too long names (there's always a solution for that) or trying to show too much information on a single line anyway.

I agree that one could make an exception for a large 2D array, though. Usually you don't really want to read that so it doesn't matter and it saves vertical space.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
Diadem
Posts: 5654
Joined: Wed Jun 11, 2008 11:03 am UTC
Location: The Netherlands

Re: Why Python is the best programming language in the world

Postby Diadem » Fri Sep 20, 2013 12:39 pm UTC

I couldn't disagree more about 80 characters being a reasonable limit. Giving your identifiers good names helps readability a lot, and a good name is generally 2 or 3 words. You can easily have several identifiers on one line. Something like "NamespaceName::ReturnTypeName Classname::Functionname(ParameterType* ParameterOne, SecondParameterType* ParameterTwo) {" is entirely reasonable, and 120 characters. Plus you're indenting can easily eat away 20 characters too. Granted, that's c++ and python will generally have shorter lines, but even in python 80 characters is very limiting.

The 80 character limit made sense, a long time ago. It doesn't make sense anymore. My monitor here is at the small side, a huge portion of my screen is taken by other windows than my main view, and I can still display 135 characters.

If more than 80 characters is a problem, you should shout at your manager until he buys you a new monitors. If comparing things side by side is a problem, shout at your manager until he buys you a second monitor.
It's one of those irregular verbs, isn't it? I have an independent mind, you are an eccentric, he is round the twist
- Bernard Woolley in Yes, Prime Minister

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Why Python is the best programming language in the world

Postby Jplus » Fri Sep 20, 2013 1:19 pm UTC

Diadem wrote:Something like "NamespaceName::ReturnTypeName Classname::Functionname(ParameterType* ParameterOne, SecondParameterType* ParameterTwo) {" is entirely reasonable, and 120 characters. Plus you're indenting can easily eat away 20 characters too.

Yes, that's reasonable, but there's no need to align it with another line and you can do something similar to this:

Code: Select all

NamespaceName::ReturnTypeName Classname::Functionname   (
                    ParameterType* ParameterOne,
                    SecondParameterType* ParameterTwo   ) {

This has nothing to do with screen estate and everything with readability.

Wrapping tricks like these are common practice; go read Boost libraries if you think I'm pulling this from my ass.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Why Python is the best programming language in the world

Postby troyp » Fri Sep 20, 2013 11:05 pm UTC

Diadem wrote:The 80 character limit made sense, a long time ago. It doesn't make sense anymore. My monitor here is at the small side, a huge portion of my screen is taken by other windows than my main view, and I can still display 135 characters.

My monitor is average-sized. 22 inches, maybe? Something like that. I can really only fit a hundred characters or so on a half screen at a comfortable size. I used to read tiny writing, which is probably why I can't anymore (also, reading books in the dark...) On my laptop, even 100 is pushing it, unless I want to devote the whole screen to the code.

For some languages, >100 chars may be necessary, but for python, which is a fairly concise and not heavily nested language, I think 100 chars is mostly reasonable. There are occasions when keeping to 100 chars causes me difficulties and I have to spend a minute or two trying to find a way to readably format some code. It's relatively rare though, and I think some of the fault is Python's due to its limited flexibility in formatting code.

EvanED wrote:There are a couple of reasons I don't like the 80 character limit, and I think it's because I see the code as more of a 2D thing than a lot of people do. For instance, I like to align things between lines that have parallel structure. For example, if I have this:

Code: Select all

foo(-x,  y)
foo(-x, -y)
foo( x,  y)
foo( x, -y)

I would rather lay it out as above than

Code: Select all

foo(-x, y)
foo(-x, -y)
foo(x, y)
foo(x, -y)

which a lot of style guides (e.g. PEP8) require. It makes it much easier to see what the relation is between the four lines, and to make sure that every case is covered. But if that appeared indented a few times1 and with a longer name (maybe window.mainArea().drawRectangle instead of foo) or something and pretty soon you'll be forced to wrap at 80 characters, and can no longer show correspondences between lines.

This is something I hate about PEP8 as well*. I'm not fanatical about alignment. In the assignment example given in PEP8, I'd probably format it like they do, but that's a pretty extreme case (and frankly, it seems somewhat dishonest of them to use it as an example). In most cases aligning things makes them easier to read.

Still, I only occasionally have a real problem with "table style" formatting forcing me over the limit. Now and then I may need to exercise my judgement and have an entry "sticking out" to the left so it doesn't exceed 100 chars. If I have problems with a long, namespace-qualified name, I'll usually just add a line assigning it to a shorter name. I dislike the cruft of a pointless assignment, but it can be worth it to prevent horizontal spread. (Besides, I'm kinda used to needless definitions in Python, what with the lambda situation, etc)

That's 100 chars, though. 80 chars is more annoying, I admit.

afterthought: it occurs to me that my preference for aligning things does cause me to use more horizontal space - but not more characters - for indirect reasons. I think alignment is the only reason I restrict my self to monospaced fonts in Python. I've tried proportional fonts for Python and they work very well (probably because Python has such a natural language feel). The only real reason I don't use them is because they prevent me from aligning stuff. Of course, that's not directly relevant to a strict n-char limit (but a limit measured in characters is senseless in this context anyway).

I think the worst case for me is when I'm opening a function application far to the right

Code: Select all

# ...indented...
                my_var = some * long ^ expression(with) operators % etc and my_far_right_fn_call(expression + for(arg1), longish & expression * for(arg2), expression + for(arg3), *etc)

You can start the args on a new line, but the default

Code: Select all

# ...indented...
                my_var = some * long ^ expression(with) operators % etc and my_far_right_fn_call(
                    expression + for(arg1),
                    longish & expression * for(arg2),
                    expression + for(arg3),
                    *etc)

separates the args from the function, and if you start them indented from the function name

Code: Select all

# ...indented...
                my_var = some * long ^ expression(with) operators % etc and my_far_right_fn_call(
                                                                                expression + for(arg1),
                                                                                longish & expression * for(arg2),
                                                                                expression + for(arg3),
                                                                                *etc)

it still doesn't give you that much more room. What I usually have to do is break the line further back, but I sometimes have trouble doing it in a way that's nice to read.

* One of several things I hate about PEP8. Honestly, I don't think anyone should care about PEP8 unless they're writing code for the standard library (or somewhere else that uses it). It really only specifies one particular style for coding Python. I don't believe it can be credibly interpreted as "requirements for good style".

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Why Python is the best programming language in the world

Postby EvanED » Sat Sep 21, 2013 5:53 am UTC


User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Why Python is the best programming language in the world

Postby ahammel » Tue Sep 24, 2013 4:16 am UTC


By way of comparison, here is (roughly) the same thing in (probably embarrassingly amateurish) C++.

Code: Select all

// prime_generator.h

#ifndef PRIME_GENERATOR_H
#define PRIME_GENERATOR_H

#include <limits.h>
#include <unordered_map>

using namespace std;

class PrimeGenerator
{
public:
    PrimeGenerator(unsigned long max = ULONG_MAX) : max_value(max) 
    
{
        next_candidate = 2;
    }
    unsigned long next();
private:
    unsigned long next_candidate;
    std::unordered_map<unsigned long, unsigned long> lazy_sieve;
    const unsigned long max_value;
};

#endif /* end of include guard: PRIME_GENERATOR_H */

 


Code: Select all

// prime_generator.cpp

#include <prime_generator.h>
#include <iostream>

unsigned long PrimeGenerator::next()
{
    unsigned long factor;
    unsigned long next_composite;

    if (next_candidate > max_value) {
        throw "Integer overfow!\n";
    }
    
    if 
( !lazy_sieve.count(next_candidate) ) {
        lazy_sieve[next_candidate * next_candidate] = next_candidate;
        return next_candidate++;
    } else {
        factor = lazy_sieve.at(next_candidate);
        next_composite = next_candidate + factor;
        while ( lazy_sieve.count(next_composite) ) {
            next_composite += factor;
        }
        lazy_sieve[next_composite] = factor;
        lazy_sieve.erase(next_candidate);
        ++next_candidate;
        next();
    }
}
 


A few things jump out at me comparing them:
    General readability: Python is a bit better here. I think we can all agree that `if next_candidate in lazy_sieve' is a bit clearer than `if lazy_sieve.count(next_candidate)' (and can I point out that `count' is a pretty stupid name for a method that can only count to one?). The `yield' keyword is very handy for this particular algorithm in Python, but C++ doesn't have that, so I've had to do some slightly evil recursion magic that even the compiler complains about. Also `std::unordered_map<unsigned long, unsigned long> lazy_sieve'. I wrote it, and I can barely remember what the hell all that means.
    Boilerplate: Python wins. Leaving aside the issue of the separation of variable instantiation in C++, there's a bit of language-specific weirdness in the implementation already that doesn't have much to do with the algorithm, particularly the header guard. I know the header guard isn't necessary, but it's a good idea if the program is ever going to be expanded beyond just printing primes.
    Brevity: 42 non-trivial SLOC in the C++ vs 15 in the Python for similar or slightly better readability. Python wins.
    Int management: Python does it automatically, but it's a bit annoying in C++. The Python interpretation also has a slight advantage in that it will run until your exhaust either you memory or your patience, whereas I've had the C++ implementation error out once it gets to 18446744073709551615 rather than suffer an integer overflow. Sorry about that.
    Memory management: perhaps surprisingly it's a tie. I haven't had to do any more explicit memory management in C++ than in the Python implementation, and it's valgrind-pure. I can't say as I understand exactly how everything gets cleaned up in my version, but then I don't understand how the Python garbage collector works either.
    Static typing: I like static typing. C++ wins.
    Strong typing: I like strong typing. Python wins.
    Performance: Uh, yeah. I haven't done any formal benchmarking for time, but unless I've done something horribly stupid (which is quite possible) or the compiler chokes really hard on the recursion, the C++ version is going to be way faster. I did in fact benchmark the memory usage a little bit, and was amused to learn that my implementation has a peak memory usage of about 17.6MB. That sounds a bit high to me, but it's about 10MB less than Python's peak memory allocation just to fire up the interpreter.

So, in sum, some really cool things about Python are: `yield', and generators in general; a nice, compact, expressive syntax; lack of boilerplate; and automatic integer management. In exchange for this, you're giving up a big chunk of performance.
He/Him/His/Alex
God damn these electric sex pants!

User avatar
phlip
Restorer of Worlds
Posts: 7573
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Why Python is the best programming language in the world

Postby phlip » Tue Sep 24, 2013 5:43 am UTC

ahammel wrote:I've had the C++ implementation error out once it gets to 18446744073709551615 rather than suffer an integer overflow. Sorry about that.

ahammel wrote:

Code: Select all

[...]
PrimeGenerator(unsigned long max = ULONG_MAX) : max_value(max)
[...]
if (next_candidate > max_value)
[...]

Yeah... that isn't quite going to do what you hope. "If the value in this unsigned long variable is larger than the maximum value that can be stored in an unsigned long variable..."

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Why Python is the best programming language in the world

Postby Jplus » Tue Sep 24, 2013 6:19 am UTC

ahammel wrote:
    Strong typing: I like strong typing. Python wins.

Wait. C++ and Python are about equally strongly typed?

You could implement Python-style coroutines in C++ using Boost.Context (or perhaps Boost even already has a coroutine library based on that), but that probably would add more boilerplate.

Edit: yes, there's Boost.Coroutine, and yes, it would add boilerplate. Though perhaps not as much as I expected.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Why Python is the best programming language in the world

Postby troyp » Tue Sep 24, 2013 2:01 pm UTC

I was looking at the docs on ABCs (I'm behind on the "new" features and I want to swap to Python3 since most libraries are updated finally). I was excited about the registration method, thinking I could use it to add methods to builtin types, but I can't. In fact, AFAICT, the entire ABC "feature" is just a standardization of stuff you could do all along. I thought there were new features :-(

Oh well, at least I'll have real closures :-) (and some nice syntactic conveniences: set literals, dict comprehensions, class decorators, context aware super,...)

Jplus wrote:Wait. C++ and Python are about equally strongly typed?

Python people always claim Python is "strongly typed". It's pretty much bullshit, of course. They're using a rather dodgy definition of "strongly typed" to mean something like "no implicit type casting".

Traditionally, strongly typed means "no unchecked type errors" or "cannot subvert the type system". But Python only has this form of strong typing with respect to its builtin types: user defined types can be unsafely cast simply by reassigning to the __class__ attribute. If the new and old classes share a method name and one or more attribute names, the new class method may interpret the original data in a way inconsistent with its original meaning (ie. an unchecked type error may occur.)

I suspect a lot of the confusion comes from people misusing "weak typing" to refer to Perl's use of implicit type conversion*. Since Python doesn't do this**, it must be "strongly typed".

* Perl-style casting isn't what I'd call weak typing at all: those conversions are semantically meaningful, eg. 65 -> "65". They're just normal, type-safe functions applied implicitly under certain conditions. Really, the kind of casting that indicates weak typing is a coercion which actually reinterprets the untyped data as a different type, eg. 65-> 'A'.
** Although Python uses operator overloading to convert between numeric types in operations, which ultimately has the same effect as implicit conversion, anyway.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 10 guests