Переписал все предыдущие примеры так, чтобы один и тот же файл кода мог исполняться и в Python 2 и в Python 3, для сравнения, для типизации это особенно интересно.
Для чего в терминальных программах достаточно переписать
операторы print в функциональные
вызовы print(), что-то типа такого, чтобы вместо такого:
Код: Выделить всё
print "i - это : %s . id=%08x . hash=%i" % ( type( i ), id( i ), long( hash( i ) ) )
теперь бы стало что-то такое:
Код: Выделить всё
print( "i - это : {0:s} . id={1:08x} . hash={2:d}".format( ( type( i ), id( i ), hash( i ) )
Но повозиться с форматами, чтобы 2/3 выглядели адекватно, сравнимо - пришлось повозиться (форматирование срабатывает по-разному, особенно UTF-строки, с которыми в Python 2, как уже отмечали, негаразды...). Но возня стоила того, потому как посмотреть результаты интересно... Это то, как переменная i пробегая самые разные значения меняет тип, как этот тип идентифицируется Python и т.д. (в листингах: сначала тип, потом id(), затем hash(), где он может вычисляться и ==> str(), то есть значение):
Код: Выделить всё
bash-4.2$ ./tp2.py
i - это : <type 'int'> | id=009c290b0 | hash=000000000001 ==> 1
i - это : <type 'float'> | id=009c32304 | hash=-02061781074 ==> 0.015
i - это : <type 'complex'> | id=0b76989c8 | hash=-00345735165 ==> (3+5.5j)
i - это : <type 'str'> | id=0b769c360 | hash=000132808738 ==> теперь это UNICODE строка
i - это : <type 'list'> | id=0b770af8c | не хэшируемый тип! ==> [1, 2, 3]
i - это : <type 'list'> | id=0b76acd0c | не хэшируемый тип! ==> [0, 3, 6]
i - это : <type 'list'> | id=0b770af8c | не хэшируемый тип! ==> [[0, 0], [1, 1], [2, 4]]
i - это : <type 'tuple'> | id=0b76ab75c | hash=-00378539185 ==> (1, 2, 3)
i - это : <type 'set'> | id=0b76f6f7c | не хэшируемый тип! ==> set([1, 2, 3])
i - это : <type 'dict'> | id=0b76ad79c | не хэшируемый тип! ==> {1: 'one', 2: 'two', 3: 'three'}
i - это : <type 'function'> | id=0b76a510c | hash=-00881416944 ==> <function <lambda> at 0xb76a510c>
i - это : <type 'code'> | id=0b76a78d8 | hash=-02089338066 ==> <code object <module> at 0xb76a78d8, file "", line 1>
i - это : <type 'iterator'> | id=0b76b854c | hash=-00881412012 ==> <iterator object at 0xb76b854c>
i - это : <type 'instance'> | id=0b76b84cc | hash=-00881412020 ==> <__main__.own1 instance at 0xb76b84cc>
i - это : <type 'classobj'> | id=0b76a026c | hash=-00881418202 ==> __main__.own1
i - это : <type 'instance'> | id=0b76b856c | не хэшируемый тип! ==> <__main__.own2 instance at 0xb76b856c>
i - это : <type 'classobj'> | id=0b76a020c | hash=-00881418208 ==> __main__.own2
Код: Выделить всё
bash-4.2$ python3 tp2.py
i - это : <class 'int'> | id=0475b1580 | hash=000000000001 ==> 1
i - это : <class 'float'> | id=008f8e704 | hash=001578400478 ==> 0.015
i - это : <class 'complex'> | id=0b737a200 | hash=-01068741806 ==> (3+5.5j)
i - это : <class 'str'> | id=0b73daf60 | hash=001282498349 ==> теперь это UNICODE строка
i - это : <class 'list'> | id=0b7412c6c | не хэшируемый тип! ==> [1, 2, 3]
i - это : <class 'list'> | id=0b741274c | не хэшируемый тип! ==> [0, 3, 6]
i - это : <class 'list'> | id=0b7412c6c | не хэшируемый тип! ==> [[0, 0], [1, 1], [2, 4]]
i - это : <class 'tuple'> | id=0b7411194 | hash=-00378539185 ==> (1, 2, 3)
i - это : <class 'set'> | id=0b7407b1c | не хэшируемый тип! ==> {1, 2, 3}
i - это : <class 'dict'> | id=0b74a2bdc | не хэшируемый тип! ==> {1: 'one', 2: 'two', 3: 'three'}
i - это : <class 'function'> | id=0b73c926c | hash=-00881604314 ==> <function <lambda> at 0xb73c926c>
i - это : <class 'code'> | id=0b73cbb10 | hash=-00858576570 ==> <code object <module> at 0xb73cbb10, file "", line 1>
i - это : <class 'str_iterator'> | id=0b73d546c | hash=-00881601210 ==> <str_iterator object at 0xb73d546c>
i - это : <class '__main__.own1'> | id=0b73d54ec | hash=-00881601202 ==> <__main__.own1 object at 0xb73d54ec>
i - это : <class 'type'> | id=009083e04 | hash=001083212768 ==> <class '__main__.own1'>
i - это : <class '__main__.own2'> | id=0b73d550c | не хэшируемый тип! ==> <__main__.own2 object at 0xb73d550c>
i - это : <class 'type'> | id=009081d1c | hash=-01064271407 ==> <class '__main__.own2'>
Видно, что теперь (Python 3), как и обещано в описаниях, любая переменная, будь то элементарный int - это экземпляр
класса ... класса int ... или класса float.
(вообще то, это может сильно замедлять выполнение, ... что, похоже, и наблюдалось при тестировании параллельных ветвей выполнения ... рядом тема).
P.S. Ну и в примерах несколько расширен набор тех типов, которые может принимать переменная.
2-й интересный пример - это с операторами == для != экземляров классов... :
Код: Выделить всё
bash-4.2$ ./tp-eq.py
сравнения объекта <__main__.obj0(13)> и объекта <__main__.obj0(13)> : '=='->False | !='->True
сравнения объекта <__main__.obj0(13)> и объекта <__main__.obj0(31)> : '=='->False | !='->True
сравнения объекта <__main__.obj1(24)> и объекта <__main__.obj1(24)> : '=='->True | !='->True
сравнения объекта <__main__.obj1(24)> и объекта <__main__.obj1(42)> : '=='->False | !='->True
сравнения объекта <__main__.obj2(35)> и объекта <__main__.obj2(35)> : '=='->True | !='->False
сравнения объекта <__main__.obj2(35)> и объекта <__main__.obj2(53)> : '=='->False | !='->True
сравнения объекта <__main__.obj0(77)> и объекта <__main__.obj1(77)> : не сравнимые типы объектов!
сравнения объекта <__main__.obj1(88)> и объекта <__main__.obj0(88)> : не сравнимые типы объектов!
сравнения объекта <<type 'int'>(55)> и объекта <__main__.obj1(55)> : не сравнимые типы объектов!
сравнения объекта <__main__.obj1(55)> и объекта <<type 'int'>(55)> : не сравнимые типы объектов!
Код: Выделить всё
bash-4.2$ python3 tp-eq.py
сравнения объекта <<class '__main__.obj0'>(13)> и объекта <<class '__main__.obj0'>(13)> : '=='->False | !='->True
сравнения объекта <<class '__main__.obj0'>(13)> и объекта <<class '__main__.obj0'>(31)> : '=='->False | !='->True
сравнения объекта <<class '__main__.obj1'>(24)> и объекта <<class '__main__.obj1'>(24)> : '=='->True | !='->False
сравнения объекта <<class '__main__.obj1'>(24)> и объекта <<class '__main__.obj1'>(42)> : '=='->False | !='->True
сравнения объекта <<class '__main__.obj2'>(35)> и объекта <<class '__main__.obj2'>(35)> : '=='->True | !='->False
сравнения объекта <<class '__main__.obj2'>(35)> и объекта <<class '__main__.obj2'>(53)> : '=='->False | !='->True
сравнения объекта <<class '__main__.obj0'>(77)> и объекта <<class '__main__.obj1'>(77)> : не сравнимые типы объектов!
сравнения объекта <<class '__main__.obj1'>(88)> и объекта <<class '__main__.obj0'>(88)> : не сравнимые типы объектов!
сравнения объекта <<class 'int'>(55)> и объекта <<class '__main__.obj1'>(55)> : не сравнимые типы объектов!
сравнения объекта <<class '__main__.obj1'>(55)> и объекта <<class 'int'>(55)> : не сравнимые типы объектов!
Здесь всё грустнее...
В Python 3 (файл исполняемый один!), похоже, реализация == влечёт за собой адекватное поведение симметричной операции != ... что совсем не так в Python 2 (3-и строки листингов).
И как следствие таких вот "мелочей" (а их, похоже, по-мелочам выявляется весьма много) всё программное обеспечение, написанное под Python 2, будет работать
не так под Python 3. Именно не сваливаться синтаксически (это как-раз удачный случай, значит вам повезло
), а именно выполняться, но результат выдавать не тот, то есть ошибочный, создавая при этом видимость правильной работы.
P.S. Остальные там примеры тоже интересные, и тоже запускаются все как в Python 2, так и в Puthon 3, для сравнения ... но это уже любопытствующие посмотрят сами ... + как всегда, в архиве - текстовый файл .hist, история листингов в хронологии их изменений.