grayvedigga•

It's when I read stuff like this that I wonder why I love python.

1
pemboa•

Your comment warrants some explanation.

3
grayvedigga•

The scoping rules for comprehensions don't give you the heebie jeebies?

1
pemboa•

No, not at all

3
masklinn•

Why? I like that it's so basic and simple.

1
[deleted]•

I laughed out loud.

Explain, please:

 >>> from new import instancemethod
 >>> class C(object):pass
 ...
 >>> C.__str__ = instancemethod(lambda self: 'hi!', C, type)
 >>> C.__str__()
 hi!
 >>> str(C)
 <class '__main__.C'>

Edit2: by the way, for additional shits and giggles try explaining what is different if you use classmethod or staticmethod instead. And why not just use a naked lambda. I mean, Python's object model is so basic and simple, it must be obvious, right?

Edit: oh, and on a related note (related to this funny "no method calls, not really" thing), try guessing what happens when I do:

 t = ([],)
 t[0] += [1, 2, 3]

And what's the value of t after that? When you've guessed incorrectly, observe the actual results and try explaining them.

Then stop referring to Python as "simple", please, don't add insult to injury. It's "simple for beginners", but when you get deeper it's more like a forgotten tomb of Ye Olde Ones, with Insanity that Lurks.

2
voidspaceOP•

When you call str(C) the metaclass str method is called. Protocol methods are looked up on the class, not the instance, and your class C is an instance of type.

3
[deleted]•

Indeed, reference.

Though I don't have a slightest idea if there is any difference between staticmethod, classmethod and instancemethod (besides their arguments).

The second one goes as follows: interpreter translates a[i] += b into a.__setitem__(a.__getitem__(i) += b) and can't take any shortcuts because items of a could be ints for example. Also it can't check the existence of a.__setitem__ in advance, because it might suddenly appear due to a side-effect. Neither it has a special __getitem_iadd__ operator. And, finally, lists feature a kind of broken (from the mathematical standpoint) +=:

>>> x1, x2 = [1], [1]
>>> y1, y2 = x1, x2
>>> x1 += [2]  # should be equivalent to the one below?
>>> x2 = x2 + [2]
>>> y1, y2
([1, 2], [1])	

As a result the exception gets raised, but after the element of the tuple was modified inplace.

My point is not that Python sucks, but rather that it shouldn't be called "simple". It is complex, in places -- very complex, sometimes as a tradeoff for the simplicity or features in other places, sometimes due to the design mistakes. In particular, Python's object system is like an order of magnitude more complex and produces more complex effects than Java's, despite appearing deceptively simple at the first glance: "everything is an object, object's class is an object, methods are looked up in the instance dictionary and then in the class and its parents, that is all".

2
grayvedigga•

For clarity:

>>> str(C())
'hi!'

pretty obvious now.

1
grayvedigga•

And what's the value of t after that?

wow. I almost missed this. Just in case anyone else reading does miss it, here's the complete test script:

t = ([],)
try:
  t[0] += [1,2,3]
except Exception, e:    # one of my favourite bits of syntax, fwiw
  print "Exception raised:", e
print t

... in cthulhu's name?

2
[deleted]•

By the way, you can use except Exception as e in 2.6 too.

1
riffito•

The code above yields:

>>> 
Exception raised: 'tuple' object does not support item assignment
([1, 2, 3],)

And if you do:

t = ([],)
try:
    t[0] = t[0] + [1,2,3]            # a += 1 equals a = a + 1, riiiight?
except Exception, e:
    print "Exception raised:", e
print t

you get:

>>>
Exception raised: 'tuple' object does not support item assignment
([],)

Nice! And consistent too! :-/

1
grayvedigga•

Did Guido never look at classes and go "hey, these things are pretty similar to functions"?

1
steppenfox•

Nice article!

1
zahlmanthe heretic•

This dictionary is protected by being wrapped in a dictproxy.

Only if you're inheriting from object.

1