On Mon, Jul 19, 2010 at 6:55 PM, Tim Peters <tim.pet...@gmail.com> wrote: > [kirby urner] >> ... here's another basic >> question. Is there a way, after importing from __future__, >> to revert to the "old ways" later on in the same script? >> ... >> I'm not saying this would ever be a good idea, just >> wondering about possibilities... > > In general it's not possible. At least CPython compiles an entire > file into bytecode before anything is executed. That's why __future__ > imports have to be the first non-trivial statements in a file: they > can change just about anything, including the bytecode that gets > generated. > > For example, here's a little program: > > def f(): > print x / y > > import dis > dis.dis(f) > > That defines a tiny function, then displays the bytecode generated: > > 2 0 LOAD_GLOBAL 0 (x) > 3 LOAD_GLOBAL 1 (y) > 6 BINARY_DIVIDE > 7 PRINT_ITEM > 8 PRINT_NEWLINE > 9 LOAD_CONST 0 (None) > 12 RETURN_VALUE > > It's not necessary to know what any of those mean, although they > should be pretty obvious ;-) If you change the program by putting: > > from __future__ import division > > at the top, the output changes: > > 4 0 LOAD_GLOBAL 0 (x) > 3 LOAD_GLOBAL 1 (y) > 6 BINARY_TRUE_DIVIDE > 7 PRINT_ITEM > 8 PRINT_NEWLINE > 9 LOAD_CONST 0 (None) > 12 RETURN_VALUE > > Note that the third operation changed, from BINARY_DIVIDE to > BINARY_TRUE_DIVIDE. >
Thank you Tim, that's uber-clear and enlightening. I notice that in IDLE, even a shell restart (menu option) does not reset division back to the old way. IDLE 2.6.5 >>> 1/4 0 >>> from __future__ import division >>> 1/4 0.25 >>> ==== RESTART ==== >>> 1/4 0.25 I also recall how special name __div__ will be triggered by default in Python 2.6 until division is imported from __future__, then __truediv__ gets triggered instead: >>> class Foo (object): def __truediv__(self, other): print "__truediv__ triggered" def __div__(self, other): print "__div__ triggered" >>> o = Foo() >>> b = Foo() >>> o/b __div__ triggered >>> from __future__ import division >>> o/b __truediv__ triggered If all you've done is define __div__ for your object, that'll work by default, until you import division, then unless you have __truediv__ defined, you'll be getting those error messages: >>> class Foo (object): def __div__(self, other): print "__div__ triggered" >>> a = Foo() >>> a/3 __div__ triggered >>> from __future__ import division >>> a/3 Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> a/3 TypeError: unsupported operand type(s) for /: 'Foo' and 'int' >>> a/a Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> a/a TypeError: unsupported operand type(s) for /: 'Foo' and 'Foo' > This is all done before anything in the file is executed, so after > execution begins it's too late to change any of it: the opcode will > remain whatever was generated at the start (BINARY_DIVIDE or > BINARY_TRUE_DIVIDE) no matter what you do while the program is > running. After all, the instant after you import the future, it > becomes the past, and nobody can change the past ;-) > I'm a little surprised that resetting the IDLE shell doesn't reset division "back to factory". It does disappear from the namespace: >>> dir() ['Foo', '__builtins__', '__doc__', '__name__', '__package__', 'a', 'division'] >>> ======== RESTART ======= >>> dir() ['__builtins__', '__doc__', '__name__', '__package__'] >>> division Traceback (most recent call last): File "<pyshell#15>", line 1, in <module> division NameError: name 'division' is not defined >>> 1/4 0.25 Maybe it shouldn't be allowed to disappear from the namespace (del division raises an exception) as long as its effects are enforced. That way a program could test for it. But then I supposed there's another way. Reading from PEP 238: The true and floor division APIs will look for the corresponding slots and call that; when that slot is NULL, they will raise an exception. There is no fallback to the classic divide slot. In Python 3.0, the classic division semantics will be removed; the classic division APIs will become synonymous with true division. Testing in 3.1, I see __div__ is indeed gone as a special name for integers. Only __truediv__ ( and __floordiv__ and their =/ =// semantics) have been retained. __div__ may be in your code, but it's not a special name (nor is it a mangled private function given the trailing __ prevents mangling). Python 3.1.2 (r312:79149, Mar 21 2010, 00:41:52) [MSC v.1500 32 bit (Intel)] on win32 Type "copyright", "credits" or "license()" for more information. >>> class Foo (object): def __truediv__(self, other): print ("__truediv__ triggered") def __div__(self, other): print ("__div__ triggered") >>> o = Foo() >>> o/3 __truediv__ triggered >>> dir(3) # showing __div__ is all gone ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real'] >>> o .__div__(3) __div__ triggered What's in __future__ anyway? >>> import __future__ >>> dir(__future__) ['CO_FUTURE_ABSOLUTE_IMPORT', 'CO_FUTURE_DIVISION', 'CO_FUTURE_PRINT_FUNCTION', 'CO_FUTURE_UNICODE_LITERALS', 'CO_FUTURE_WITH_STATEMENT', 'CO_GENERATOR_ALLOWED', 'CO_NESTED', '_Feature', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'absolute_import', 'all_feature_names', 'division', 'generators', 'nested_scopes', 'print_function', 'unicode_literals', 'with_statement'] Kirby _______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig