0% found this document useful (0 votes)
13 views

Python Lecture 5

This document summarizes some of the main differences between Python 2.x and 3.x. Key changes include print becoming a function, string formatting using {} instead of %, iterators replacing lists for functions like map and filter, range being lazy instead of a list, integer division changing, and syntax cleanups around sets, dictionaries, and strings. It recommends reviewing the comprehensive online documentation for all changes between Python versions.

Uploaded by

Peter Stephen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

Python Lecture 5

This document summarizes some of the main differences between Python 2.x and 3.x. Key changes include print becoming a function, string formatting using {} instead of %, iterators replacing lists for functions like map and filter, range being lazy instead of a list, integer division changing, and syntax cleanups around sets, dictionaries, and strings. It recommends reviewing the comprehensive online documentation for all changes between Python versions.

Uploaded by

Peter Stephen
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 39

CS 11 Python track

Lecture 5: Python 3.x


Python 3.x
• Python 3.1.2 is the latest version of Python
• (not yet available on the CS cluster)
• This lecture will summarize the main differences
between Python 2.x and Python 3.x
• Comprehensive overview:
http://docs.python.org/dev/3.0/whatsnew/3.0.html
Overview
• Python 3.x is a major revision of the language
• Several new features
• A lot of cleaning up of old features
• Many dubious old features removed entirely
• some just deprecated; will be removed eventually
• "Deliberately incompatible" with older versions
• so old code will break if run under python 3.x
This lecture
• Too many changes in Python 3.x to
conveniently fit into one lecture
• Therefore, this lecture contains features that
• are most likely to trip you up
• are most radical
• are most interesting (according to me)
print statement (1)
• The print statement is no longer special
• it's just another function!
• So instead of writing
print "hello, world!"
• You write:
print("hello, world!")
print statement (2)
• Old:
print "foo", "bar", "baz"

• New:
print("foo", "bar", "baz")
print statement (3)
• Old:
print "foobar", # no newline
• New:
print("foobar", end="")
print("foobar", end=" ")
# space instead of newline
print statement (4)
• Old:
>>> print "There are <", 2**32, "> possibilities!"

There are < 4294967296 > possibilities!

• New:
>>> print("There are <", 2**32, "> possibilities!",

sep="") # no separator

There are <4294967296> possibilities!


print statement (5)
• Old:
>>> print # prints a newline only

• New:
>>> print()
print statement (6)
• Old:
>>> print >> sys.stderr, "error!"

• New:
>>> print("error!", file=sys.stderr)
String formatting (1)
• Old:
>>> "int: %d\tfloat: %f\tstring: %s\n" %

(10, 3.14, "this is a string")

• New:
>>> "int: {0}\tfloat: {1}\tstring: {2}\n".format(

10, 3.14, "this is a string")

• (Old syntax still supported for the time being)


String formatting (2)
• Keyword syntax:
>>> "a: {0}\tb: {1}\tc: {c}".format(1, 2, c=3)

'a: 1 b: 2 c: 3'

• Literal curly braces:


>>> "Braces: {{}}".format()

'Braces: {}'
String formatting (3)
• Attributes inside curly braces:
>>> lst = [1, 2, 3, 4, 5]

>>> "lst[3] = {0[3]}".format(lst)

'lst[3] = 4'

>>> dict = {"foo" : 1, "bar" : 2}

>>> "dict[\"foo\"] = {0[foo]}".format(dict)

'dict["foo"] = 1'
String formatting (4)
• Dot syntax inside curly braces:
>>> import string

>>> "lowercase letters:{0.ascii_lowercase}".format(

string)

'lowercase letters: abcdefghijklmnopqrstuvwxyz'

• Format specifiers:
>>> "pi: {0:15.8f}".format(math.pi)

'pi: 3.14159265'
Iterators (1)
• Iterators are a new kind of Python object
• Have been around for a while (since Python 2.2)
• Are used more extensively in Python 3.x
• Embody the notion of "sequence that you can take
the next item of"
Iterators (2)
• Iterators can be constructed from most Python
sequences using the iter() function:
>>> i = iter(range(10))

>>> i

<listiterator object at 0x81c30>


Iterators (3)
• Iterators have a __next__() special method:
>>> i = iter(range(10))

>>> i.__next__()

>>> i.__next__()

...
Iterators (4)
• Continuing:
>>> i.__next__()

>>> i.__next__()

>>> i.__next__()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

StopIteration
Iterators (5)
• Iterating through an iterator:
i = iter(range(5))

for item in i:

print(item)

4
Iterators (6)
• In Python 3.x, common functions like map() and
filter() return iterators, not lists
• However, you can turn an iterator into a list using
the list() built-in function
• Advantage of iterator: doesn't have to generate the
entire list all at once
The range() function
• The range() function no longer returns a list
• Instead, it's "lazy"; it evaluates its arguments as
they are needed (sort of like an iterator)
• Useful if you write e.g. range(1000000) and only
use the first (say) 1000 elements
• This is also doable in Python 2.x as the xrange()
function, which no longer exists in Python 3.x
Integer division
• Dividing two integers that don't divide evenly
returns a float:
1 / 2 # ==> 0.5
5 / 3 # ==> 1.66666...

• If you want truncating behavior, use the new //


operator:
1 // 2 # ==> 0
5 // 3 # ==> 1
Removed syntax
• Backtick syntax has been removed:

`foo` # used to be same as str(foo)

• <> no longer usable for !=


• from X import Y only legal at top level (yeah!)
• still works, but will be removed eventually
Syntax changes (1)
• True, False, None are reserved words
• Good news: can't assign to them
• Bad news: True still == 1 etc. (retarded)

• Binary literals
• Use 0b prefix (by analogy with 0x for hexadecimal)

0b11001 # ==> 25

• Also octal literals with 0o prefix (who cares?)


Syntax changes (2)
• Set literals
• {1, "foo", 4} is a set (not a dictionary)
• {} is still the empty dictionary; use set() for empty sets
• Set methods:
• intersection, union, difference

>>> {1, 2, 3}.intersection({1, 2, 5})


{1, 2}
• X in <set>

>>> 1 in {1, 2, 3}

True
Syntax changes (3)
• Set comprehensions:

>>> {x + y for x in range(3)


for y in range(3)}

{0, 1, 2, 3, 4}
• Note difference between this and corresponding
list comprehension: no duplicates!

>>> [x + y for x in range(3)


for y in range(3)]

[0, 1, 2, 1, 2, 3, 2, 3, 4]
Syntax changes (4)
• Dictionary comprehensions

>>> {k:v for (k, v) in


[("foo", 1), ("bar", 2), ("baz", 3)]}


{'baz': 3, 'foo': 1, 'bar': 2}


Syntax changes (5)
• Strings now use Unicode (16-bit) instead of ASCII
(8-bit) representation for characters
• Unicode characters can be typed in strings directly
as \uxxxx where x = hexadecimal digit

• Strings preceded by the character b are "byte


literals"; each character is one byte

>>> b"foo" # byte array: [102,111,111]


b'foo'

>>> bytes([102,111,111])

b'foo'
Syntax changes (6)
• Byte arrays can also have characters outside of
ASCII range:

>>> bytes([127,128,129])

b'\x7f\x80\x81'

>>> bytes([255,255,256])

Traceback (most recent call last):


File "<stdin>", line 1, in <module>


ValueError: bytes must be in range(0, 256)


Syntax changes (7)
• Function argument and return value annotations

>>> def foo(x:int, y:int) -> int:


... return x + y

>>> foo(3, 4)

7

>>> print(foo.__annotations__)

{'y': <class 'int'>, 'x': <class 'int'>,


'return': <class 'int'>}
Syntax changes (8)
• Python doesn't do anything with argument and
return value annotations except make them
available as the __annotations__ attribute of
the function

• Code introspection tools might use them for e.g.


some kind of run-time type checking

• What follows the : or -> doesn't have to be a type


name; it can be any python expression e.g.

def foo(x:"this is x",


y:"and this is y") -> 42: ...


Syntax changes (9)
• nonlocal statement
• Python allows nested functions:

def adder(x):

def add(y):

return x + y

return add

>>> add5 = adder(5)


>>> add5(10) # 15
• So far so good ...
Syntax changes (10)
• Sometimes want to modify variable in an outer
scope:

def counter(x):

count = x

def increment():

nonlocal count

count += 1

return count

return increment

>>> c = counter(0)

>>> c() # 1
Syntax changes (11)
• Iterable unpacking:

>>> a, *b, c = range(5)


>>> a

0

>>> c

4

>>> b

[1, 2, 3]
Built-in functions
• raw_input() is now just input()
• reduce() is now functools.reduce()
• dict.has_key() gone; use x in dict
Exceptions
• All exceptions must subclass from
BaseException

• raise MyException(args) instead of


raise MyException, args
(allowed in Python 2.x)
• Catching: except
MyException as e, not
except MyException, e
• Other changes too: see the online docs for the full
story
Function decorators (1)
• When you write:

@foo

def bar(x):

# ... whatever ...


• It's the same as:

def bar(x):

# ... whatever ...


bar = foo(bar) # "decorated" function


Function decorators (2)
• A very common decorator:

class Foo:

@staticmethod

def bar(x): # n.b. no "self"


return 2 * x

>>> Foo.bar(10)

20
• bar is a method of class Foo, not of Foo instances
• though it also works on instances
Summing up
• These changes remove language "warts", make
language cleaner and more consistent
• Many more extensions/changes than I've
discussed here!
• See online docs for comprehensive list
• Will take time to absorb all the changes
• Python 3.x provides "2to3" program to automate
most conversions

You might also like