This article is the 9th day article of Python Part 2 Advent Calendar 2015.
I wrote Python for the first time four years ago and thought it was a very good language, so I always wrote simple code in Python. The first thing I wrote was Python 2.7, but when I was looking into it, there was something called Python 3, and I liked new things, so when I really started learning, I used Python 3.3. So, I didn't know much about the 2nd system, and I didn't think it was necessary to learn the old ones (although the 2nd system was the main one at that time). But. There were various problems such as the library of 2 series did not support 3 series, and it was written in 2 series and I had to replace it with 3 series by myself.
Anyway, I decided to take a look at the differences between the 2nd and 3rd systems while learning. (Aside from the fact that it's been about 7 years since the 3rd system came out ...) (Furthermore, aside from the fact that other wonderful people are writing wonderful articles ... (T_T))
――When I started writing, I thought I would write the progress from Python2 to Python3.5, but since it became quite long up to Python3.0, the progress from Python3.0 to Python3.5 is a separate article. Write in. --The version where you executed the code is written in the upper left. --For those who have some knowledge of Python. If you have touched it for a while, it's probably okay! --The underscore that suddenly appears in the code stores the previous execution result.
Python3
>>> 1+1
2
>>> _
2
>>> 2+3
5
>>> _ -3
2
>>> type(_)
<class 'int'>
>>> _
<class 'int'>
Well then, it's quite long (laughs) Let's do our best!
Python2 -> Python3.0
Python2
>>> print 'Hello'
Hello
Python3
>>> print('Hello')
Hello
The definition in Python3 seems to be like this.
def print(*args, sep=' ', end='\n', file=None)
I wonder if I'm in trouble when trying to display tuples.
Python2
>>> print ('item1', 'item2')
('item1', 'item2')
Python3
>>> print ('item1', 'item2')
item1 item2
>>> print(('item1', 'item2'), )
('item1', 'item2')
Views is Nanno Kocha. Well, you can see the result.
Python2
>>> d = {"key1": "value1"}
>>> d.keys()
['key1']
>>> type(_)
<type 'list'>
>>> d.values()
['value1']
>>> d.items()
[('key1', 'value1')]
Python3
>>> d = {"key1": "value1"}
>>> d.keys()
<dict_keys object at 0x7f0da5268e18>
>>> type(_)
<class 'dict_keys'>
>>> d.values()
<dict_values object at 0x7f0da5268e18>
>>> d.items()
<dict_items object at 0x7f0da3a44638>
In Python2, everything is a list, and in Python3, it is returned as an object such as dict_keys
.
This is an iterable object, which you probably call Views.
If you want it as a list in Python3, wrap it with list ()
.
Python3
>>> list(d.keys())
['key1']
Python2
>>> d.iterkeys()
<dictionary-keyiterator object at 0x7f5b586155d0>
>>> type(_)
<type 'dictionary-keyiterator'>
Python3
>>> d.iterkeys()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'iterkeys'
It's natural, isn't it? The keys return the iterator.
Python2
>>> f1 = lambda x : x + 1
>>> f2 = lambda x : x%2 == 0
>>> l = [1, 2, 3]
>>> map(f1, l)
[2, 3, 4]
>>> type(_)
<type 'list'>
>>> filter(f2, l)
[2]
>>> type(_)
<type 'list'>
Python3
>>> iter_check = lambda obj : hasattr(obj, '__iter__') and hasattr(obj, '__next__')
>>> isIterable = lambda obj : hasattr(obj, '__iter__')
>>> f1 = lambda x : x + 1
>>> f2 = lambda x : x%2 == 0
>>> l = [1, 2, 3]
>>> map(f1, l)
<map object at 0x7f0da5261950>
>>> map_obj = _
>>> type(map_obj)
<class 'map'>
>>> iter_check(map_obj)
True
>>>
>>> filter(f2, l)
<filter object at 0x7f0da52619d0>
>>> filter_obj = _
>>> type(filter_obj)
<class 'filter'>
>>> iter_check(filter_obj)
True
You don't have to worry too much about the contents of lambda (laughs) It is a function that checks whether it is an iterator or an iterator. A list is returned in Python2, and an iterator is returned in Python3.
Python2
>>> iter_check = lambda obj : hasattr(obj, '__iter__') and hasattr(obj, '__next__')
>>> isIterable = lambda obj : hasattr(obj, '__iter__')
>>> type(range(1,10))
<type 'list'>
>>> type(xrange(1,10))
<type 'xrange'>
>>> iter_check(xrange(1,10))
False
>>> isIterable(xrange(1,10))
True
Python3
>>> type(range(1,10))
<class 'range'>
>>> type(iter(range(1,10)))
<class 'range_iterator'>
>>> xrange(1,10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
In Python 3, range returns an iterable object instead of a list. And xrange has passed away. Chain
Python2
>>> zip([1,2,3], [2,3,4])
[(1, 2), (2, 3), (3, 4)]
>>> type(_)
<type 'list'>
Python3
>>> zip([1,2,3], [2,3,4])
<zip object at 0x7f0da3a40cf8>
>>> iter_check(_)
True
Python 3 is returning an iterator.
Python2
>>> 1 < 'a'
True
>>> 0 > None
True
>>> len <= len
True
>>> None < None
False
Python3
>>> 1 < 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()
>>> 0 > None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() > NoneType()
>>> len <= len
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: builtin_function_or_method() <= builtin_function_or_method()
>>> None < None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < NoneType()
I knew this for the first time. Python2 is terrible ... However, Python3 throws exceptions firmly, so it's safe!
The definition in Python2 is as follows
sorted(iterable[, cmp[, key[, reverse]]])
s.sort([cmp[, key[, reverse]]])
The definition in Python3 is as follows
sorted(iterable[, key][, reverse])
sort(*, key=None, reverse=None)
The cmp argument is gone. Also, the argument of the sort method of list in Python3 must be passed as a keyword argument.
__cmp__
method is no longer supportedThis is not an example, isn't it?
Please use the __lt__
method for sorting.
Python2
>>> type(10**100)
<type 'long'>
Python3
>>> type(10**100)
<class 'int'>
It is treated as an int type in Python.
Python2
>>> 1/2
0
>>> type(1/2)
<type 'int'>
Python3
>>> type(1/2)
<class 'float'>
>>> 1//2
0
>>> type(1//2)
<class 'int'>
If you want to divide in Python3 and return it as an int, use the // operator.
Python2
>>> sys.maxint
9223372036854775807
Python3
>>> sys.maxint
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'maxint'
It has been deleted.
Python2
>>> 10**20
100000000000000000000L
Python3
>>> 10**20
100000000000000000000
L is not at the end in Python3.
Python2
>>> 0720
464
>>> 0o720
464
Python3
>>> 0720
File "<stdin>", line 1
0720
^
SyntaxError: invalid token
>>> 0o720
464
Is this a unified form of notation such as 0x and 0b?
As the title says. This made the old Unicode text literals ʻu" ... "` unusable.
Python2
>>> u"unicode"
u'unicode'
Python3
>>> u"unicode"
File "<stdin>", line 1
u"unicode"
^
SyntaxError: invalid syntax
Python3
>>> type("test")
<class 'str'>
>>> type(b"test")
<class 'bytes'>
Use b" ... "
for binary data literals.
Python2
>>> "str" + b"bytes"
'strbytes'
Python3
>>> "str" + b"bytes"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bytes' object to str implicitly
Python2 Seriously ... (2nd time) It's such a crazy thing. .. Python3 is wrong!
Python3
>>> "str".encode()
b'str'
>>> bytes("str", "utf-8")
b'str'
>>>
>>> b"bytes".decode()
'bytes'
>>> str(b"bytes", "utf-8")
'bytes'
It's a conversion between str and bytes. Well, there are a lot of articles about encode and decode in Python, so please refer to that.
Python2
>>> print(ur"\u20ac")
€
Python3
>>> print(r"\u20ac")
\u20ac
I'm not saying that Python2 is serious, but hey! It is a feeling. I don't like raw strings! Well, there may be times when you want this behavior, but Python 3's behavior is better.
Python2
>>> str.__base__
<type 'basestring'>
>>> bytes.__base__
<type 'basestring'>
Python3
>>> str.__base__
<class 'object'>
>>> bytes.__base__
<class 'object'>
In Python2, there was an abstract class called basestring. It means that str and bytes type were created by inheriting it. In Python3, each class is defined directly.
Python3
>>> def f(a: "int_value", b: "int_value default value one" = 1) -> "added_value":
... return a+b
...
>>> f.__annotations__
{'a': 'int_value', 'b': 'int_value default value one', 'return': 'added_value'}
You can add annotations to function arguments and return values.
In the above example, it is only a character string, but since you can write an expression, you can write 1 + 1
, ʻint`, and so on.
Python3
>>> i=2
>>> j=3
>>> def f(a: i*j, b: i+j) -> 1+1:
... return a+b
...
>>> f.__annotations__
{'a': 6, 'b': 5, 'return': 2}
>>> i=10
>>> j=10
>>> f.__annotations__
{'a': 6, 'b': 5, 'return': 2}
The expression is evaluated when the function is defined. It's natural, isn't it? ..
Python3
>>> def f(a, *, b):
... return a+b
...
>>> def g(*, a, b):
... return a*b
...
>>> f(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 1 positional argument (2 given)
>>> f(1, b=2)
3
>>> g(1, b=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: g() takes exactly 0 non-keyword positional arguments (1 given)
>>> g(a=1, b=2)
2
>>> g(b=1, a=2)
2
You can use the asterisk *
to limit the arguments listed after that to keyword arguments.
There are very few Japanese documents, so when I first saw it, I was in trouble (laughs).
Python3
>>> class MClass(type):
... def __new__(cls, name, bases, namespace, **kwds):
... result = type.__new__(cls, name, bases, dict(namespace))
... result.members = tuple(namespace)
... return result
... def __init__(self, *args, **kargs):
... print("args: " + str(args))
... print("kargs: " + str(kargs))
...
>>> class A(object, metaclass=MClass, a=1, b=2, c=3):
... def one(self): pass
...
args: ('A', (<class 'object'>,), {'__module__': '__main__', 'one': <function one at 0x7f62d071c408>})
kargs: {'a': 1, 'c': 3, 'b': 2}
This is a little heavy ... Anyway, you can receive keyword arguments after the base class. However, type cannot receive keyword arguments, so you have to create your own metaclass to receive them. .. (MClass is that)
Python3
>>> def counter(init=0):
... def cntup():
... nonlocal init
... init+=1
... return init
... return cntup
...
>>> c = counter()
>>> c()
1
>>> c()
2
>>> c()
3
The nonlocal statement allows the specified identifier to refer to a variable in the scope one level above. In short, is it a closure? In the example, the argument init of the counter function is referenced by the nonlocal statement. In Python2, I couldn't do it without using list etc., but in Python3 I can write it concisely. (If you just want to refer to it, you don't need nonlocal or list in Python2. You need it when binding variables in the outer scope.)
Python3
>>> c.__closure__
(<cell at 0x7f62d071d5c8: int object at 0x7a3e20>,)
>>> c.__closure__[0].cell_contents
3
By the way, you can refer to the closure in this way.
Python3
>>> a, *rest, b = range(5)
>>> a
0
>>> rest
[1, 2, 3]
>>> b
4
After unpacking a and b in rest, the surplus is unpacked as a list. This rest may be unpacked as an empty list.
Python3
>>> a, *rest, b = range(2)
>>> a
0
>>> rest
[]
>>> b
1
it's amazing···.
Python2
>>> try:
... raise Exception("test")
... except Exception, e:
... print "catch exception!"
...
catch exception!
Python3
>>> try:
... raise Exception("test")
... except Exception as e:
... print("catch exception!")
...
catch exception!
The comma has been changed to the as keyword.
Python3
>>> try:
... raise Exception("test")
... except Exception as e:
... raise RuntimeError("catch exception!") from e
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: test
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: catch exception!
The from clause has been added to allow you to represent a chain of exceptions. Also, it seems to work implicitly when an exception is thrown in the except clause.
Python3
>>> try:
... 1/0
... except Exception as e:
... raise RuntimeError("raise exception.")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: raise exception.
Python2
>>> True = 0
>>> False = 1
>>> True
0
>>> False
1
>>> True and True
0
Python3
>>> True=0
File "<stdin>", line 1
SyntaxError: assignment to keyword
>>> False=1
File "<stdin>", line 1
SyntaxError: assignment to keyword
Fear! !! Well, you can substitute it for True, False, or usually! I don't.
Python2
>>> class M(type):
... pass
...
>>> class C:
... __metaclass__ = M
...
>>> C.__class__
<class '__main__.M'>
Python3
>>> class M(type):
... pass
...
>>> class C(metaclass=M):
... pass
...
>>> C.__class__
<class '__main__.M'>
In Python2, the \ _ \ _ metaclass \ _ \ _ variable is specified, and in Python3, the base class is specified and passed as a keyword argument. Python3 does not support methods like Python2.
What I learned for the first time here was that in Python2, class had to explicitly inherit object, but by using a metaclass, a class that inherits object can be created. I see!
Python2
>>> class A:
... pass
...
>>> A.__bases__
()
>>> class C:
... __metaclass__ = type
...
>>> C.__bases__
(<type 'object'>,)
Python3
>>> ...
Ellipsis
>>> def e():
... ...
abridgement. (I have nothing to say ...)
It's been deleted, so let's move on.
Python2
>>> def foo(a, (b,c)):
... return a+b+c
...
>>> t = 2,3
>>> foo(1, t)
6
Python3
>>> def foo(a, (b,c)):
File "<stdin>", line 1
def foo(a, (b,c)):
^
SyntaxError: invalid syntax
It's hard to read ... In Python3, I get angry from the first line.
Python2
>>> i = 123
>>> `i`
'123'
Python3
>>> i=123
>>> `i`
File "<stdin>", line 1
`i`
^
SyntaxError: invalid syntax
Apparently the \ _ \ _ repr \ _ \ _ method was called.
Python2
>>> exec "print('python2')"
python2
>>> exec("print('python2')")
python2
Python3
>>> exec "print('python3')"
File "<stdin>", line 1
exec "print('python3')"
^
SyntaxError: invalid syntax
>>> exec("print('python3')")
python3
In Python2 it was an exec statement. Function notation is also okay. In Python3, it is no longer a reserved word and remains as a function.
Python2
>>> 1 <> 2
True
>>> 1 <> 1
False
Python3
>>> 1 <> 2
File "<stdin>", line 1
1 <> 2
^
SyntaxError: invalid syntax
! = Isn't it okay?
Python2
>>> u"python2"
u'python2'
>>> 100L
100L
Python3
>>> u"python3"
File "<stdin>", line 1
u"python3"
^
SyntaxError: invalid syntax
>>> 100L
File "<stdin>", line 1
100L
^
SyntaxError: invalid syntax
That's what I've already mentioned above.
Python2
>>> from sys import *
>>> def f():
... from os import *
...
<stdin>:1: SyntaxWarning: import * only allowed at module level
Python3
>>> from sys import *
>>> def f():
... from os import *
...
File "<stdin>", line 1
SyntaxError: import * only allowed at module level
Warning has changed to Error. Why did Python 2 stop with Warning ...
! =
Returns the opposite of ==
(if ==
does not return Not Implemented)Python2
>>> class C:
... def __init__(self, a):
... self.a = a
...
... def __eq__(self, other):
... return self.a == other.a
...
>>> a = C(1)
>>> b = C(1)
>>> c = C(2)
>>> a == b
True
>>> a == c
False
>>> a != b
True
>>> a != c
True
Python3
>>> class C:
... def __init__(self, a):
... self.a = a
...
... def __eq__(self, other):
... return self.a == other.a
...
>>> a = C(1)
>>> b = C(1)
>>> c = C(2)
>>> a == b
True
>>> a != b
False
>>> a == c
False
>>> a != c
True
This was a little surprising.
Since ! =
In Python2 does not implement __ne__ ()
, it compares whether the objects are the same.
The result is True because a, b, and c are all different.
I was wondering if I would get an Attribute Error ... It was a story that you can understand with a little thought.
Python2
>>> class C:
... def f(self):
... pass
...
>>> C.f
<unbound method C.f>
Python3
>>> class C:
... def f(self):
... pass
...
>>> C.f
<function f at 0x100a35270>
Yes. Python3 is treated as just a function. The unbound method is probably a method that is not tied to an instance. Python3 is simpler and easier to understand
__getslice__ ()
method is deleted and the slice object is passed to the __getitem__ ()
method.Python2
>>> class C:
... def __getslice__(self, i, j):
... print i, j
... raise NotImplementedError()
...
>>> a = C()
>>> a[0:2]
0 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __getslice__
NotImplementedError
Python3
>>> class C:
... def __getitem__(self, obj):
... print(obj)
... print(type(obj))
... raise NotImplementedError()
...
>>> a = C()
>>> a[0:2]
slice(0, 2, None)
<class 'slice'>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getitem__
NotImplementedError
But
Is now called instead, and the slice object is now passed. I haven't implemented it in the example, but you can see that the slice object is passed as an argument.
next ()
method has been renamed to __next__ ()
Python2
>>> class C:
... def __iter__(self):
... return self
...
... def next(self):
... return 0
...
>>> a = C()
>>> i = iter(a)
>>> next(i)
0
>>> i.next()
0
Python3
>>> class C:
... def __iter__(self):
... return self
...
... def __next__(self):
... return 0
...
>>> a = C()
>>> i = iter(a)
>>> next(a)
0
>>> i.__next__()
0
It has changed so that __next__ ()
is called from next ()
.
__oct__ ()
and __hex __ ()
have been removed and __index__ ()
should be used.Python2
>>> class C:
... def __oct__(self):
... return "07"
...
... def __hex__(self):
... return "0x7"
...
>>> a = C()
>>> hex(a)
'0x7'
>>> oct(a)
'07'
Python3
>>> class C:
... def __index__(self):
... return 7
...
>>> a = C()
>>> hex(a)
'0x7'
>>> oct(a)
'0o7'
__oct__ ()
and __hex__ ()
are methods that convert a number to a string and return it, but __index__ ()
only returns a number. After that, Python will convert it to good.
Python3 is wonderful ~.
(The example returns a constant, but please forgive me ...)
__nonzero__ ()
has been renamed to __bool__ ()
Python2
>>> class C:
... def __nonzero__(self):
... return True
...
>>> a = C()
>>> bool(a)
True
Python3
>>> class C:
... def __bool__(self):
... return True
...
>>> a = C()
>>> bool(a)
True
How did you decide on the name __nonzero__ ()
?
In Python 3, __bool__ ()
is called. Easy to understand.
Builtins
super ()
Python3
>>> class SuperClass:
... pass
...
>>> class SubClass(SuperClass):
... def findSuperClass(self):
... print("call super(): ", super())
... print("call super(SubClass, self)", super(SubClass, self))
...
>>> i = SubClass()
>>> i.findSuperClass()
call super(): <super: <class 'SubClass'>, <SubClass object>>
call super(SubClass, self) <super: <class 'SubClass'>, <SubClass object>>
super ()
can be called with no arguments and will automatically pick the appropriate class and instance for you.
The processing is the same as when there is an argument.
raw_input ()
to ʻinput ()`Python3
>>> input()
test
'test'
ʻInput () reads one line from the standard input and returns the string without line breaks. If you want to execute ʻinput ()
in Python2, you can do it with ʻeval (input ())`.
In blunt Python 3
--print becomes a function
--keys, items, values methods return iterable objects
--The standard string is Unicode and the type is str
--xrange becomes range
I think that there is almost no problem if you remember the area.
Also, there are some changes that I omitted in this article, but I've removed about 10% of the niche content that I felt wasn't very important. If you want to know, please read What's New in Python 3.0 (round throw).
As I was writing the article, I was surprised to find that Python2 was addicted to traps. I'm glad I started doing it myself from Python 3 (laughs)
And if you haven't switched from Python2 yet, it's convenient to take this opportunity to remember this and switch to Python3, and a happy Python life will be waiting for you (laughs). (Although there are a lot of summary articles such as Python 2 to 3)
As I wrote at the beginning, I will write the progress from Python 3.0 to Python 3.5 in another article. The progress from Python 3.0 to Python 3.5 will be on the 16th of Python Part 2 Advent Calendar.
Also, if you have any strange points, mistakes, or better things to do, please comment!
Tomorrow is free and 11th is @FGtatsuro!
** Then have a good Python3 life! !! ** **
Recommended Posts