Live data from Hacker News

Python and the Principle of Least Astonishment

lucumr.pocoo.org

1–10 of 53 posts

Re: Python and the Principle of Least Astonishment

#2
Differentiating properties and methods from internal methods is as simple as using another char, like dots and colons. So box.length would not be the same as box:length, that way you could assign all names you want without fear of collision. Poor choices in language design will always haunt you til the end of times.

That being said, python is my favorite language right now and the only complain I have is about underscores which I try to avoid.

Now, GO being a new language, I can't really understand why it does not implement methods for primitive types like "hello".ToUpper(), instead we have to import "strings" and call strings.ToUpper("hello").

Easier for the compiler but harder for the programmer has never been my mantra.

Re: Python and the Principle of Least Astonishment

#3

Differentiating properties and methods from internal methods is as simple as using another char, like dots and colons. So box.length would not be the same as box:length, that way you could assign all names you want without fear of collision. Poor choices in language design will always haunt you til the end of times. That being said, python is my favorite language right now and the only complain I have is about unders…

I'm not sure about different namespaces for special methods. Python's object system is so self-referential and so transparent that it'd be surprising.

Go devs are of the opinion that what behaves like a function should be a function, with no exception. It's also the reason they don't do operator overloading, which I think is just dumb.

Re: Python and the Principle of Least Astonishment

#4
For extra fun....

  a = 5
  def print_a():
      print a
  # Prints 5
  print_a()
  
  def print_and_assign_a():
      print a
      a = 2
  # raises UnboundLocalError
  print_and_assign_a()
  
  class PrintOnInitSet(set):
      def __init__(self, *args, **kwargs):
          print "init!"
          set.__init__(self, *args, **kwargs)
  # Creates a PrintOnInitSet and prints "init!"
  a = PrintOnInitSet([1,2])
  # Creates a PrintOnInitSet and prints "init!"
  b = PrintOnInitSet([3,4])
  # Creates a PrintOnInitSet and prints nothing
  c = a | b

Re: Python and the Principle of Least Astonishment

#5
I miss something like the Principle of Least Astonishment for design.

Why every time there's a revamp of a website the new design is more astonishing and less clear? Why the search button in Google Calendar is now blue?

Why new design is usually a tease on our muscle memory?

Re: Python and the Principle of Least Astonishment

#6
This is a nice article, as a non-Python programmer who's dabbled a bit in order to read some random Python code, it gave me some appreciation for the "Pythonic"-way.

I have to say though, that the thing that astonished me the most about Python is the Java-like "closures". I sort of thought it would be like Ruby, which I thought was closer to Scheme and JavaScript, and then I realized that Ruby isn't quite like them either. (I know Ruby is close with its lambdas and blocks, but it's not intuitive to me.)

This isn't necessarily to the detriment of Python (or Ruby) but just something I observed when trying to explain Java's lack of closures to someone who only knows Python.

Re: Python and the Principle of Least Astonishment

#8

This is a nice article, as a non-Python programmer who's dabbled a bit in order to read some random Python code, it gave me some appreciation for the "Pythonic"-way. I have to say though, that the thing that astonished me the most about Python is the Java-like "closures". I sort of thought it would be like Ruby, which I thought was closer to Scheme and JavaScript, and then I realized that Ruby isn't quite like them e…

I have only a trivial amount of experience experience with Scheme, could you explain how its closures are different from Python's?

I haven't used Java a lot either, but from what I have done Python's function seems more similar to JavaScript than to Java.

Re: Python and the Principle of Least Astonishment

#9

This is a nice article, as a non-Python programmer who's dabbled a bit in order to read some random Python code, it gave me some appreciation for the "Pythonic"-way. I have to say though, that the thing that astonished me the most about Python is the Java-like "closures". I sort of thought it would be like Ruby, which I thought was closer to Scheme and JavaScript, and then I realized that Ruby isn't quite like them e…

Python has Java like closures? No comprende.

Re: Python and the Principle of Least Astonishment

#10

For extra fun.... a = 5 def print_a(): print a # Prints 5 print_a() def print_and_assign_a(): print a a = 2 # raises UnboundLocalError print_and_assign_a() class PrintOnInitSet(set): def __init__(self, *args, **kwargs): print "init!" set.__init__(self, *args, **kwargs) # Creates a PrintOnInitSet and prints "init!" a = PrintOnInitSet([1,2]) # Creates a PrintOnInitSet and prints "init!" b = PrintOnInitSet([3,4]) # Crea…

Well, your first example makes sense. It ensures you're always referring to the same-scoped 'a' throughout your function. FWIW if you said 'global a' at the start of 'print_and_assign_a', Python wouldn't have a problem:

    >>> a = 5
    >>> def print_and_assign_a():
    ...     global a
    ...     print(a)
    ...     a = 2
    ... 
    >>> print_and_assign_a()
    5
    >>> print_and_assign_a()
    2
Your second example, however, seems to show an implementation detail of Python leaking out, and is probably a bug. Union starts off by making a copy of 'a' and adds the elements of 'b' to it, rather than creating a new object and adding the elements of both.

On a hunch that PyPy's implementation would be less special-cased, I installed PyPy and and it actually does print "Init!" on "c = a | b". So, I vote bug in CPython rather than an inconsistency in the language.

One more question arises, however. Should "a = set([1,2])" be equivalent to "a = set(); a.add(1); a.add(2)"? I overloaded 'add' on your PrintOnInitSet and it's not:

    >>>> a = PrintOnInitSet(); a.add(1); a.add(2)
    init!
    Called add with item: 1
    Called add with item: 2
    >>>> a = PrintOnInitSet([1,2])
    init!
Post reply on HN