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

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

Why Python is the best programming language in the world

Postby xGeovanni » Wed Sep 04, 2013 8:01 am UTC

Code: Select all

def checkSorted(_list, comparison = operator.le):
   return all([comparison(*x) for x in [(_list[i], _list[i + 1]) for i in range(len(_list) - 1)]])


I invite other examples of Python awesomeness.

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 » Wed Sep 04, 2013 8:32 am UTC

Cute, but why not do it with generator expressions instead of list comprehensions? And if this is Python 2, xrange() is generally preferable to range() although range is probably better for very short ranges.

Code: Select all

def checkSorted(_list, comparison = operator.le):
    return all(comparison(*x) for x in ((_list[i], _list[i + 1]) for i in xrange(len(_list) - 1)))

Also, I'm not exactly thrilled with _list as an identifier...

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 04, 2013 12:07 pm UTC

I'm using Python 3. Really, that's what "Python" should mean by now.

I was under the impression that "all" didn't work with generators. There are so many oddities about what you can and can't do with each of the many different iterable classes in Python. (Why the hell are there all those different ones anyway? Why isn't it just list, tuple and generator?)

I knew "_list" was a bad variable name, but nothing better came to mind.

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 04, 2013 12:46 pm UTC

Code: Select all

def checksorted(alist, comparison=operator.le):
    return all(comparison(alist[i], alist[i + 1]) for i in xrange(len(alist) - 1))


This way you don't create the new list, or the pairs, or use *-magic.
ameretrifle wrote:Magic space feudalism is therefore a viable idea.

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 » Wed Sep 04, 2013 1:22 pm UTC

Nice work, jestingrabbit. Why didn't I think of that? :)

(Maybe inadequate sleep over the last week or so has something to do with it).

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 » Wed Sep 04, 2013 5:02 pm UTC

To be honest... I don't like any of them. They're cute and all, but by shoehorning the problem in the way you're doing it into things like the generator expressions and all that already exist, you make it less general than a straightforward solution you might get in another language, because it requires the sequence supports random access.

I'd prefer just a straightforward implementation:

Code: Select all

class Marker:
    pass

def check_sorted(seq, comp=operator.le):
    marker = first = Marker()
    for second in seq:
        if (first is not marker) and (not comp(first, second)):
            return False
        first = second
    return True


If you really want to be clever and just stitch legos together, maybe something like this:

Code: Select all

def iter_tail(seq):
    it = iter(seq)
    try:
        it.next()
        return it
    except StopIteration:
        return iter(seq)

def check_sorted(seq, comp=operator.le):
    return all(comp(fst, snd) for (fst, snd) in itertools.izip(seq, iter_tail(seq)))

although even that is technically less general: You can't use it on a sequence that you can only pass over once.

Edit: That problem too could be rectified, but at the cost of something that's longer and harder to read than the "boring" implementation:

Code: Select all

class PairedIterator:
    def __init__(self, seq):
        self._iter = iter(seq)
        try:
            self._prev = self._iter.next()
        except StopIteration:
            self._prev = None
    def __iter__(self):
        return self
    def next(self):
        old_prev = self._prev
        self._prev = self._iter.next()
        return (old_prev, self._prev)

def check_sorted(seq, comp=operator.le):
    return all(comp(fst, snd) for (fst, snd) in PairedIterator(seq))

In some ways that's the best solution out of all of them. It's the most general, and it gives you a PairedIterator in case you need it for other stuff. But is the latter benefit enough to make it more complex than the basic version I posted first?

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 04, 2013 5:23 pm UTC

EvanED wrote:

Code: Select all

class Marker:
    pass

...

    marker = first = Marker()



You can't convince me that this is anything but immensely icky and weird.

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 05, 2013 12:12 am UTC

xGeovanni wrote:
EvanED wrote:

Code: Select all

class Marker:
    pass

...

    marker = first = Marker()



You can't convince me that this is anything but immensely icky and weird.
It's really not that bad. Creating an internal type and then an instance of that type that is difficult or impossible for users to access, then using that instance as a sentinel value to distinguish from any user-provided value like None, is quite idiomatic, though usually I've seen it applied to default argument values.

But if you don't like it, you could also do something like

Code: Select all

def check_sorted(seq, comp=operator.le):
    is_first_iteration = True
    for second in seq:
        if (not is_first_iteration) and (not comp(first, second)):
            return False
        is_first_iteration = False
        first = second
    return True

(I'd rename first/second to prev/current because of first/is_first_iteration confusion, then use a shorter name for is_first_iteration, but I figured I'd keep it closer to the original.)

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 05, 2013 3:32 am UTC

Code: Select all

def primes():
  """Prime number generator using Sieve of Eratosthenes."""
  # Instead of crossing off every multiple of a prime up to some bound, we just
  # cross off the next uncrossed multiple of a prime. Crossed off numbers are
  # stored in lazy_sieve, together with the factor, which we can use to figure
  # out the next number to cross off. One new (int: int) pair is stored in each
  # iteration, so when this function yields n, we are using O(n*log(n)) memory.
  lazy_sieve = {}
  next_candidate = 2
  while True:
    if next_candidate not in lazy_sieve:
      # next_candidate is prime. Yield it and cross off its square.
      yield next_candidate
      lazy_sieve[next_candidate * next_candidate] = next_candidate
    else:
      # next_candidate is composite. Cross off the next number.
      factor = lazy_sieve[next_candidate]
      next_composite = next_candidate + factor
      while next_composite in lazy_sieve:
        next_composite += factor
      lazy_sieve[next_composite] = factor
      del lazy_sieve[next_candidate]
    next_candidate += 1


Modified from this recipe.
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
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 » Thu Sep 05, 2013 4:14 am UTC

I appreciate what you say about Marker(), EvanED, but I'm not comfortable with it. But I guess that I could get used to it. I do like your PairedIterator(), though.

I like skeptical scientist's primes generator. It'd be interesting to know how it fares speed-wise; Python dictionaries are pretty fast, but I have found that dict-based algorithms do tend to be a little slower than alternatives.

Here's a simple sieve of Eratosthenes I've used a fair bit. I like it because it uses slice notation to "cross out" composites. And it's very easy to read. :)

Code: Select all

def primes(n):
    ''' Return a boolean list of all primes < n '''
    s = [False]*2 + [True]*(n-2)
    for i in xrange(2, int(n**0.5) + 1):
        if s[i]:
            s[i*i : n : i] = [False] * (1 + (n - 1)/i - i)
    return s

#test
print [i for i,v in enumerate(primes(100))if v]

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 05, 2013 5:39 am UTC

For the "check_sorted" example, EvanED's examples can be cleaned up a fair bit with more use of itertools...

Code: Select all

def checksorted(seq, comp=operator.le):
  left, right = itertools.tee(seq, 2)
  return all(comp(a, b) for (a, b) in itertools.izip(left, itertools.islice(right, 1, None)))
That said, if the lists weren't too long, and I wasn't too worried about performance, I'd probably for readability write it as:

Code: Select all

def checksorted(seq, comp=operator.le):
  xs = list(seq)
  return all(comp(a, b) for (a, b) in zip(xs, xs[1:]))

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 05, 2013 5:44 am UTC

Yours is significantly faster:
To generate all primes less than 100, skepsci's algorithm took 0.061000 milliseconds while PM 2Ring's algorithm took 0.025000 milliseconds.
To generate all primes less than 1000, skepsci's algorithm took 0.640000 milliseconds while PM 2Ring's algorithm took 0.037000 milliseconds.
To generate all primes less than 10000, skepsci's algorithm took 6.603000 milliseconds while PM 2Ring's algorithm took 0.267000 milliseconds.
To generate all primes less than 100000, skepsci's algorithm took 70.966000 milliseconds while PM 2Ring's algorithm took 3.653000 milliseconds.
To generate all primes less than 33554432, skepsci's algorithm took 33833.623000 milliseconds while PM 2Ring's algorithm took 2721.861000 milliseconds.


Interestingly, your algorithm seems to perform best relative to mine when n is around 15,000. For larger n, my algorithm starts to catch up, although I could only test up to around 60,000,000 at which point your algorithm was still more than 12 times as fast.

Spoiler:
For 2**2, PM 2Ring's algorithm was faster by a factor of 1.000000.
For 2**3, PM 2Ring's algorithm was faster by a factor of 1.600000.
For 2**4, PM 2Ring's algorithm was faster by a factor of 1.125000.
For 2**5, PM 2Ring's algorithm was faster by a factor of 3.000000.
For 2**6, PM 2Ring's algorithm was faster by a factor of 3.800000.
For 2**7, PM 2Ring's algorithm was faster by a factor of 4.117647.
For 2**8, PM 2Ring's algorithm was faster by a factor of 8.000000.
For 2**9, PM 2Ring's algorithm was faster by a factor of 7.155556.
For 2**10, PM 2Ring's algorithm was faster by a factor of 6.359223.
For 2**11, PM 2Ring's algorithm was faster by a factor of 18.885714.
For 2**12, PM 2Ring's algorithm was faster by a factor of 22.512000.
For 2**13, PM 2Ring's algorithm was faster by a factor of 24.646789.
For 2**14, PM 2Ring's algorithm was faster by a factor of 26.507426.
For 2**15, PM 2Ring's algorithm was faster by a factor of 24.791523.
For 2**16, PM 2Ring's algorithm was faster by a factor of 21.086084.
For 2**17, PM 2Ring's algorithm was faster by a factor of 23.471206.
For 2**18, PM 2Ring's algorithm was faster by a factor of 18.404067.
For 2**19, PM 2Ring's algorithm was faster by a factor of 16.037602.
For 2**20, PM 2Ring's algorithm was faster by a factor of 16.211311.
For 2**21, PM 2Ring's algorithm was faster by a factor of 15.170212.
For 2**22, PM 2Ring's algorithm was faster by a factor of 14.599662.
For 2**23, PM 2Ring's algorithm was faster by a factor of 13.893406.
For 2**24, PM 2Ring's algorithm was faster by a factor of 13.876389.
For 2**25, PM 2Ring's algorithm was faster by a factor of 14.488746.
For 2**26, PM 2Ring's algorithm was faster by a factor of 12.537016.


Comparison code:

Code: Select all

import time

def compare_times(n):
  t_0 = time.clock()
  for p in primes():
    if p > n: break
  t_1 = time.clock()
  primes2(n)
  t_2 = time.clock()
  return (n, t_1 - t_0, t_2 - t_1)

def print_times(n, t_1, t_2):
  print ("To generate all primes less than %d, skepsci's algorithm took %f "
         "milliseconds while PM 2Ring's algorithm took %f milliseconds." %
         (n, 1000 * t_1, 1000 * t_2))

def print_ratio(n, t_1, t_2):
  print ("To generate all primes less than %d, PM 2Ring's algorithm was faster "
         "by a factor of %f." % (n, t_1 / t_2))

The advantage of mine is really that it's unbounded. Yours is much faster if you want all primes less than a specific bound which you know ahead of time, whereas the purpose of mine is to be an unbounded generator. I'm not sure how much of the speed difference is because when your algorithm computes primes(n), it only ever bothers considering numbers less than n, while by the time my algorithm has finished generating all primes below n, it's already started marking composites larger than n, because it needs to store enough state to keep going.
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
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 » Thu Sep 05, 2013 6:21 am UTC

phlip wrote:For the "check_sorted" example, EvanED's examples can be cleaned up a fair bit with more use of itertools...

Code: Select all

def checksorted(seq, comp=operator.le):
  left, right = itertools.tee(seq, 2)
  return all(comp(a, b) for (a, b) in itertools.izip(left, itertools.islice(right, 1, None)))
That said, if the lists weren't too long, and I wasn't too worried about performance, I'd probably for readability write it as:

Code: Select all

def checksorted(seq, comp=operator.le):
  xs = list(seq)
  return all(comp(a, b) for (a, b) in zip(xs, xs[1:]))

Groovy, phlip! I really ought to familiarise myself with itertools... and I probably should install Python 2.7, even though it's not in the stable Debian repos. I did consider the zip(xs, xs[1:]) technique earlier, but decided against it due to the list duplication. OTOH, I often sacrifice memory for speed in Python.

...

skeptical scientist wrote:Yours is significantly faster:

[...]

The advantage of mine is really that it's unbounded. Yours is much faster if you want all primes less than a specific bound which you know ahead of time, whereas the purpose of mine is to be an unbounded generator. I'm not sure how much of the speed difference is because when your algorithm computes primes(n), it only ever bothers considering numbers less than n, while by the time my algorithm has finished generating all primes below n, it's already started marking composites larger than n, because it needs to store enough state to keep going.


Thanks for doing the speed tests, skepsci. But yeah, it's not really fair to compare a fixed length list maker with a proper generator. Although I like unbounded generators I've found that they can be noticeably slower than non-generator algorithms: once again, it's the old memory vs CPU time trade-off, and I guess there's a fair bit of overhead in what the interpreter has to do when handing the yield statement.

I suspect that a significant reason for the non-linear speed difference in our algorithms is due to the internal mechanics of Python dictionaries, especially the way it handles hash key collisions.


Sometimes, it can be useful to generate numbers that are probably prime, eg when doing prime factorisation, it's not necessary to ensure that all the candidate factors are prime. I use the following generator in my Gaussian integer factorisation program:

Code: Select all

def potential_primes():
    ''' Make a generator for 2, 3, 5, & thence all numbers coprime to 30 '''
    s = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
    for i in s:
        yield i
    s = (1,) + s[3:]
    j = 30
    while True:
        for i in s:
            yield j + i
        j += 30



And a simpler version that doesn't screen out multiples of 5:

Code: Select all

def potential_primesA():
    ''' Make a generator for 2, 3, 5 & thence all numbers coprime to 6 '''
    for i in (2, 3, 5):
        yield i
    j = 6
    while True:
        yield j + 1
        yield j + 5
        j += 6

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 05, 2013 6:55 am UTC

PM 2Ring wrote:I really ought to familiarise myself with itertools...

To be fair, I'm not super familiar with it myself... whenever I think to use it, I always have to pull up the docs for it. But then, that's why docs exist. And just knowing that itertools and functools exist goes a long way.

Code: Select all

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

User avatar
Qaanol
The Cheshirest Catamount
Posts: 3069
Joined: Sat May 09, 2009 11:55 pm UTC

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

Postby Qaanol » Thu Sep 05, 2013 2:58 pm UTC

So, as someone unfamiliar with Python, here is what I have gleaned from this thread:

In Python there are numerous ways to accomplish simple tasks, using many different functions and classes that require knowing lots of different keywords and syntax.

It is not always obvious, even to people who are familiar with the language, what all the different approaches to a problem are, not even all the simple approaches.

Nor is it obvious which methods are fastest or use the least memory, and determining those things requires carrying out many tests of each of the large number of possible implementations, using a wide range of input values.
wee free kings

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 05, 2013 3:03 pm UTC

See also: every language ever, that any sort of respectable set of libraries? I'm really not sure what your point is, here...

What language are you using for comparison, here?

Code: Select all

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

Breakfast
Posts: 117
Joined: Tue Jun 16, 2009 7:34 pm UTC
Location: Coming to a table near you

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

Postby Breakfast » Thu Sep 05, 2013 6:38 pm UTC

Qaanol, please feel free to correct me or shout at me if I'm wrong but I think that his point was just that. It's just like every other language. The title of the thread is making a ridiculous claim based on a piece of code that can be reproduced more succinctly in other languages or implemented in a multitude of ways in Python.

User avatar
Qaanol
The Cheshirest Catamount
Posts: 3069
Joined: Sat May 09, 2009 11:55 pm UTC

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

Postby Qaanol » Thu Sep 05, 2013 7:12 pm UTC

Breakfast wrote:Qaanol, please feel free to correct me or shout at me if I'm wrong but I think that his point was just that. It's just like every other language. The title of the thread is making a ridiculous claim based on a piece of code that can be reproduced more succinctly in other languages or implemented in a multitude of ways in Python.

Yeah, when I saw the thread title I was expecting examples of elegant solutions for problems that would be more complicated or difficult to solve in other languages, thus providing reasons for a person like myself to learn this language. That did not happen.
wee free kings

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 05, 2013 7:18 pm UTC

PM 2Ring wrote:
phlip wrote:For the "check_sorted" example, EvanED's examples can be cleaned up a fair bit with more use of itertools...[code]def checksorted(seq, comp=operator.le):
...

Groovy, phlip!
That is groovy, and I do like them.

I even took a quick look through itertools when I was writing my iter_tail function to see if it had anything like that, but I was too much in the ML/Haskell mindset and looking for things named like "tail" or "rest".

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 06, 2013 6:14 am UTC

Qaanol wrote:So, as someone unfamiliar with Python, here is what I have gleaned from this thread:

In Python there are numerous ways to accomplish simple tasks, using many different functions and classes that require knowing lots of different keywords and syntax.

It is not always obvious, even to people who are familiar with the language, what all the different approaches to a problem are, not even all the simple approaches.

Nor is it obvious which methods are fastest or use the least memory, and determining those things requires carrying out many tests of each of the large number of possible implementations, using a wide range of input values.


What phlip said about libraries.

Also, feature creep. Thus the code in the OP uses list comprehensions, a construction from early Python to quickly create and populate a list. Much later, the generator expression was introduced, which has very similar syntax to the list comprehension (which is handy when modifying old code). A generator expression creates an iterator function: i.e., a function that returns the next item in a (potentially) infinite list each time it's called. Lots of old example code uses list comprehensions that could be re-written to use generator expressions, so it's not unusual to see Python programmers (both old-timers & newbies) using list comprehensions when they probably should be using generator expressions instead.

Python is an interpreted language, so it can be a little tricky to guess what's the fastest way to do a particular task, since a chunk of native Python code may run slower than equivalent code that calls a library routine (or built-in function) written in C.

Python comes with a whole stack of standard modules (libraries), plus there are tons of 3rd party libraries available. Many of these libraries provide very efficient routines written in C, but some of them are written in Python, so they don't provide a speed advantage over hand-written code. Most Python programmers soon get a rough idea of what's available in the most frequently-used libraries, but you don't always go searching through the library docs looking for a function when you can write equivalent code in a handful of lines yourself, unless you really need to make the code run as fast as possible.

OTOH, if typical Python run speed is not good enough, you may end up using the Python version as a rough prototype & re-write the whole thing in C, or at least write some of the critical portions in C. Of course, if you intend to follow that strategy, then your Python version will probably stick fairly closely to C-like syntax & avoid such Pythonic constructions as list comprehensions & generator expressions.

...

Qaanol wrote:
Breakfast wrote:Qaanol, please feel free to correct me or shout at me if I'm wrong but I think that his point was just that. It's just like every other language. The title of the thread is making a ridiculous claim based on a piece of code that can be reproduced more succinctly in other languages or implemented in a multitude of ways in Python.

Yeah, when I saw the thread title I was expecting examples of elegant solutions for problems that would be more complicated or difficult to solve in other languages, thus providing reasons for a person like myself to learn this language. That did not happen.


When I first saw the thread title, I thought "Uh-oh! Shouldn't this be in Religious Wars?". I love Python, but it certainly isn't flawless. OTOH, what language is?

Hopefully, this thread will evolve to give examples of elegant solutions for problems that illustrate the power of Python... or at least the tendency of Python syntax to look cleaner than that of most other languages. :)

User avatar
WarDaft
Posts: 1583
Joined: Thu Jul 30, 2009 3:16 pm UTC

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

Postby WarDaft » Fri Sep 06, 2013 10:23 pm UTC

Hopefully, this thread will evolve to give examples of elegant solutions for problems that illustrate the power of Python... or at least the tendency of Python syntax to look cleaner than that of most other languages.
Indeed, right now it's almost the opposite.
All Shadow priest spells that deal Fire damage now appear green.
Big freaky cereal boxes of death.

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 » Sat Sep 07, 2013 12:16 am UTC

For me one of the best parts of python is that you can swap variables in one line:

Code: Select all

a, b = b, a


You can use this, for example, to build a simple fibonacci generator:

Code: Select all

def fibo():
    a = b = 1
    while True:
        yield a
        a, b = b, a + b

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 » Sat Sep 07, 2013 9:08 pm UTC

EvanED wrote:It's really not that bad. Creating an internal type and then an instance of that type that is difficult or impossible for users to access, then using that instance as a sentinel value to distinguish from any user-provided value like None, is quite idiomatic, though usually I've seen it applied to default argument values.
Since you're using "is" comparison, you can just use object() for this. There's no need for the class to be hidden from users, since they would have to somehow pass the actual instance you're using a sentinel to screw things up.

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 » Sat Sep 07, 2013 11:29 pm UTC

Ok so how do you even run the first program? It gives an error about opeator.le not existing, even if I import operator. Honestly I can't really make sense of that program anyway, which is not a good sign for a language.

Just for fun I also tried running PM 2Ring's algorithm.

PM 2Ring wrote:

Code: Select all

def primes(n):
    ''' Return a boolean list of all primes < n '''
    s = [False]*2 + [True]*(n-2)
    for i in xrange(2, int(n**0.5) + 1):
        if s[i]:
            s[i*i : n : i] = [False] * (1 + (n - 1)/i - i)
    return s

#test
print [i for i,v in enumerate(primes(100))if v]


Result:

Code: Select all

  File "primes.py", line 10
    print [i for i,v in enumerate(primes(100))if v]
               ^
SyntaxError: invalid syntax

Ah yes, PM 2Ring's algorithm is written for an older version of python. I can fix that, put () around the print statement, run again

Code: Select all

Traceback (most recent call last):
  File "primes.py", line 10, in <module>
    print ([i for i,v in enumerate(primes(100))if v])
  File "primes.py", line 4, in primes
    for i in xrange(2, int(n**0.5) + 1):
NameError: global name 'xrange' is not defined

Ah yes, xrange is deprecated as well. Let's fix that too, remove the x.

Code: Select all

Traceback (most recent call last):
  File "primes.py", line 10, in <module>
    print ([i for i,v in enumerate(primes(100))if v])
  File "primes.py", line 6, in primes
    s[i*i : n : i] = [False] * (1 + (n - 1)/i - i)
TypeError: can't multiply sequence by non-int of type 'float'

Ok I have no idea what that means, and in the time it will take me to figure that out, I can probably write this algorithm in c++ as well.

Seriously people, I actually do love python as a language, but this thread is seriously not helping Python's case.
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

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 » Sun Sep 08, 2013 12:04 am UTC

Diadem wrote:Ok so how do you even run the first program? It gives an error about opeator.le not existing, even if I import operator.
What version of Python? Works fine for me with both 2.7 and 3.3:

Code: Select all

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import operator
>>> def checkSorted(_list, comparison = operator.le):
...    return all([comparison(*x) for x in [(_list[i], _list[i + 1]) for i in range(len(_list) - 1)]])
...
>>> checkSorted([1,2,3])
True
>>> checkSorted([1,2,3,1])
False

Python 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:06:53) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import operator
>>> def checkSorted(_list, comparison = operator.le):
...    return all([comparison(*x) for x in [(_list[i], _list[i + 1]) for i in range(len(_list) - 1)]])
...
>>> checkSorted([1,2,3])
True
>>> checkSorted([1,2,3,1])
False


Ok I have no idea what that means, and in the time it will take me to figure that out, I can probably write this algorithm in c++ as well.
It needs an int(...) around 1 + (n - 1)/i - i, because division results in a floating point instead of integer in Python 3.

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 » Sun Sep 08, 2013 9:34 am UTC

EvanED wrote:It needs an int(...) around 1 + (n - 1)/i - i, because division results in a floating point instead of integer in Python 3.

Or just change the / to // to get an integer division (really should be using that explicitly, even in Python 2, when you need integer division).

Code: Select all

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

alessandro95
Posts: 109
Joined: Wed Apr 24, 2013 1:33 am UTC

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

Postby alessandro95 » Sun Sep 08, 2013 6:17 pm UTC

What if python isn't the best programming language in the world?

I don't want to start a religious war but Lua can do most of the things python does, but faster and with a much smaller interpreter!
Of course it cannot do everything python does, especially when it comes to maths computations, and it doesn't have nearly any library included in the standard package but it has a lot to offer, including generators, associative arrays, object oriented paradigm (though prototype based*), very flexible and easy to read syntax, trivial C interface, multiple threading, fast interpreter, a very clean source code easy to modify by yourself and much more! A google search for "Lua vs Python" will find a lot of interesting websites, including the lua-users wiki and a stackoverflow question, that last one especially brings up a good point: you cannot decide how good a language is out of context, you need a task, then you can choose which language is the best for doing it. Do you need a fast scripting language for your C/C++ videogame? Then you'd better go for Lua, not python. Are you doing some projecteuler problems (first example of maths stuff that came to my mind)? Then I'd rather suggest python over Lua, but I think there are other languages even more suited than python for this kind of stuff.

*edit: That was not entirely true. Lua doesn't provide native support for OOP, but you can easily write your own prototype or class system in a few lines thanks to metatables and metamethods, as I said Lua is extremely flexible, you can choose how to do OOP in the way you prefer or you can choose as well that you don't want any object and simply don't use them
The primary reason Bourbaki stopped writing books was the realization that Lang was one single person.

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 » Sun Sep 08, 2013 11:13 pm UTC

Just a note that if this thread moves from being an excuse to share neat Python snippets to being an actual discussion of "the best programming language in the world", then it's getting moved to RW. Not saying you can't go down that road... but just putting that out there.

Code: Select all

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

alessandro95
Posts: 109
Joined: Wed Apr 24, 2013 1:33 am UTC

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

Postby alessandro95 » Mon Sep 09, 2013 5:38 am UTC

phlip wrote:Just a note that if this thread moves from being an excuse to share neat Python snippets to being an actual discussion of "the best programming language in the world", then it's getting moved to RW. Not saying you can't go down that road... but just putting that out there.


As I said I didn't want to start a RW, actually I didn't even want to claim Lua (or any other language) better then python, because it is a pointless discussion, just as pointless as claiming python the best language in the world.
I misunderstood what the aim of this thread was, probably with a title like "why we love python" or "why is python a great programming language" I wouldn't have written my previous post, sorry!
The primary reason Bourbaki stopped writing books was the realization that Lang was one single person.

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 » Mon Sep 09, 2013 7:52 am UTC

phlip wrote:
EvanED wrote:It needs an int(...) around 1 + (n - 1)/i - i, because division results in a floating point instead of integer in Python 3.

Or just change the / to // to get an integer division (really should be using that explicitly, even in Python 2, when you need integer division).


Thanks, phlip. I normally do use explicit // for integer division, but I slipped up on that one. My excuse is that I C&P'd the s[i*i : n : i] = [False] * (1 + (n - 1)/i - i) line 5 years ago from someone else's code (possibly from this very forum).

:oops:

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 » Wed Sep 11, 2013 11:21 am UTC

Sorry, couldn't help it. It is not my intention to turn this into RW, nor to make any claims about the greatness of Python.

Code: Select all

template <class fwditer>
bool is_sorted (fwditer first, fwditer last) {
    return adjacent_find(first, last, greater<decltype(*first)>()) == last;
}


Edit: == instead of !=.
"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 13, 2013 7:28 am UTC

If I wanted check_sorted to work on any iterable, I'd probably use a straightforward imperative solution (I'd use skeptical's function for lists):

Code: Select all

import operator

def check_sorted(itbl, op=operator.le):
   iterator = iter(itbl)
   x1 = next(it)
   for x2 in iterator:
      if not op(x1,x2): return False
      x1 = x2
   return True
It's verbose, but I find using itertools functions often makes for cluttered code - there aren't enough of them, so you always have to fuck around too much.
Spoiler:
What I'd really do is use an iterator function of my own, like this:

Code: Select all

def check_sorted(ls, op=operator.le):
   return all(op(*t) for t in window(ls, 2))

where window is probably self-explanatory:

Code: Select all

def window(it, k):
   # unoptimized - probably no good for large k (deque for large k? all k?)
   it = iter(it)
   items = []
   for i in range(k):
      items.append(next(it))
   while True:
      yield tuple(items)
      items = items[1:]
      items.append(next(it))


Code: Select all

class Marker:
    pass

def check_sorted(seq, comp=operator.le):
    marker = first = Marker()
    # <snip>
If I need a sentinel/special value, I usually just use

Code: Select all

marker = object()
I'd only make a class for it in a more complicated situation (eg. if I had multiple markers at once.) Using object is really concise, but also, if you think about it, it's pretty appropriate for this purpose. After all, all the object class does by itself is create unique objects - and that's precisely what you want for creating a sentinel.

I'm surprised some people don't like this. Sentinels are pretty widespread, and if you want to use one in a heterogeneous collection, the only way to be sure it can't be an element (without placing the burden on the user) is to use a unique, internally-created object. Of course, if the collection is indexable, you'd likely just use an index, and if you have information about what kind of elements can occur, you might be able to use some existing value (like None), but in the general case, you really need to make your own. I'm curious what people would do instead?

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 » Fri Sep 13, 2013 2:59 pm UTC

troyp wrote:(I'd use skeptical's function for lists)

I don't think I wrote one. Are you thinking of one of EvanED's posts?

Code: Select all

def window(it, k):
   # unoptimized - probably no good for large k (deque for large k? all k?)
   it = iter(it)
   items = []
   for i in range(k):
      items.append(next(it))
   while True:
      yield tuple(items)
      items = items[1:]
      items.append(next(it))


I like how this never actually raises StopIteration, just waits for the underlying iterator to raise it.

Imo this thread would be more interesting if people would stop talking about how to check whether a list is sorted, and instead show off some other cool python features with interesting applications.
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

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 13, 2013 10:54 pm UTC

skeptical scientist wrote:I don't think I wrote one. Are you thinking of one of EvanED's posts?

I was thinking of jestingrabbit's solution, sorry. (I had the impression of "a math person visiting from another forum" and attached it to you - I know you're regularly in AE now, but I still kind of think of you as belonging to the science fora.)

I like how this never actually raises StopIteration, just waits for the underlying iterator to raise it.

Yeah, I like that as well. I've noticed this when I've written other iterator functions: StopIteration makes them quite clean to write. Often you can completely ignore finite iterators and everything will work out (since the first argument iterator that runs out will finish your iterator as well.) Yield statements are also really elegant for writing imperative style code for generators.

Imo this thread would be more interesting if people would stop talking about how to check whether a list is sorted, and instead show off some other cool python features with interesting applications.

Personally I like Python because it is (at its best) beautifully uncluttered and readable, is dynamic (handy for a convenient go-to language) has plenty of mature libraries and is just powerful enough to be usable. I think it has a lot of lacks (no macros, no optional braces syntax*, lack of inline callables, no TCO, no monkeypatching, etc, etc), but it does have enough powerful features that most of the time, it doesn't hamper me too severely.

One of the best things is the descriptor interface which allows you to customize attribute access. This, combined with first-class functions, first-class classes, special methods for overloading operators/indexing/application/etc and metaclasses, means you can do virtually anything you want with classes.

Iterators and generators are also handled nicely, and becoming more and more useful as time goes on. (My only complaint is that with more and more things returning iterators, it's becoming annoying in the really simple cases - especially interactive use - having to call list() to convert them.)

Even decorators I like, despite myself. They're a bit of a sore spot for me. I mean, the lack of proper lambdas was causing such a hassle that new syntax was needed to remedy it...but did Guido introduce lambda syntax? No...he introduced a much more limited mechanism that would fix his problem (mymethod = classmethod(mymethod) at the very end of a long method) without putting too much flexibility in the hands of users. Still, although they're an example of pigheadedness, they're also an example of clean syntax design. Yes, decorators are equivalent to a special case of lambdas, but they also introduce a useful syntactic sugar that makes code more readable**. In many cases

Code: Select all

@decorator
def foo(args):
    code

is nicer than

Code: Select all

foo = decorator(
    (lambda args:
        code))
(I've just used a straightforward lambda syntax for illustration - I don't know if it's even unambiguous)
Mind you, it can be a bit weird when you're using def to define something that's not even a function...

* I have to admit, as annoying as lack of brace syntax is, there is probably some justification to omitting it. I'd like to say that no-one would abuse it (I mean, Haskell has brace syntax, but you don't see it being used willy-nilly.) But realistically, Python's target users are quite different from Haskell's, and the amount of complaining you hear because Python doesn't look like Java... I wouldn't be surprised if it became quite common to use braces by default.
** One thing that would be nice is the option for an indent following the decorator. Having them at the same level is fine if there's a blank line preceding, but if there isn't the decorator tends to visually dissociate from its target.


PS.
I tried to find something cool to post to illustrate some of Python's features, but everything I look at seems pretty pedestrian. So I'll end with a cute syntax hack instead. It only really uses special methods (and inner classes), but I find it amusing...

Code: Select all

class Switch(object):
    def __init__(self, expr):
        self.expr = expr
    def __iter__(self):
        return iter([Switch.Case(self.expr)])
    class Case(object):
        def __init__(self, expr):
            self.expr = expr
            self.result = None
        def __call__(self, val):
            if self.expr == val:
                return Switch.CaseHandler(self, True)
            else:
                return Switch.CaseHandler(self, False)
    class CaseHandler(object):
        def __init__(self, case_instance, success):
            self.case_instance = case_instance
            self.success = success
        def __rshift__(self, result):
            if self.success:
                self.case_instance.result = result


example:

Code: Select all

x = 3
for case in Switch( x*x*x + x + 1 ):
    case(29) >>  "A"
    case(30) >>  "B"
    case(31) >>  "C"
    case(32) >>  "D"
print case.result

Derek
Posts: 2181
Joined: Wed Aug 18, 2010 4:15 am UTC

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

Postby Derek » Sat Sep 14, 2013 5:17 pm UTC

troyp wrote:no monkeypatching,

You can monkey patch in python. In fact, I think I read somewhere that the term originates from python. Classes are objects like any other, and new methods can be assigned to it or old methods replaced. However, it's not considered Pythonic, so it's use is discouraged.

Code: Select all

>>> class Foo:
...   pass
...
>>> foo = Foo()
>>> Foo.bar = lambda self: print("Hello")
>>> foo.bar()
Hello

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 » Sun Sep 15, 2013 12:30 am UTC

I misused the word. I should have said "no monkeypatching of built-in classes". (I first heard the term in reference to Ruby's ability to add/change core class methods and I still associate it with that. Plus, monkey patching in general I just think of as part of being a dynamic language, so I barely even notice it...until it doesn't work for something.)

Outside of the REPL, I rarely need to change a class's members at runtime outside of the class's intended interface*. If I want to change something in a user-defined class I'd normally subclass it (or create a class that delegates to it). Usually when I really wish I had monkeypatching, it's because I want to change core types where subtyping or delegation wouldn't work, like adding a property to every integer literal.

* I used to sometimes add attributes to functions (for metadata, configuration or persistent state when I didn't want to bother with a closure and it wasn't natural to use a mutable default arg.) I rarely seem to do it lately, though.

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 » Sun Sep 15, 2013 10:19 am UTC

It seems to me that the fact that Python has monkeypatching kind of proves the falseness of the thread title. Not that monkeypatching isn't an awesome feature of course, but it's something that necessarily slows your language the fuck down, and greatly reduces the readability of your code, making large code bases problematic.

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 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 » Sun Sep 15, 2013 3:53 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.

I don't adhere to the position that Python is the best programming language myself, but I think you're giving Python way too little credit with that statement. The standard libraries make Python very useful as a general-purpose programming language. The language itself is also very mature. You have to rely on the C language bindings (with libraries like numpy) if you want to do any significant number crunching and the efficiency doesn't scale to very large applications, but apart from that it's definitely an all-round language.

Of course it depends on what you mean by "scripting language", but unless your definition is "any dynamically typed language is a scripting language and this automatically excludes it from being a programming language", I think there's not much truth in what you said.

(Also, as far as I can tell this thread isn't about the question whether Python is actually the best, but about how people like to express their affinity with the language. This is not the religious wars forum!)
"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 » Mon Sep 16, 2013 4:07 am UTC

@ troyp

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.

lunar
Posts: 5
Joined: Fri May 18, 2012 2:18 am UTC

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

Postby lunar » Mon Sep 16, 2013 4:23 am UTC

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/

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).


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 10 guests