Python 2 to 3
From raju
dummy
str __iter__ attrbute
python 2 | python 3 | |
---|---|---|
>>> hasattr('20201210', '__iter__') False |
>>> hasattr('20201210', '__iter__') True | |
tested using | 2.7.15 | 3.8.1 |
To migrate the code from Python 2 to 3, change
if hasattr(x, '__iter__'):
to
if hasattr(x, '__iter__') and not isinstance(x, str):
Similarly change
if not hasattr(x, '__iter__'):
to
if not hasattr(x, '__iter__') or isinstance(x, str):
Testing:
python 2 | python 3 | |
---|---|---|
>>> import pandas as pd >>> a = ['foo', 5, pd.Series()] >>> [True if hasattr(x, '__iter__') else False for x in a] [False, False, True] >>> [True if hasattr(x, '__iter__') and not isinstance(x, str) else False for x in a] [False, False, True] >>> [True if not hasattr(x, '__iter__') or isinstance(x, str) else False for x in a] [True, True, False] |
>>> import pandas as pd >>> a = ['foo', 5, pd.Series()] >>> [True if hasattr(x, '__iter__') else False for x in a] [True, False, True] >>> [True if hasattr(x, '__iter__') and not isinstance(x, str) else False for x in a] [False, False, True] >>> [True if not hasattr(x, '__iter__') or isinstance(x, str) else False for x in a] [True, True, False] | |
tested using | 2.7.15 | 3.8.1 |
Note: The elements of the test data are chosen to cover the following cases - a string object, a non string object with no __iter__ attribute, a non string object with an __iter__ attribute.
Ref:- https://stackoverflow.com/a/10509817/6305733
import statements
Python 3 does not allow implicit relative imports. They were allowed in python 2.
python 2 | python 3 |
---|---|
import foo | from . import foo |
from bar import foo | from .bar import foo |
Ref:-
- https://docs.python.org/3/tutorial/modules.html
- https://softwareengineering.stackexchange.com/a/159505/294460 - explains why implicit relative imports are bad.
tags | python3 does not look in current directory for modules, python 3 import local module
SyntaxWarning: "is" with a literal. Did you mean "=="?
python 2 | python 3 | |
---|---|---|
issue | >>> 1 is 1 True >>> 'a' is 'a' True |
>>> 1 is 1 <stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="? True >>> 'a' is 'a' <stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="? True |
fix | >>> 1 == 1 True >>> 'a' == 'a' True | |
tested using | 2.7.15 | 3.8.1 |
SafeConfigParser DeprecationWarning
python 2 | python 3 | |
---|---|---|
issue | >>> import configparser >>> a = configparser.SafeConfigParser() |
>>> import configparser >>> a = configparser.SafeConfigParser() <stdin>:1: DeprecationWarning: The SafeConfigParser class has been renamed to ConfigParser in Python 3.2. This alias will be removed in future versions. Use ConfigParser directly instead. |
fix | >>> a = configparser.ConfigParser() | |
tested using | 2.7.15 | 3.8.1 |
comparing None and a string
python 2 | python 3 | |
---|---|---|
issue | comparison of None and a string is allowed. | not allowed. |
example | >>> None < 'a' True >>> None < '' True |
>>> None < 'a' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '<' not supported between instances of 'NoneType' and 'str' >>> None < '' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '<' not supported between instances of 'NoneType' and 'str' |
tested using | 2.7.15 | 3.8.1 |
Ref:-
- https://docs.python.org/3/whatsnew/3.0.html#ordering-comparisons - tells that a TypeError exception is raised when None is compared with a string.
tags | python 3 comparison operators using None
To find out | Is None considered less than any string in Python 2?
replace map calls with none as first argument
tags | map with None as function, 2 to 3 starred expression
In Python 2:
$ ipython Python 2.7.13 |Anaconda custom (64-bit)| (default, Dec 19 2016, 13:29:36) [MSC v.1500 64 bit (AMD64)] In [1]: a = [1,2,3]; b = [4,5]; c = [6] ...: for i,j,k in map(None, a, b, c): ...: print i, 'blah', j, 'blah', k 1 blah 4 blah 6 2 blah 5 blah None 3 blah None blah None In [2]: import itertools ...: for i,j,k in itertools.izip_longest(a,b,c): ...: print i, 'blah', j, 'blah', k 1 blah 4 blah 6 2 blah 5 blah None 3 blah None blah None
In Python 3:
$ ipython Python 3.6.8 |Anaconda custom (64-bit)| (default, Dec 30 2018, 18:50:55) [MSC v.1915 64 bit (AMD64)] In [1]: import itertools ...: a = [1,2,3]; b = [4,5]; c = [6] ...: for i,j,k in itertools.zip_longest(a,b,c): ...: print(i, 'blah', j, 'blah', k) 1 blah 4 blah 6 2 blah 5 blah None 3 blah None blah None
Ref:- https://stackoverflow.com/questions/1277278/python-zip-like-function-that-pads-to-longest-length
None value comparison
In python 2, comparing two values using a < b is allowed even if both values are None. But Python 3 will throw an exception on it.
In Python 2
$ python Python 2.7.15 |Anaconda, Inc.| (default, May 1 2018, 18:37:09) [MSC v.1500 64 bit (AMD64)] on win32 >>> a = None; b = None; c = 2 >>> a == b True >>> a != b False >>> a < b False >>> a > b False >>> a == c False >>> a != c True >>> a < c True >>> a > c False
In Python 3
$ python Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)] on win32 >>> a = None; b = None; c = 2 >>> a == b True >>> a != b False >>> a < b Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '<' not supported between instances of 'NoneType' and 'NoneType' >>> a > b Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '>' not supported between instances of 'NoneType' and 'NoneType' >>> a == c False >>> a != c True >>> a < c Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '<' not supported between instances of 'NoneType' and 'int' >>> a > c Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '>' not supported between instances of 'NoneType' and 'int'
integer division
python 2 | python 3 | |
---|---|---|
issue | >>> 17 / 3 5 |
>>> 17 / 3 5.666666666666667 |
fix | >>> 17 // 3 5 |
>>> 17 // 3 5 |
tested using | 2.7.15 | 3.8.1 |
Ref:- https://stackoverflow.com/a/21317017/6305733