5 ms·
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"
by spacemanaki 15y ago
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.
- JeremyBanks 15y agoI 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.
- irahul 15y ago> I have only a trivial amount of experience experience with Scheme, could you explain how its closures are different from Python's? In pre Python 3, the closed over value isn't mutable unless it's a reference to a mutable object. def counter(num): def foo(): num += 1 return num return foo c = counter(5) c() This won't work because you can't mutate the closed variable `start`. This would work in languages with proper closures(Ruby, Perl, Scheme...). Here is how you do it in Ruby: def counter(n) lambda { n += 1 } end c = counter(5) c[] # returns 6 c.call() # Alternate syntax. returns 7 c[] # returns 8 The above python will work in Python 3 if the closed variable is declared `nonlocal`. def counter(num): def foo(): nonlocal num num += 1 return num return foo Or you can have workarounds in pre Python3. def counter(num): def foo(): foo.num += 1 return foo.num foo.num = num return foo
- kbd 15y agoI dunno if I'd say that's an issue of Python not having proper closures, or just that before you could say 'nonlocal' there was no way to refer to the outer scope, since the only scopes you could refer to were 'local' and 'global'.
- deleted 15y ago[deleted]
- irahul 15y ago> In pre Python 3, the closed over value isn't mutable unless it's a reference to a mutable object. > Proper closures were added in Python 2.2 (which is quite old at this point), not Python 3. x is a reference to a mutable object(list), and it's not x which is mutated but what x refers to. Pre python 3 doesn't have proper closures - ways to emulate it, yes. Proper closures - no.
- bobbyi 15y agoPython has had proper closures since version 2.2, which is quite old at this point. You can verify this using the following code: def func(): x = [] def func2(): x.append(1) return x return func2 closed = func(); closed(); assert closed() == [1,1] closed = func(); closed(); assert closed() == [1,1]
- spacemanaki 15y agoThat's what I was referring to as "Java closures".
- MostAwesomeDude 15y agoPython closes over names, not objects. This is consistent with the rest of Python, which treats names as references to objects rather than variables which hold objects. I do agree that it's confusing for people used to closures and used to languages with different semantics.
- peteretep 15y ago
- kingkilr 15y agoPython has Java like closures? No comprende.
- irahul 15y agoJava's closures are a pain as they need inner classes to emulate closures - Python's are a lot easier, hands down. Java needs the local variables to be final for it to close over them. Python doesn't but you can't directly mutate it. Won't you agree in that sense the statement holds some truth?
- irahul 15y ago> then I realized that Ruby isn't quite like them either. I am curious. How does Ruby's closure differ from Scheme's?
- spacemanaki 15y agoTo be honest, I'm not really sure. I think it's a superficial difference. When I put this into a Ruby 1.9.2 REPL def foo (n) lambda {|i| n += i } end I expected to be able to do this: acc = foo(0) acc(1) But instead have to do acc.call(1) Maybe there's another way... Edit: oops you pointed out this example in another comment, sorry! Is there no way for the returned lambda to "feel" like a regular function?
- deleted 15y ago[deleted]
- nikcub 15y agoyou should read Armin's other posts about Python and webdev, if you haven't already: http://lucumr.pocoo.org/tags/python/ http://lucumr.pocoo.org/tags/python/