Slide 1

Slide 1 text

Python Tips, Tricks, and Hidden Features (using type, collections, meta-classes, and more)

Slide 2

Slide 2 text

I'm Dustin http://github.com/di

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Irked.

Slide 5

Slide 5 text

Irked. >>> j = object() >>> j.hi = 'there' Traceback (most recent call last): File "", line 1, in AttributeError: 'object' object has no attribute 'hi'

Slide 6

Slide 6 text

type

Slide 7

Slide 7 text

type >>> type(['foo', 'bar'])

Slide 8

Slide 8 text

type >>> type(['foo', 'bar'])

Slide 9

Slide 9 text

type >>> type(list)

Slide 10

Slide 10 text

type >>> type(list)

Slide 11

Slide 11 text

type >>> type(type)

Slide 12

Slide 12 text

type >>> type(type)

Slide 13

Slide 13 text

type >>> type(None)

Slide 14

Slide 14 text

type >>> type(None)

Slide 15

Slide 15 text

type >>> def func(): ... pass ... >>> type(func)

Slide 16

Slide 16 text

type >>> def func(): ... pass ... >>> type(func)

Slide 17

Slide 17 text

type >>> import types >>> dir(types) ['BooleanType', 'BufferType', 'BuiltinFunctionType', 'BuiltinMethodType', 'ClassType', 'CodeType', 'ComplexType', 'DictProxyType', 'DictType', 'DictionaryType', 'EllipsisType', 'FileType', 'FloatType', 'FrameType', 'FunctionType', 'GeneratorType', 'GetSetDescriptorType', 'InstanceType', 'IntType', 'LambdaType', 'ListType', 'LongType', 'MemberDescriptorType', 'MethodType', 'ModuleType', 'NoneType', 'NotImplementedType', 'ObjectType', 'SliceType', 'StringType', 'StringTypes', 'TracebackType', 'TupleType', 'TypeType', 'UnboundMethodType', 'UnicodeType', 'XRangeType', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__']

Slide 18

Slide 18 text

type >>> import types >>> type(types)

Slide 19

Slide 19 text

type >>> import types >>> type(types) >>> type(types) == types.ModuleType True

Slide 20

Slide 20 text

type >>> class FooClass: ... pass ... >>> type(FooClass)

Slide 21

Slide 21 text

type >>> class FooClass: # Python 2.7 ... pass ... >>> type(FooClass)

Slide 22

Slide 22 text

type >>> class FooClass: # Python 3.4 ... pass ... >>> type(FooClass)

Slide 23

Slide 23 text

type >>> class FooClass(object): # Python 2.7 ... pass ... >>> type(FooClass)

Slide 24

Slide 24 text

type >>> type(42) is int True >>> type(42)() 0 >>> int() 0

Slide 25

Slide 25 text

type >>> j = type()

Slide 26

Slide 26 text

type >>> j = type() Traceback (most recent call last): File "", line 1, in TypeError: type() takes 1 or 3 arguments

Slide 27

Slide 27 text

type >>> j = type('FooClass', (object,), {'hi': 'there'}) >>> type(j)

Slide 28

Slide 28 text

type >>> j = type('FooClass', (object,), {'hi': 'there'}) >>> j.hi 'there'

Slide 29

Slide 29 text

type >>> j = type('', (object,), {'hi': 'there'}) >>> j.hi 'there'

Slide 30

Slide 30 text

type >>> j = type('', (), {'hi': 'there'}) >>> j.hi 'there'

Slide 31

Slide 31 text

type >>> j = type('', (), {}) >>> j.hi = 'there' >>> j.hi 'there'

Slide 32

Slide 32 text

type >>> j = object() >>> j.hi = 'there' Traceback (most recent call last): File "", line 1, in AttributeError: 'object' object has no attribute 'hi'

Slide 33

Slide 33 text

type >>> class FooClass(): ... pass ... >>> hasattr(FooClass(), '__dict__') True >>> hasattr(object(), '__dict__') False

Slide 34

Slide 34 text

type >>> from stackoverflow import getsize¹ >>> getsize(object()) 16 >>> getsize(0) 24 >>> getsize(dict()) 280 >>> getsize(FooClass()) 344 1 http://stackoverflow.com/a/30316760/4842627

Slide 35

Slide 35 text

Questions?

Slide 36

Slide 36 text

collections

Slide 37

Slide 37 text

collections >>> def group(names): ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 38

Slide 38 text

collections >>> def group(names): ... d = {} ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 39

Slide 39 text

collections >>> def group(names): ... d = {} ... for name in names: ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 40

Slide 40 text

collections >>> def group(names): ... d = {} ... for name in names: ... key = len(name) ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 41

Slide 41 text

collections >>> def group(names): ... d = {} ... for name in names: ... key = len(name) ... if key not in d: ... d[key] = [] ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 42

Slide 42 text

collections >>> def group(names): ... d = {} ... for name in names: ... key = len(name) ... if key not in d: ... d[key] = [] ... d[key].append(name) ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 43

Slide 43 text

collections >>> def group(names): ... d = {} ... for name in names: ... key = len(name) ... if key not in d: ... d[key] = [] ... d[key].append(name) ... return d ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 44

Slide 44 text

collections >>> def group(names): ... d = {} ... for name in names: ... key = len(name) ... d.setdefault(key, []).append(name) ... return d ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 45

Slide 45 text

collections >>> def group(names): ... return { ... length: [ ... name for name in names if len(name) == length ... ] ... for length in {len(name) for name in names} ... } ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 46

Slide 46 text

collections.defaultdict >>> from collections import defaultdict >>> def group(names): ... d = defaultdict(list) ... for name in names: ... key = len(name) ... d[key].append(name) ... return dict(d) ... >>> group(['tom', 'dick', 'harry', 'guido']) {3: ['tom'], 4: ['dick'], 5: ['harry', 'guido']}   

Slide 47

Slide 47 text

collections.defaultdict trie: an ordered tree data structure that is used to store a dynamic set or associative array where the keys are usually strings2. e.g.: "peter piper picked a peck of pickled peppers" 2 https://en.wikipedia.org/wiki/Trie

Slide 48

Slide 48 text

collections.defaultdict >>> trie = ... >>> trie['b']['a']['r'] = True >>> trie['b']['a']['r'] == True True >>> trie['f']['o']['o'] == True False >>> trie {'b': {'a': {'r': True}}}

Slide 49

Slide 49 text

collections.defaultdict >>> trie = {} >>> trie['b']['a']['r'] = True Traceback (most recent call last): File "", line 1, in KeyError: 'b'

Slide 50

Slide 50 text

collections.defaultdict >>> from collections import defaultdict >>> trie = defaultdict(lambda: defaultdict(dict)) >>> trie['b']['a']['r'] = True >>> trie['b']['a']['r'] == True True

Slide 51

Slide 51 text

collections.defaultdict >>> from collections import defaultdict >>> trie = defaultdict(lambda: defaultdict(dict)) >>> trie['b']['a']['r'] = True >>> trie['b']['a']['r'] == True True >>> trie['f']['o']['o'] == True Traceback (most recent call last): File "", line 1, in KeyError: 'o'

Slide 52

Slide 52 text

collections.defaultdict >>> from collections import defaultdict >>> trie = defaultdict(lambda: defaultdict(dict)) >>> trie['t']['r']['i']['e'] = True Traceback (most recent call last): File "", line 1, in KeyError: 'i'

Slide 53

Slide 53 text

collections.defaultdict >>> from collections import defaultdict >>> trie = defaultdict(lambda: defaultdict( ... lambda: defaultdict(lambda: defaultdict( ... lambda: defaultdict(lambda: defaultdict( ... dict))))))

Slide 54

Slide 54 text

collections.defaultdict >>> from collections import defaultdict >>> infinitedict = lambda: defaultdict(infinitedict) >>> trie = infinitedict() >>> trie['b']['a']['r'] = True >>> trie['b']['a']['r'] == True True >>> trie['f']['o']['o'] == True False

Slide 55

Slide 55 text

collections.defaultdict >>> from collections import defaultdict >>> def infinitedict(): ... return defaultdict(infinitedict) ... >>> trie = infinitedict() >>> trie['b']['a']['r'] = True >>> trie['b']['a']['r'] == True True >>> trie['f']['o']['o'] == True False

Slide 56

Slide 56 text

collections >>> def count(names): ... >>> count(['beetlejuice', 'beetlejuice', 'guido']) {'beetlejuice': 2, 'guido': 1}

Slide 57

Slide 57 text

collections >>> from collections import defaultdict >>> def count(names): ... d = defaultdict(int) ... >>> count(['beetlejuice', 'beetlejuice', 'guido']) {'beetlejuice': 2, 'guido': 1}

Slide 58

Slide 58 text

collections >>> from collections import defaultdict >>> def count(names): ... d = defaultdict(int) ... for name in names: ... d[name] += 1 ... >>> count(['beetlejuice', 'beetlejuice', 'guido']) {'beetlejuice': 2, 'guido': 1}

Slide 59

Slide 59 text

collections >>> from collections import defaultdict >>> def count(names): ... d = defaultdict(int) ... for name in names: ... d[name] += 1 ... return dict(d) ... >>> count(['beetlejuice', 'beetlejuice', 'guido']) {'beetlejuice': 2, 'guido': 1}

Slide 60

Slide 60 text

collections.Counter >>> from collections import Counter >>> def count(names): ... return dict(Counter(names)) ... >>> count(['beetlejuice', 'beetlejuice', 'guido']) {'beetlejuice': 2, 'guido': 1}

Slide 61

Slide 61 text

Questions?

Slide 62

Slide 62 text

Metaclasses

Slide 63

Slide 63 text

Metaclasses >>> class FooClass(): ... pass ...

Slide 64

Slide 64 text

Metaclasses >>> class FooClass(): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b False

Slide 65

Slide 65 text

Metaclasses >>> class Singleton(): ... >>> class FooClass(Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 66

Slide 66 text

Metaclasses >>> class Singleton(): ... _instance = None ... >>> class FooClass(Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 67

Slide 67 text

Metaclasses >>> class Singleton(): ... _instance = None ... def __new__(cls, *args, **kwargs): ... >>> class FooClass(Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 68

Slide 68 text

Metaclasses >>> class Singleton(): ... _instance = None ... def __new__(cls, *args, **kwargs): ... if not cls._instance: ... >>> class FooClass(Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 69

Slide 69 text

Metaclasses >>> class Singleton(): ... _instance = None ... def __new__(cls, *args, **kwargs): ... if not cls._instance: ... cls._instance = object.__new__(cls, *args, **kwargs) ... >>> class FooClass(Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 70

Slide 70 text

Metaclasses >>> class Singleton(): ... _instance = None ... def __new__(cls, *args, **kwargs): ... if not cls._instance: ... cls._instance = object.__new__(cls, *args, **kwargs) ... return cls._instance ... >>> class FooClass(Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 71

Slide 71 text

Metaclasses classes : instances : : metaclasses : classes

Slide 72

Slide 72 text

Metaclasses >>> j = type('FooClass', (object,), {'hi': 'there'}) >>> type(j)

Slide 73

Slide 73 text

Metaclasses >>> j = type('FooClass', (object,), {'hi': 'there'}) >>> type(j) >>> type(j())

Slide 74

Slide 74 text

Metaclasses >>> class MyMeta(type): ... pass ...

Slide 75

Slide 75 text

Metaclasses >>> class MyMeta(type): ... pass ... >>> class FooClass(metaclass=MyMeta): ... pass ...

Slide 76

Slide 76 text

Metaclasses >>> class MyMeta(type): ... pass ... >>> class FooClass(object): # Python 2.7 ... __metaclass__ = MyMeta ...

Slide 77

Slide 77 text

Metaclasses >>> class MyMeta(type): ... def __new__(meta, name, bases, attrs): ... return super().__new__(meta, name, bases, attrs) ... >>> class FooClass(metaclass=MyMeta): ... pass ...

Slide 78

Slide 78 text

Metaclasses >>> class MyMeta(type): ... def __new__(meta, name, bases, attrs): ... print('New {}'.format(name)) ... return super().__new__(meta, name, bases, attrs) ... >>> class FooClass(metaclass=MyMeta): ... pass ... New FooClass

Slide 79

Slide 79 text

Metaclasses >>> class MyMeta(type): ... def __call__(cls, *args, **kwargs): ... print('Call {}'.format(cls.__name__)) ... return super().__call__(*args, **kwargs) ... >>> class FooClass(metaclass=MyMeta): ... pass ... >>> f = FooClass() Call FooClass   

Slide 80

Slide 80 text

Metaclasses >>> class Singleton(type): ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 81

Slide 81 text

Metaclasses >>> class Singleton(type): ... def __new__(meta, name, bases, attrs): ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 82

Slide 82 text

Metaclasses >>> class Singleton(type): ... def __new__(meta, name, bases, attrs): ... attrs['_instance'] = None ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 83

Slide 83 text

Metaclasses >>> class Singleton(type): ... def __new__(meta, name, bases, attrs): ... attrs['_instance'] = None ... return super().__new__(meta, name, bases, attrs) ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 84

Slide 84 text

Metaclasses >>> class Singleton(type): ... def __new__(meta, name, bases, attrs): ... attrs['_instance'] = None ... return super().__new__(meta, name, bases, attrs) ... def __call__(cls, *args, **kwargs): ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 85

Slide 85 text

Metaclasses >>> class Singleton(type): ... def __new__(meta, name, bases, attrs): ... attrs['_instance'] = None ... return super().__new__(meta, name, bases, attrs) ... def __call__(cls, *args, **kwargs): ... if not cls._instance: ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 86

Slide 86 text

Metaclasses >>> class Singleton(type): ... def __new__(meta, name, bases, attrs): ... attrs['_instance'] = None ... return super().__new__(meta, name, bases, attrs) ... def __call__(cls, *args, **kwargs): ... if not cls._instance: ... cls._instance = super().__call__(*args, **kwargs) ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 87

Slide 87 text

Metaclasses >>> class Singleton(type): ... def __new__(meta, name, bases, attrs): ... attrs['_instance'] = None ... return super().__new__(meta, name, bases, attrs) ... def __call__(cls, *args, **kwargs): ... if not cls._instance: ... cls._instance = super().__call__(*args, **kwargs) ... return cls._instance ... >>> class FooClass(metaclass=Singleton): ... pass ... >>> a, b = FooClass(), FooClass() >>> a is b True

Slide 88

Slide 88 text

Questions?

Slide 89

Slide 89 text

wat

Slide 90

Slide 90 text

wat #0 >>> x = ... >>> x == x False

Slide 91

Slide 91 text

wat #0 - Possible! >>> x = float('nan') >>> x == x False

Slide 92

Slide 92 text

wat #0 - Possible! >>> x = 0*1e400 >>> x == x False

Slide 93

Slide 93 text

http://python-wats.herokuapp.com/

Slide 94

Slide 94 text

wat #1 >>> x = ... >>> a = ... >>> b = ... >>> c = ... >>> max(x) < max(x[a:b:c]) True

Slide 95

Slide 95 text

wat #1 - Not Possible >>> x = ... >>> a = ... >>> b = ... >>> c = ... >>> max(x) < max(x[a:b:c]) True

Slide 96

Slide 96 text

wat #2 >>> x = ... >>> y = ... >>> min(x, y) == min(y, x) False

Slide 97

Slide 97 text

wat #2 - Possible! >>> x = {0} >>> y = {1} >>> min(x, y) == min(y, x) False

Slide 98

Slide 98 text

wat #2 - Possible! >>> min({0}, {1}) set([0]) >>> min({1}, {0}) set([1])

Slide 99

Slide 99 text

wat #2 - Possible! >>> min({0}, {1}) set([0]) >>> min({1}, {0}) set([1]) >>> min({0, 1}, {0}) set([0])

Slide 100

Slide 100 text

wat #2 - Possible! >>> def min(*args): ...

Slide 101

Slide 101 text

wat #2 - Possible! >>> def min(*args): ... has_item = False ... min_item = None ...

Slide 102

Slide 102 text

wat #2 - Possible! >>> def min(*args): ... has_item = False ... min_item = None ... for x in args: ...

Slide 103

Slide 103 text

wat #2 - Possible! >>> def min(*args): ... has_item = False ... min_item = None ... for x in args: ... if not has_item or x < min_item: ...

Slide 104

Slide 104 text

wat #2 - Possible! >>> def min(*args): ... has_item = False ... min_item = None ... for x in args: ... if not has_item or x < min_item: ... has_item = True ... min_item = x ...

Slide 105

Slide 105 text

wat #2 - Possible! >>> def min(*args): ... has_item = False ... min_item = None ... for x in args: ... if not has_item or x < min_item: ... has_item = True ... min_item = x ... return min_item ...

Slide 106

Slide 106 text

wat #2 - Possible! >>> {1} < {0} False >>> {1} < {0, 1} True

Slide 107

Slide 107 text

wat #2 - Possible! >>> {1} < {0} False >>> {1} < {0, 1} True >>> min({0}, {1}) set([0])

Slide 108

Slide 108 text

wat #3 >>> x = ... >>> y = ... >>> any(x) and not any(x + y) True

Slide 109

Slide 109 text

wat #3 - Not Possible >>> x = ... >>> y = ... >>> any(x) and not any(x + y) True

Slide 110

Slide 110 text

wat #4 >>> x = ... >>> y = ... >>> x.count(y) > len(x) True

Slide 111

Slide 111 text

wat #4 - Possible! >>> x = 'a' >>> y = '' >>> x.count(y) > len(x) True

Slide 112

Slide 112 text

wat #4 - Possible! >>> x = 'a' >>> y = '' >>> x.count(y) > len(x) True >>> len('a') 1

Slide 113

Slide 113 text

wat #4 - Possible! >>> x = 'a' >>> y = '' >>> x.count(y) > len(x) True >>> len('a') 1 >>> 'a'.count('') 2

Slide 114

Slide 114 text

wat #4 - Possible! >>> def count(s, sub): ...

Slide 115

Slide 115 text

wat #4 - Possible! >>> def count(s, sub): ... result = 0 ...

Slide 116

Slide 116 text

wat #4 - Possible! >>> def count(s, sub): ... result = 0 ... for i in range(len(s) + 1 - len(sub)): ...

Slide 117

Slide 117 text

wat #4 - Possible! >>> def count(s, sub): ... result = 0 ... for i in range(len(s) + 1 - len(sub)): ... possible_match = s[i:i + len(sub)] ...

Slide 118

Slide 118 text

wat #4 - Possible! >>> def count(s, sub): ... result = 0 ... for i in range(len(s) + 1 - len(sub)): ... possible_match = s[i:i + len(sub)] ... if possible_match == sub: ... result += 1 ... return result ...

Slide 119

Slide 119 text

wat #4 - Possible! >>> def count(s, sub): ... result = 0 ... for i in range(len(s) + 1 - len(sub)): ... possible_match = s[i:i + len(sub)] ... if possible_match == sub: ... result += 1 ... return result ... >>> count('a', '') 2

Slide 120

Slide 120 text

wat #4 - Possible! >>> count('foofoof', 'foof') # my implementation 2 >>> 'foofoof'.count('foof') 1

Slide 121

Slide 121 text

wat #5 >>> x = ... >>> y = ... >>> z = ... >>> x * (y * z) == (x * y) * z False

Slide 122

Slide 122 text

wat #5 - Possible! >>> x = [0] >>> y = -1 >>> z = -1 >>> x * (y * z) == (x * y) * z False

Slide 123

Slide 123 text

wat #5 - Possible! >>> x = [0] >>> y = -1 >>> z = -1 >>> x * (y * z) == (x * y) * z False >>> x * (y * z) == [0]*(-1*-1)

Slide 124

Slide 124 text

wat #5 - Possible! >>> x = [0] >>> y = -1 >>> z = -1 >>> x * (y * z) == (x * y) * z False >>> x * (y * z) == [0]*(-1*-1) == [0]*1

Slide 125

Slide 125 text

wat #5 - Possible! >>> x = [0] >>> y = -1 >>> z = -1 >>> x * (y * z) == (x * y) * z False >>> x * (y * z) == [0]*(-1*-1) == [0]*1 == [0] True

Slide 126

Slide 126 text

wat #5 - Possible! >>> x = [0] >>> y = -1 >>> z = -1 >>> x * (y * z) == (x * y) * z False >>> x * (y * z) == [0]*(-1*-1) == [0]*1 == [0] True >>> (x * y) * z == ([0]*-1)*-1

Slide 127

Slide 127 text

wat #5 - Possible! >>> x = [0] >>> y = -1 >>> z = -1 >>> x * (y * z) == (x * y) * z False >>> x * (y * z) == [0]*(-1*-1) == [0]*1 == [0] True >>> (x * y) * z == ([0]*-1)*-1 == []*-1

Slide 128

Slide 128 text

wat #5 - Possible! >>> x = [0] >>> y = -1 >>> z = -1 >>> x * (y * z) == (x * y) * z False >>> x * (y * z) == [0]*(-1*-1) == [0]*1 == [0] True >>> (x * y) * z == ([0]*-1)*-1 == []*-1 == [] True

Slide 129

Slide 129 text

wat #6 >>> x = ... >>> y = ... >>> x < y and all(a >= b for a, b in zip(x, y)) True

Slide 130

Slide 130 text

wat #6 - Possible! >>> x = [] >>> y = [0] >>> x < y and all(a >= b for a, b in zip(x, y)) True

Slide 131

Slide 131 text

wat #6 - Possible! >>> x = [] >>> y = [0] >>> x < y and all(a >= b for a, b in zip(x, y)) True >>> [] < [0] True

Slide 132

Slide 132 text

wat #6 - Possible! >>> x = [] >>> y = [0] >>> x < y and all(a >= b for a, b in zip(x, y)) True >>> [] < [0] True >>> zip([], [0]) []

Slide 133

Slide 133 text

wat #6 - Possible! >>> x = [] >>> y = [0] >>> x < y and all(a >= b for a, b in zip(x, y)) True >>> [] < [0] True >>> zip([], [0]) [] >>> all([]) True

Slide 134

Slide 134 text

wat #7 >>> x = ... >>> len(set(list(x))) == len(list(set(x))) False

Slide 135

Slide 135 text

wat #7 - Not Possible >>> x = ... >>> len(set(list(x))) == len(list(set(x))) False

Slide 136

Slide 136 text

wat #8 >>> x = ... >>> min(x) == min(*x) False

Slide 137

Slide 137 text

wat #8 - Possible! >>> x = [[0]] >>> min(x) == min(*x) False

Slide 138

Slide 138 text

wat #8 - Possible! >>> x = [[0]] >>> min(x) == min(*x) False >>> min([1, 2, 3]) == min(*[1, 2, 3]) == min(1, 2, 3) True

Slide 139

Slide 139 text

wat #8 - Possible! >>> x = [[0]] >>> min(x) == min(*x) False >>> min([1, 2, 3]) == min(*[1, 2, 3]) == min(1, 2, 3) True >>> min(x) == [0] True

Slide 140

Slide 140 text

wat #8 - Possible! >>> x = [[0]] >>> min(x) == min(*x) False >>> min([1, 2, 3]) == min(*[1, 2, 3]) == min(1, 2, 3) True >>> min(x) == [0] True >>> min(*x) == min([0]) == 0 True

Slide 141

Slide 141 text

wat #9 >>> x = ... >>> y = ... >>> sum(0 * x, y) == y False

Slide 142

Slide 142 text

wat #9 - Not Possible >>> x = ... >>> y = ... >>> sum(0 * x, y) == y False

Slide 143

Slide 143 text

wat #9 - Not Possible >>> x = ... >>> y = ... >>> sum(0 * x, y) == y False >>> sum([1, 1, 1], 7) 10

Slide 144

Slide 144 text

wat #9 - Not Possible >>> x = ... >>> y = ... >>> sum(0 * x, y) == y False >>> sum([1, 1, 1], 7) 10 >>> sum([], 7) 7

Slide 145

Slide 145 text

wat #10 >>> x = ... >>> y = ... >>> y > max(x) and y in x True

Slide 146

Slide 146 text

wat #10 - Possible! >>> x = 'aa' >>> y = 'aa' >>> y > max(x) and y in x True

Slide 147

Slide 147 text

wat #10 - Possible! >>> x = 'aa' >>> y = 'aa' >>> y > max(x) and y in x True >>> max('aa') 'a'

Slide 148

Slide 148 text

wat #10 - Possible! >>> x = 'aa' >>> y = 'aa' >>> y > max(x) and y in x True >>> max('aa') 'a' >>> 'aa' > 'a' True

Slide 149

Slide 149 text

wat #10 - Possible! >>> x = 'aa' >>> y = 'aa' >>> y > max(x) and y in x True >>> max('aa') 'a' >>> 'aa' > 'a' True >>> 'aa' in 'aa' True

Slide 150

Slide 150 text

Questions?

Slide 151

Slide 151 text

Thanks!