Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Python WATs:
Uncovering
Odd Behavior
Hacker School Alum
Software Engineer at Venmo
!
@amygdalama
mathamy.com
Who am I?
Allison Kaptur
Tom Ballinger
Gary Bernhardt
Thanks!
Identity
Mutability
Scope
Themes
a. Trivia
b. Why?
c. Tips
for theme in themes:
Identity
>	
  ""	
  is	
  ""	
  
???
Trivia
>	
  ""	
  is	
  ""	
  
True
Trivia
>	
  0	
  is	
  0	
  
???
Trivia
>	
  0	
  is	
  0	
  
True
Trivia
>	
  []	
  is	
  []	
  
???
Trivia
>	
  []	
  is	
  []	
  
False
Trivia
>	
  {}	
  is	
  {}	
  
???
Trivia
>	
  {}	
  is	
  {}	
  
False
Trivia
>	
  a	
  =	
  256	
  
>	
  b	
  =	
  256	
  
>	
  a	
  is	
  b	
  
???
Trivia
>	
  a	
  =	
  256	
  
>	
  b	
  =	
  256	
  
>	
  a	
  is	
  b	
  
True
Trivia
>	
  a	
  =	
  257	
  
>	
  b	
  =	
  257	
  
>	
  a	
  is	
  b	
  
???
Trivia
>	
  a	
  =	
  257	
  
>	
  b	
  =	
  257	
  
>	
  a	
  is	
  b	
  
False
Trivia
>	
  a	
  =	
  257;	
  b	
  =	
  257	
  
>	
  a	
  is	
  b	
  
???
Trivia
>	
  a	
  =	
  257;	
  b	
  =	
  257	
  
>	
  a	
  is	
  b	
  
True
Trivia
a
Why?-­‐5
…
255
256
…
>	
  a	
  =	
  256	
  
!
!
a
Why?-­‐5
…
255
256
…
b
>	
  a	
  =	
  256	
  
>	
  b	
  =	
  256	
  
!
a
Why?-­‐5
…
255
256
…
b
>	
  a	
  =	
  256	
  
>	
  b	
  =	
  256	
  
>	
  a	
  is	
  b	
  
True
a
Why?…
255
256
…
257
>	
  a	
  =	
  257	
  
!
!
a
Why?…
255
256
…
257
257 b
>	
  a	
  =	
  257	
  
>	
  b	
  =	
  257	
  
!
a
Why?…
255
256
…
257
257 b
>	
  a	
  =	
  257	
  
>	
  b	
  =	
  257	
  
>	
  a	
  is	
  b	
  
False
>	
  a	
  =	
  257	
  
>	
  b	
  =	
  257	
  
>	
  id(a)	
  ==	
  id(b)	
  
False
Why?
>	
  a	
  =	
  257;	
  b	
  =	
  257	
  
>	
  id(a)	
  ==	
  id(b)	
  
True
Why?
• Use == instead of is	
  to
compare values	

• Exceptions:	

• x	
  is	
  None	
  
• tests for identity
Tips
Mutability
>	
  faves	
  =	
  ["cats",	
  "dragons"]	
  
!
!
!
Trivia
>	
  faves	
  =	
  ["cats",	
  "dragons"]	
  
>	
  temp	
  =	
  faves	
  
!
!
Trivia
>	
  faves	
  =	
  ["cats",	
  "dragons"]	
  
>	
  temp	
  =	
  faves	
  
>	
  temp.append("rainbows")	
  
!
Trivia
>	
  faves	
  =	
  ["cats",	
  "dragons"]	
  
>	
  temp	
  =	
  faves	
  
>	
  temp.append("rainbows")	
  
>	
  temp	
  
?...
>	
  faves	
  =	
  ["cats",	
  "dragons"]	
  
>	
  temp	
  =	
  faves	
  
>	
  temp.append("rainbows")	
  
>	
  temp	
  
[...
>	
  faves	
  =	
  ["cats",	
  "dragons"]	
  
>	
  temp	
  =	
  faves	
  
>	
  temp.append("rainbows")	
  
>	
  faves	
  
...
>	
  faves	
  =	
  ["cats",	
  "dragons"]	
  
>	
  temp	
  =	
  faves	
  
>	
  temp.append("rainbows")	
  
>	
  faves	
  
...
faves
Why?
"cats"
"dragons"
>	
  faves	
  =	
  ["cats",	
  "dragons"]
faves
Why?
"cats"
"dragons"
>	
  temp	
  =	
  faves
temp
faves
Why?
"cats"
"dragons"
"rainbows"
>	
  temp.append("rainbows")
temp
• lists []	

• dictionaries {}	

• sets ()
Tip: Mutable Objects
>	
  temp	
  =	
  faves[:]	
  
>	
  temp	
  =	
  list(faves)
Tip: Make Real Copies
>	
  temp	
  =	
  []	
  
>	
  for	
  element	
  in	
  faves:	
  
	
  	
  	
  	
  	
  	
  temp.append(element)
Tip: Shallow...
>	
  faves	
  =	
  [["cats",	
  "dragons"]]	
  
!
!
!
Tip: Deep Copy
>	
  faves	
  =	
  [["cats",	
  "dragons"]]	
  
>	
  temp	
  =	
  faves[:]	
  
!
!
Tip: Deep Copy
>	
  faves	
  =	
  [["cats",	
  "dragons"]]	
  
>	
  temp	
  =	
  faves[:]	
  
>	
  temp[0].append("rainbows")	
  
!
Tip: ...
>	
  faves	
  =	
  [["cats",	
  "dragons"]]	
  
>	
  temp	
  =	
  faves[:]	
  
>	
  temp[0].append("rainbows")	
  
>	
  fa...
>	
  faves	
  =	
  [["cats",	
  "dragons"]]	
  
>	
  temp	
  =	
  faves[:]	
  
>	
  temp[0].append("rainbows")	
  
>	
  fa...
• For arbitrarily-nested
lists, make deep copies	

!
>	
  import	
  copy	
  
>	
  temp	
  =	
  copy.deepcopy(faves)
Tip: D...
Mutable Default
Arguments
def	
  append_cat(l=[]):	
  
!
Trivia
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append(‘cat’)	
  
	
  	
  	
  	
  return	
  l
Trivia
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append(‘cat’)	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat()	
  
?...
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append(‘cat’)	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat()	
  
[...
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append(‘cat’)	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat()	
  
[...
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append(‘cat’)	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat()	
  
[...
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append(‘cat’)	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat.func_de...
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append(‘cat’)	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat.func_de...
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append('cat')	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat()	
  
>...
def	
  append_cat(l=[]):	
  
	
  	
  	
  	
  l.append('cat')	
  
	
  	
  	
  	
  return	
  l	
  
!
>	
  append_cat()	
  
>...
>	
  append_cat.func_defaults	
  
(['cat'],)	
  
!
!
Why?
>	
  append_cat.func_defaults	
  
(['cat'],)	
  
>	
  _[0].append('dragon')	
  
!
Why?
>	
  append_cat.func_defaults	
  
(['cat'],)	
  
>	
  _[0].append('dragon')	
  
>	
  append_cat()	
  
???
Why?
>	
  append_cat.func_defaults	
  
(['cat'],)	
  
>	
  _[0].append('dragon')	
  
>	
  append_cat()	
  
['cat',	
  'dragon',...
def	
  append_cat(l=None):	
  
!
!
!
Tip: Use None
def	
  append_cat(l=None):	
  
	
  	
  	
  	
  if	
  l	
  is	
  None:	
  
	
  	
  	
  	
  	
  	
  	
  	
  l	
  =	
  []	
  ...
def	
  append_cat(l=None):	
  
	
  	
  	
  	
  if	
  l	
  is	
  None:	
  
	
  	
  	
  	
  	
  	
  	
  	
  l	
  =	
  []	
  ...
def	
  sorting_hat(student,	
  cache={}):	
  
!
!
!
!
!
!
Tip: Take Advantage!
def	
  sorting_hat(student,	
  cache={}):	
  
	
  	
  	
  	
  if	
  student	
  in	
  cache:	
  
	
  	
  	
  	
  	
  	
  	
...
def	
  sorting_hat(student,	
  cache={}):	
  
	
  	
  	
  	
  if	
  student	
  in	
  cache:	
  
	
  	
  	
  	
  	
  	
  	
...
>	
  sorting_hat('Amy	
  Hanlon')	
  
'Ravenclaw'	
  
!
!
!
!
Tip: Take Advantage!
>	
  sorting_hat('Amy	
  Hanlon')	
  
'Ravenclaw'	
  
>	
  sorting_hat('Amy	
  Hanlon')	
  
Used	
  cache!	
  
‘Ravenclaw'...
>	
  sorting_hat('Amy	
  Hanlon')	
  
'Ravenclaw'	
  
>	
  sorting_hat('Amy	
  Hanlon')	
  
Used	
  cache!	
  
‘Ravenclaw'...
Scope
>	
  a	
  =	
  1	
  
!
!
!
!
Trivia
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  return	
  a	
  
!
!
Trivia
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  return	
  a	
  
!
>	
  foo()	
  
???
Trivia
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  return	
  a	
  
!
>	
  foo()	
  
1
Trivia
Namespaces!	

!
• locals()	
  
!
Why?
Namespaces!	

!
• locals()	
  
• globals()	
  	
  	
  	
  #	
  {'a'	
  :	
  1}	
  
Why?
Namespaces!	

!
• locals()	
  
• globals()	
  	
  	
  	
  #	
  {'a'	
  :	
  1}	
  
• __builtins__
Why?
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  return	
  a	
  
!
>	
  foo()	
  
1
Trivia
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  a	
  +=	
  1	
  
	
  	
  	
  	
  return	
  a	
  
!
>	
  foo()	...
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  a	
  +=	
  1	
  
	
  	
  	
  	
  return	
  a	
  
!
>	
  foo()	...
“When you make an
assignment to a variable in a
scope, that variable becomes
local to that scope.”
Why?
Why?
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  #	
  a	
  +=	
  1	
  
	
  	
  	
  	
  a	
  =	
  a	
  +	
 ...
>	
  a	
  =	
  1	
  
>	
  def	
  foo():	
  
	
  	
  	
  	
  global	
  a	
  
	
  	
  	
  	
  a	
  +=	
  1	
  
	
  	
  	
  	...
>	
  def	
  foo(a):	
  
	
  	
  	
  	
  a	
  +=	
  1	
  
	
  	
  	
  	
  return	
  a	
  
>	
  a	
  =	
  1	
  
>	
  a	
  =	...
Links
• https://docs.python.org/3/	

• http://eli.thegreenplace.net/	

• http://akaptur.github.io/blog/
2013/10/29/a-pytho...
Thank you!
Questions?
Upcoming SlideShare
Loading in …5
×

Python WATs: Uncovering Odd Behavior

2,003 views

Published on

Presented at PyGotham 2014.

Published in: Engineering
  • Be the first to comment

Python WATs: Uncovering Odd Behavior

  1. 1. Python WATs: Uncovering Odd Behavior
  2. 2. Hacker School Alum Software Engineer at Venmo ! @amygdalama mathamy.com Who am I?
  3. 3. Allison Kaptur Tom Ballinger Gary Bernhardt Thanks!
  4. 4. Identity Mutability Scope Themes
  5. 5. a. Trivia b. Why? c. Tips for theme in themes:
  6. 6. Identity
  7. 7. >  ""  is  ""   ??? Trivia
  8. 8. >  ""  is  ""   True Trivia
  9. 9. >  0  is  0   ??? Trivia
  10. 10. >  0  is  0   True Trivia
  11. 11. >  []  is  []   ??? Trivia
  12. 12. >  []  is  []   False Trivia
  13. 13. >  {}  is  {}   ??? Trivia
  14. 14. >  {}  is  {}   False Trivia
  15. 15. >  a  =  256   >  b  =  256   >  a  is  b   ??? Trivia
  16. 16. >  a  =  256   >  b  =  256   >  a  is  b   True Trivia
  17. 17. >  a  =  257   >  b  =  257   >  a  is  b   ??? Trivia
  18. 18. >  a  =  257   >  b  =  257   >  a  is  b   False Trivia
  19. 19. >  a  =  257;  b  =  257   >  a  is  b   ??? Trivia
  20. 20. >  a  =  257;  b  =  257   >  a  is  b   True Trivia
  21. 21. a Why?-­‐5 … 255 256 … >  a  =  256   ! !
  22. 22. a Why?-­‐5 … 255 256 … b >  a  =  256   >  b  =  256   !
  23. 23. a Why?-­‐5 … 255 256 … b >  a  =  256   >  b  =  256   >  a  is  b   True
  24. 24. a Why?… 255 256 … 257 >  a  =  257   ! !
  25. 25. a Why?… 255 256 … 257 257 b >  a  =  257   >  b  =  257   !
  26. 26. a Why?… 255 256 … 257 257 b >  a  =  257   >  b  =  257   >  a  is  b   False
  27. 27. >  a  =  257   >  b  =  257   >  id(a)  ==  id(b)   False Why?
  28. 28. >  a  =  257;  b  =  257   >  id(a)  ==  id(b)   True Why?
  29. 29. • Use == instead of is  to compare values • Exceptions: • x  is  None   • tests for identity Tips
  30. 30. Mutability
  31. 31. >  faves  =  ["cats",  "dragons"]   ! ! ! Trivia
  32. 32. >  faves  =  ["cats",  "dragons"]   >  temp  =  faves   ! ! Trivia
  33. 33. >  faves  =  ["cats",  "dragons"]   >  temp  =  faves   >  temp.append("rainbows")   ! Trivia
  34. 34. >  faves  =  ["cats",  "dragons"]   >  temp  =  faves   >  temp.append("rainbows")   >  temp   ??? Trivia
  35. 35. >  faves  =  ["cats",  "dragons"]   >  temp  =  faves   >  temp.append("rainbows")   >  temp   ["cats",  "dragons",  "rainbows"] Trivia
  36. 36. >  faves  =  ["cats",  "dragons"]   >  temp  =  faves   >  temp.append("rainbows")   >  faves   ??? Trivia
  37. 37. >  faves  =  ["cats",  "dragons"]   >  temp  =  faves   >  temp.append("rainbows")   >  faves   ["cats",  "dragons",  "rainbows"] Trivia
  38. 38. faves Why? "cats" "dragons" >  faves  =  ["cats",  "dragons"]
  39. 39. faves Why? "cats" "dragons" >  temp  =  faves temp
  40. 40. faves Why? "cats" "dragons" "rainbows" >  temp.append("rainbows") temp
  41. 41. • lists [] • dictionaries {} • sets () Tip: Mutable Objects
  42. 42. >  temp  =  faves[:]   >  temp  =  list(faves) Tip: Make Real Copies
  43. 43. >  temp  =  []   >  for  element  in  faves:              temp.append(element) Tip: Shallow Copy
  44. 44. >  faves  =  [["cats",  "dragons"]]   ! ! ! Tip: Deep Copy
  45. 45. >  faves  =  [["cats",  "dragons"]]   >  temp  =  faves[:]   ! ! Tip: Deep Copy
  46. 46. >  faves  =  [["cats",  "dragons"]]   >  temp  =  faves[:]   >  temp[0].append("rainbows")   ! Tip: Deep Copy
  47. 47. >  faves  =  [["cats",  "dragons"]]   >  temp  =  faves[:]   >  temp[0].append("rainbows")   >  faves   ??? Tip: Deep Copy
  48. 48. >  faves  =  [["cats",  "dragons"]]   >  temp  =  faves[:]   >  temp[0].append("rainbows")   >  faves   [["cats",  "dragons",  "rainbows"]] Tip: Deep Copy
  49. 49. • For arbitrarily-nested lists, make deep copies ! >  import  copy   >  temp  =  copy.deepcopy(faves) Tip: Deep Copy
  50. 50. Mutable Default Arguments
  51. 51. def  append_cat(l=[]):   ! Trivia
  52. 52. def  append_cat(l=[]):          l.append(‘cat’)          return  l Trivia
  53. 53. def  append_cat(l=[]):          l.append(‘cat’)          return  l   ! >  append_cat()   ???   ! Trivia
  54. 54. def  append_cat(l=[]):          l.append(‘cat’)          return  l   ! >  append_cat()   [‘cat’]   ! Trivia
  55. 55. def  append_cat(l=[]):          l.append(‘cat’)          return  l   ! >  append_cat()   [‘cat’]   >  append_cat()   ??? Trivia
  56. 56. def  append_cat(l=[]):          l.append(‘cat’)          return  l   ! >  append_cat()   [‘cat’]   >  append_cat()   [‘cat’,  ‘cat’] Trivia
  57. 57. def  append_cat(l=[]):          l.append(‘cat’)          return  l   ! >  append_cat.func_defaults   ???   Why?
  58. 58. def  append_cat(l=[]):          l.append(‘cat’)          return  l   ! >  append_cat.func_defaults   ([],)   Why?
  59. 59. def  append_cat(l=[]):          l.append('cat')          return  l   ! >  append_cat()   >  append_cat.func_defaults   ??? Why?
  60. 60. def  append_cat(l=[]):          l.append('cat')          return  l   ! >  append_cat()   >  append_cat.func_defaults   (['cat'],) Why?
  61. 61. >  append_cat.func_defaults   (['cat'],)   ! ! Why?
  62. 62. >  append_cat.func_defaults   (['cat'],)   >  _[0].append('dragon')   ! Why?
  63. 63. >  append_cat.func_defaults   (['cat'],)   >  _[0].append('dragon')   >  append_cat()   ??? Why?
  64. 64. >  append_cat.func_defaults   (['cat'],)   >  _[0].append('dragon')   >  append_cat()   ['cat',  'dragon',  'cat'] Why?
  65. 65. def  append_cat(l=None):   ! ! ! Tip: Use None
  66. 66. def  append_cat(l=None):          if  l  is  None:                  l  =  []   ! Tip: Use None
  67. 67. def  append_cat(l=None):          if  l  is  None:                  l  =  []          l.append(‘cat')          return  l Tip: Use None
  68. 68. def  sorting_hat(student,  cache={}):   ! ! ! ! ! ! Tip: Take Advantage!
  69. 69. def  sorting_hat(student,  cache={}):          if  student  in  cache:                  print  "Used  cache!"                  return  cache[student]          else:   ! ! Tip: Take Advantage!
  70. 70. 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!
  71. 71. >  sorting_hat('Amy  Hanlon')   'Ravenclaw'   ! ! ! ! Tip: Take Advantage!
  72. 72. >  sorting_hat('Amy  Hanlon')   'Ravenclaw'   >  sorting_hat('Amy  Hanlon')   Used  cache!   ‘Ravenclaw'   ! Tip: Take Advantage!
  73. 73. >  sorting_hat('Amy  Hanlon')   'Ravenclaw'   >  sorting_hat('Amy  Hanlon')   Used  cache!   ‘Ravenclaw'   >  sorting_hat.func_defaults   ({'Amy  Hanlon':  'Ravenclaw'},) Tip: Take Advantage!
  74. 74. Scope
  75. 75. >  a  =  1   ! ! ! ! Trivia
  76. 76. >  a  =  1   >  def  foo():          return  a   ! ! Trivia
  77. 77. >  a  =  1   >  def  foo():          return  a   ! >  foo()   ??? Trivia
  78. 78. >  a  =  1   >  def  foo():          return  a   ! >  foo()   1 Trivia
  79. 79. Namespaces! ! • locals()   ! Why?
  80. 80. Namespaces! ! • locals()   • globals()        #  {'a'  :  1}   Why?
  81. 81. Namespaces! ! • locals()   • globals()        #  {'a'  :  1}   • __builtins__ Why?
  82. 82. >  a  =  1   >  def  foo():          return  a   ! >  foo()   1 Trivia
  83. 83. >  a  =  1   >  def  foo():          a  +=  1          return  a   ! >  foo()   ??? Trivia
  84. 84. >  a  =  1   >  def  foo():          a  +=  1          return  a   ! >  foo()   UnboundLocalError:  local   variable  'a'  referenced  before   assignment Trivia
  85. 85. “When you make an assignment to a variable in a scope, that variable becomes local to that scope.” Why?
  86. 86. Why? >  a  =  1   >  def  foo():          #  a  +=  1          a  =  a  +  1          return  a
  87. 87. >  a  =  1   >  def  foo():          global  a          a  +=  1          return  a   >  foo()   2   >  a   2 Tip: Use global
  88. 88. >  def  foo(a):          a  +=  1          return  a   >  a  =  1   >  a  =  foo(a)   2 Tip: Don’t Use global
  89. 89. 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
  90. 90. Thank you! Questions?

×