90
Python WATs: Uncovering Odd Behavior

Python WATs: Uncovering Odd Behavior

Embed Size (px)

DESCRIPTION

Presented at PyGotham 2014.

Citation preview

Page 1: Python WATs: Uncovering Odd Behavior

Python WATs: Uncovering

Odd Behavior

Page 2: Python WATs: Uncovering Odd Behavior

Hacker School Alum Software Engineer at Venmo

!

@amygdalama mathamy.com

Who am I?

Page 3: Python WATs: Uncovering Odd Behavior

Allison Kaptur Tom Ballinger

Gary Bernhardt

Thanks!

Page 4: Python WATs: Uncovering Odd Behavior

Identity Mutability

Scope

Themes

Page 5: Python WATs: Uncovering Odd Behavior

a. Trivia b. Why? c. Tips

for theme in themes:

Page 6: Python WATs: Uncovering Odd Behavior

Identity

Page 7: Python WATs: Uncovering Odd Behavior

>  ""  is  ""  ???

Trivia

Page 8: Python WATs: Uncovering Odd Behavior

>  ""  is  ""  True

Trivia

Page 9: Python WATs: Uncovering Odd Behavior

>  0  is  0  ???

Trivia

Page 10: Python WATs: Uncovering Odd Behavior

>  0  is  0  True

Trivia

Page 11: Python WATs: Uncovering Odd Behavior

>  []  is  []  ???

Trivia

Page 12: Python WATs: Uncovering Odd Behavior

>  []  is  []  False

Trivia

Page 13: Python WATs: Uncovering Odd Behavior

>  {}  is  {}  ???

Trivia

Page 14: Python WATs: Uncovering Odd Behavior

>  {}  is  {}  False

Trivia

Page 15: Python WATs: Uncovering Odd Behavior

>  a  =  256  >  b  =  256  >  a  is  b  ???

Trivia

Page 16: Python WATs: Uncovering Odd Behavior

>  a  =  256  >  b  =  256  >  a  is  b  True

Trivia

Page 17: Python WATs: Uncovering Odd Behavior

>  a  =  257  >  b  =  257  >  a  is  b  ???

Trivia

Page 18: Python WATs: Uncovering Odd Behavior

>  a  =  257  >  b  =  257  >  a  is  b  False

Trivia

Page 19: Python WATs: Uncovering Odd Behavior

>  a  =  257;  b  =  257  >  a  is  b  ???

Trivia

Page 20: Python WATs: Uncovering Odd Behavior

>  a  =  257;  b  =  257  >  a  is  b  True

Trivia

Page 21: Python WATs: Uncovering Odd Behavior

a

Why?-­‐5

255

256

>  a  =  256  !

!

Page 22: Python WATs: Uncovering Odd Behavior

a

Why?-­‐5

255

256

…b

>  a  =  256  >  b  =  256  !

Page 23: Python WATs: Uncovering Odd Behavior

a

Why?-­‐5

255

256

…b

>  a  =  256  >  b  =  256  >  a  is  b  True

Page 24: Python WATs: Uncovering Odd Behavior

a

Why?…255256…257

>  a  =  257  !

!

Page 25: Python WATs: Uncovering Odd Behavior

a

Why?…255256…257257 b

>  a  =  257  >  b  =  257  !

Page 26: Python WATs: Uncovering Odd Behavior

a

Why?…255256…257257 b

>  a  =  257  >  b  =  257  >  a  is  b  False

Page 27: Python WATs: Uncovering Odd Behavior

>  a  =  257  >  b  =  257  >  id(a)  ==  id(b)  False

Why?

Page 28: Python WATs: Uncovering Odd Behavior

>  a  =  257;  b  =  257  >  id(a)  ==  id(b)  True

Why?

Page 29: Python WATs: Uncovering Odd Behavior

• Use == instead of is  to compare values

• Exceptions: • x  is  None  • tests for identity

Tips

Page 30: Python WATs: Uncovering Odd Behavior

Mutability

Page 31: Python WATs: Uncovering Odd Behavior

>  faves  =  ["cats",  "dragons"]  !

!

!

Trivia

Page 32: Python WATs: Uncovering Odd Behavior

>  faves  =  ["cats",  "dragons"]  >  temp  =  faves  !

!

Trivia

Page 33: Python WATs: Uncovering Odd Behavior

>  faves  =  ["cats",  "dragons"]  >  temp  =  faves  >  temp.append("rainbows")  !

Trivia

Page 34: Python WATs: Uncovering Odd Behavior

>  faves  =  ["cats",  "dragons"]  >  temp  =  faves  >  temp.append("rainbows")  >  temp  ???

Trivia

Page 35: Python WATs: Uncovering Odd Behavior

>  faves  =  ["cats",  "dragons"]  >  temp  =  faves  >  temp.append("rainbows")  >  temp  ["cats",  "dragons",  "rainbows"]

Trivia

Page 36: Python WATs: Uncovering Odd Behavior

>  faves  =  ["cats",  "dragons"]  >  temp  =  faves  >  temp.append("rainbows")  >  faves  ???

Trivia

Page 37: Python WATs: Uncovering Odd Behavior

>  faves  =  ["cats",  "dragons"]  >  temp  =  faves  >  temp.append("rainbows")  >  faves  ["cats",  "dragons",  "rainbows"]

Trivia

Page 38: Python WATs: Uncovering Odd Behavior

faves

Why?"cats"

"dragons"

>  faves  =  ["cats",  "dragons"]

Page 39: Python WATs: Uncovering Odd Behavior

faves

Why?"cats"

"dragons"

>  temp  =  faves

temp

Page 40: Python WATs: Uncovering Odd Behavior

faves

Why?"cats"

"dragons"

"rainbows"

>  temp.append("rainbows")

temp

Page 41: Python WATs: Uncovering Odd Behavior

• lists [] • dictionaries {} • sets ()

Tip: Mutable Objects

Page 42: Python WATs: Uncovering Odd Behavior

>  temp  =  faves[:]  >  temp  =  list(faves)

Tip: Make Real Copies

Page 43: Python WATs: Uncovering Odd Behavior

>  temp  =  []  >  for  element  in  faves:              temp.append(element)

Tip: Shallow Copy

Page 44: Python WATs: Uncovering Odd Behavior

>  faves  =  [["cats",  "dragons"]]  !

!

!

Tip: Deep Copy

Page 45: Python WATs: Uncovering Odd Behavior

>  faves  =  [["cats",  "dragons"]]  >  temp  =  faves[:]  !

!

Tip: Deep Copy

Page 46: Python WATs: Uncovering Odd Behavior

>  faves  =  [["cats",  "dragons"]]  >  temp  =  faves[:]  >  temp[0].append("rainbows")  !

Tip: Deep Copy

Page 47: Python WATs: Uncovering Odd Behavior

>  faves  =  [["cats",  "dragons"]]  >  temp  =  faves[:]  >  temp[0].append("rainbows")  >  faves  ???

Tip: Deep Copy

Page 48: Python WATs: Uncovering Odd Behavior

>  faves  =  [["cats",  "dragons"]]  >  temp  =  faves[:]  >  temp[0].append("rainbows")  >  faves  [["cats",  "dragons",  "rainbows"]]

Tip: Deep Copy

Page 49: Python WATs: Uncovering Odd Behavior

• For arbitrarily-nested lists, make deep copies

!

>  import  copy  >  temp  =  copy.deepcopy(faves)

Tip: Deep Copy

Page 50: Python WATs: Uncovering Odd Behavior

Mutable Default Arguments

Page 51: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):  !

Trivia

Page 52: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append(‘cat’)          return  l

Trivia

Page 53: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append(‘cat’)          return  l  !

>  append_cat()  ???  !

Trivia

Page 54: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append(‘cat’)          return  l  !

>  append_cat()  [‘cat’]  !

Trivia

Page 55: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append(‘cat’)          return  l  !

>  append_cat()  [‘cat’]  >  append_cat()  ???

Trivia

Page 56: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append(‘cat’)          return  l  !

>  append_cat()  [‘cat’]  >  append_cat()  [‘cat’,  ‘cat’]

Trivia

Page 57: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append(‘cat’)          return  l  !

>  append_cat.func_defaults  ???  

Why?

Page 58: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append(‘cat’)          return  l  !

>  append_cat.func_defaults  ([],)  

Why?

Page 59: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append('cat')          return  l  !

>  append_cat()  >  append_cat.func_defaults  ???

Why?

Page 60: Python WATs: Uncovering Odd Behavior

def  append_cat(l=[]):          l.append('cat')          return  l  !

>  append_cat()  >  append_cat.func_defaults  (['cat'],)

Why?

Page 61: Python WATs: Uncovering Odd Behavior

>  append_cat.func_defaults  (['cat'],)  !

!

Why?

Page 62: Python WATs: Uncovering Odd Behavior

>  append_cat.func_defaults  (['cat'],)  >  _[0].append('dragon')  !

Why?

Page 63: Python WATs: Uncovering Odd Behavior

>  append_cat.func_defaults  (['cat'],)  >  _[0].append('dragon')  >  append_cat()  ???

Why?

Page 64: Python WATs: Uncovering Odd Behavior

>  append_cat.func_defaults  (['cat'],)  >  _[0].append('dragon')  >  append_cat()  ['cat',  'dragon',  'cat']

Why?

Page 65: Python WATs: Uncovering Odd Behavior

def  append_cat(l=None):  !

!

!

Tip: Use None

Page 66: Python WATs: Uncovering Odd Behavior

def  append_cat(l=None):          if  l  is  None:                  l  =  []  !

Tip: Use None

Page 67: Python WATs: Uncovering Odd Behavior

def  append_cat(l=None):          if  l  is  None:                  l  =  []          l.append(‘cat')          return  l

Tip: Use None

Page 68: Python WATs: Uncovering Odd Behavior

def  sorting_hat(student,  cache={}):  !

!

!

!

!

!

Tip: Take Advantage!

Page 69: Python WATs: Uncovering Odd Behavior

def  sorting_hat(student,  cache={}):          if  student  in  cache:                  print  "Used  cache!"                  return  cache[student]          else:  !

!

Tip: Take Advantage!

Page 70: Python WATs: Uncovering Odd Behavior

def  sorting_hat(student,  cache={}):          if  student  in  cache:                  print  "Used  cache!"                  return  cache[student]          else:                  house  =  slow_alg(student)                  cache[student]  =  house                  return  house

Tip: Take Advantage!

Page 71: Python WATs: Uncovering Odd Behavior

>  sorting_hat('Amy  Hanlon')  'Ravenclaw'  !

!

!

!

Tip: Take Advantage!

Page 72: Python WATs: Uncovering Odd Behavior

>  sorting_hat('Amy  Hanlon')  'Ravenclaw'  >  sorting_hat('Amy  Hanlon')  Used  cache!  ‘Ravenclaw'  !

Tip: Take Advantage!

Page 73: Python WATs: Uncovering Odd Behavior

>  sorting_hat('Amy  Hanlon')  'Ravenclaw'  >  sorting_hat('Amy  Hanlon')  Used  cache!  ‘Ravenclaw'  >  sorting_hat.func_defaults  ({'Amy  Hanlon':  'Ravenclaw'},)

Tip: Take Advantage!

Page 74: Python WATs: Uncovering Odd Behavior

Scope

Page 75: Python WATs: Uncovering Odd Behavior

>  a  =  1  !

!

!

!

Trivia

Page 76: Python WATs: Uncovering Odd Behavior

>  a  =  1  >  def  foo():          return  a  !

!

Trivia

Page 77: Python WATs: Uncovering Odd Behavior

>  a  =  1  >  def  foo():          return  a  !

>  foo()  ???

Trivia

Page 78: Python WATs: Uncovering Odd Behavior

>  a  =  1  >  def  foo():          return  a  !

>  foo()  1

Trivia

Page 79: Python WATs: Uncovering Odd Behavior

Namespaces! !

• locals()  !

Why?

Page 80: Python WATs: Uncovering Odd Behavior

Namespaces! !

• locals()  • globals()        #  {'a'  :  1}  

Why?

Page 81: Python WATs: Uncovering Odd Behavior

Namespaces! !

• locals()  • globals()        #  {'a'  :  1}  • __builtins__

Why?

Page 82: Python WATs: Uncovering Odd Behavior

>  a  =  1  >  def  foo():          return  a  !

>  foo()  1

Trivia

Page 83: Python WATs: Uncovering Odd Behavior

>  a  =  1  >  def  foo():          a  +=  1          return  a  !

>  foo()  ???

Trivia

Page 84: Python WATs: Uncovering Odd Behavior

>  a  =  1  >  def  foo():          a  +=  1          return  a  !

>  foo()  UnboundLocalError:  local  variable  'a'  referenced  before  assignment

Trivia

Page 85: Python WATs: Uncovering Odd Behavior

“When you make an assignment to a variable in a scope, that variable becomes

local to that scope.”

Why?

Page 86: Python WATs: Uncovering Odd Behavior

Why?>  a  =  1  >  def  foo():          #  a  +=  1          a  =  a  +  1          return  a

Page 87: Python WATs: Uncovering Odd Behavior

>  a  =  1  >  def  foo():          global  a          a  +=  1          return  a  >  foo()  2  >  a  2

Tip: Use global

Page 88: Python WATs: Uncovering Odd Behavior

>  def  foo(a):          a  +=  1          return  a  >  a  =  1  >  a  =  foo(a)  2

Tip: Don’t Use global

Page 89: Python WATs: Uncovering Odd Behavior

Links• https://docs.python.org/3/ • http://eli.thegreenplace.net/ • http://akaptur.github.io/blog/

2013/10/29/a-python-puzzle/ • http://mathamy.com/python-wats-

mutable-default-arguments.html

Page 90: Python WATs: Uncovering Odd Behavior

Thank you! Questions?