4 ms·
For extra fun.... a = 5 def print_a(): print a # Prints 5 print_a() def print_and_assign_a(): print a a = 2 # raises UnboundLo
by anonymoushn 15y ago
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
- kbd 15y agoWell, 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!
- anonymoushn 15y agoThe 'print_and_assign_a' case comes up more often with a in an enclosing local scope, so you couldn't really get it to work prior to the introduction of 'nonlocal' in Python 3. The best you could do was something silly like a = [5] def print_and_assign_a(): print(a[0]) a[0]=2 It's cool that the second case works in other implementations. I hadn't thought to test that.
- kbd 15y agoYes, 'nonlocal' definitely closed a hole in the language.
- ak217 15y ago> Should "a = set([1,2])" be equivalent to "a = set(); a.add(1); a.add(2)"? Why should it be? Adding elements one-by-one is slow and shouldn't be forced on the language model level.