diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b9e1f1c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: python +python: + - "3.6" +before_install: + - sudo apt-get update + - sudo apt-get install -y python python3 +script: + - | + set -e + + for file in $(ls *.py); do + echo "Executing with Python 2: $file" + python2 $file + echo "Executing with Python 3: $file" + python3 $file + done + + for file in $(ls *.py2); do + echo "Executing with Python 2: $file" + python2 $file + done + + for file in $(ls *.py3); do + echo "Executing with Python 3: $file" + python3 $file + done diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 0269a06..87521dd 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -35,3 +35,4 @@ - flint (github.com/flintforge) - kazuhiko (github.com/JohnTitor00) - sfdye (github.com/sfdye) +- ofek (https://github.com/ofek) diff --git a/README.md b/README.md index 9ee9c56..734a11f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.org/brennerm/PyTricks.svg?branch=master)](https://travis-ci.org/brennerm/PyTricks) + ## Intention Creating a knowledge base of unpopular Python built-in features to save a lot of unnecessary code. diff --git a/argumentunpacking.py b/argumentunpacking.py old mode 100755 new mode 100644 index 78c86ef..c474851 --- a/argumentunpacking.py +++ b/argumentunpacking.py @@ -3,8 +3,18 @@ def product(a, b): return a * b -argument_tuple = (1, 1) -argument_dict = {'a': 1, 'b': 1} +def fn_iterable(): + return [2, 3] + +def fn_dict(): + return {'a': 2, 'b': 3} + +argument_tuple = (2, 3) +argument_dict = {'a': 2, 'b': 3} print(product(*argument_tuple)) print(product(**argument_dict)) + +# unpacking works as well on function return values +print(product(*fn_iterable())) +print(product(**fn_dict())) diff --git a/boolasint.py b/boolasint.py old mode 100755 new mode 100644 diff --git a/boolfast.py b/boolfast.py new file mode 100644 index 0000000..c1a71ad --- /dev/null +++ b/boolfast.py @@ -0,0 +1,38 @@ +"""Getting the truthyness via bool(obj) is slow because it is a global and +therefore involves multiple namespace lookups. You can use the keyword `not` +to avoid the overheard i.e. `not not obj`. +""" + +import timeit + +slow_setup = """ +class C: + def __init__(self): + self.some_val = 5 + def __bool__(self): + return bool(self.some_val) +a = C() +""" + +fast_setup = """ +class C: + def __init__(self): + self.some_val = 5 + def __bool__(self): + return not not self.some_val +a = C() +""" + +# on my machine: + +# 0.433618037256565 +print(timeit.timeit('a.__bool__()', slow_setup)) + +# 0.2220980115553175 +print(timeit.timeit('a.__bool__()', fast_setup)) + +# 0.40519480762077364 +print(timeit.timeit('if a:pass', slow_setup)) + +# 0.24311949953334988 +print(timeit.timeit('if a:pass', fast_setup)) diff --git a/boolisslow.py b/boolisslow.py index b2c430d..2d80ff3 100644 --- a/boolisslow.py +++ b/boolisslow.py @@ -7,12 +7,12 @@ Note: This leads to a performance improvement only in Python2. """ - +import sys from timeit import timeit def test_true(): - count = 1000 + count = 100 while True: # here is True if count < 0: break @@ -20,23 +20,14 @@ def test_true(): def test_1(): - count = 1000 + count = 100 while 1: # here is 1 if count < 0: break count -= 1 -# on my macbook pro 15 -# test_true is about 59.3047289848 seconds -# test_1 is about 39.0966179371 seconds +# test_true is about 5.01579904556 seconds +# test_1 is about 3.70646500587 seconds print(timeit(test_true, number=1000000)) print(timeit(test_1, number=1000000)) - - -# True and False can be changed in python2 -True = 0 -False = 100 - -print(True) -print(False) diff --git a/boolisslow.py2 b/boolisslow.py2 new file mode 100644 index 0000000..cae74e9 --- /dev/null +++ b/boolisslow.py2 @@ -0,0 +1,6 @@ +# True and False can be changed in python2 +True = 0 +False = 100 + +print(True) +print(False) diff --git a/cacheproperty.py b/cacheproperty.py index 562fc27..20742d6 100644 --- a/cacheproperty.py +++ b/cacheproperty.py @@ -1,4 +1,4 @@ -class PropertyCache: +class PropertyCache(object): """ a decorator to cache property """ diff --git a/calculator.py b/calculator.py old mode 100755 new mode 100644 index 882e2b2..8dbe394 --- a/calculator.py +++ b/calculator.py @@ -12,11 +12,8 @@ "+": operator.add, "-": operator.sub, "/": operator.truediv, - "*": operator.mul + "*": operator.mul, + "**": pow } -x = input("Enter an operator [OPTIONS: +, -, *, /]: ") -y = int(input("Enter number: ")) -z = int(input("Enter number: ")) - -print (ops[x](y, z)) +print(ops['-'](50, 25)) diff --git a/chainedcomparison.py b/chainedcomparison.py old mode 100755 new mode 100644 diff --git a/concatenatestrings.py b/concatenatestrings.py old mode 100755 new mode 100644 diff --git a/conditionalassignment.py b/conditionalassignment.py old mode 100755 new mode 100644 diff --git a/conditionalfunctioncall.py b/conditionalfunctioncall.py old mode 100755 new mode 100644 diff --git a/contextmanagers.py b/contextmanagers.py index 138c6d9..021de87 100644 --- a/contextmanagers.py +++ b/contextmanagers.py @@ -12,29 +12,26 @@ @contextlib.contextmanager def unlock(resource): - resource = "unlocked" + resource.locked = False try: - yield resource + yield finally: - resource = "locked" + resource.locked = True # a resource that is locked -resource = "locked" +class Resource: + def __init__(self): + self.locked = True + +resource = Resource() # test that it is indeed locked -print(resource) +print(resource.locked) # call your 'unlock' context manager with your resource -with unlock(resource) as unlocked: - print(unlocked) # check that it is unlocked +with unlock(resource): + print(resource.locked) # check that it is unlocked # ensure it was re-locked when it left the 'unlock' context -print(resource) - - - - - - - +print(resource.locked) diff --git a/controlwhitespaces.py b/controlwhitespaces.py old mode 100755 new mode 100644 diff --git a/copylist.py b/copylist.py old mode 100755 new mode 100644 index d503efc..c8b9afe --- a/copylist.py +++ b/copylist.py @@ -1,10 +1,18 @@ #! /usr/bin/env python3 +import sys + """a fast way to make a shallow copy of a list""" a = [1, 2, 3, 4, 5] print(a[:]) +"""adding an empty list yields a copy of initial list""" + +a = [1, 2, 3, 4, 5] +print(a + []) # in python3, for small lists performs faster than a[:] + + """copy list by typecasting method""" a = [1, 2, 3, 4, 5] @@ -13,9 +21,14 @@ """using the list.copy() method (python3 only)""" -a = [1, 2, 3, 4, 5] - -print(a.copy()) +if sys.version_info.major == 3: + a = [1, 2, 3, 4, 5] + print(a.copy()) +else: + # in python2 there exists the `copy` builtin module + from copy import copy + a = [1, 2, 3, 4, 5] + print(copy(a)) """copy nested lists using copy.deepcopy""" diff --git a/dictionaryget.py b/dictionaryget.py old mode 100755 new mode 100644 diff --git a/dictsortbyvalue.py b/dictsortbyvalue.py old mode 100755 new mode 100644 diff --git a/dictswapkeysvalues.py b/dictswapkeysvalues.py old mode 100755 new mode 100644 diff --git a/exec.py b/exec.py old mode 100755 new mode 100644 diff --git a/extendediterableunpacking.py b/extendediterableunpacking.py3 old mode 100755 new mode 100644 similarity index 90% rename from extendediterableunpacking.py rename to extendediterableunpacking.py3 index bc5d77f..88014be --- a/extendediterableunpacking.py +++ b/extendediterableunpacking.py3 @@ -1,4 +1,3 @@ -#! /usr/bin/env python3 """allows collecting not explicitly assigned values into a placeholder variable""" diff --git a/flattenlist.py b/flattenlist.py old mode 100755 new mode 100644 index 51070d6..a086ce9 --- a/flattenlist.py +++ b/flattenlist.py @@ -1,4 +1,3 @@ -#! /usr/bin/env python3 """ Deep flattens a nested list @@ -10,18 +9,6 @@ """ -def flatten_list(L): - for item in L: - if isinstance(item, list): - yield from flatten_list(item) - else: - yield item - -# In Python 2 -from compiler.ast import flatten -flatten(L) - - # Flatten list of lists a = [[1, 2], [3, 4]] @@ -35,8 +22,5 @@ def flatten_list(L): print(list(itertools.chain.from_iterable(a))) -# In Python 2 -print(reduce(lambda x, y: x+y, a)) - print(sum(a, [])) diff --git a/flattenlist.py2 b/flattenlist.py2 new file mode 100644 index 0000000..32d144a --- /dev/null +++ b/flattenlist.py2 @@ -0,0 +1,7 @@ +L = [1, 2, [3, 4], [5, 6, [7]]] + +from compiler.ast import flatten +flatten(L) + +a = [[1, 2], [3, 4]] +print(reduce(lambda x, y: x+y, a)) \ No newline at end of file diff --git a/flattenlist.py3 b/flattenlist.py3 new file mode 100644 index 0000000..15c9bbf --- /dev/null +++ b/flattenlist.py3 @@ -0,0 +1,10 @@ +L = [1, 2, [3, 4], [5, 6, [7]]] + +def flatten(L): + for item in L: + if isinstance(item, list): + yield from flatten(item) + else: + yield item + +flatten(L) diff --git a/forelse.py b/forelse.py old mode 100755 new mode 100644 diff --git a/ifelsecommentswitch.py b/ifelsecommentswitch.py old mode 100755 new mode 100644 diff --git a/keydefaultdict.py b/keydefaultdict.py index af4fede..3f0ece0 100644 --- a/keydefaultdict.py +++ b/keydefaultdict.py @@ -1,5 +1,5 @@ """ -keydefaultdict with where the function recieves the key. +keydefaultdict with where the function receives the key. """ from collections import defaultdict diff --git a/loopoverlappingdicts.py b/loopoverlappingdicts.py old mode 100755 new mode 100644 index e7d5dda..c6b1b31 --- a/loopoverlappingdicts.py +++ b/loopoverlappingdicts.py @@ -6,11 +6,3 @@ for ky in set(dctA) & set(dctB): print(ky) - -"""loop over dicts that share (some) keys in Python3""" -for ky in dctA.keys() & dctB.keys(): - print(ky) - -"""loop over dicts that share (some) keys and values in Python3""" -for item in dctA.items() & dctB.items(): - print(item) diff --git a/loopoverlappingdicts.py3 b/loopoverlappingdicts.py3 new file mode 100644 index 0000000..ef2646a --- /dev/null +++ b/loopoverlappingdicts.py3 @@ -0,0 +1,11 @@ +#! /usr/bin/env python3 +dctA = {'a': 1, 'b': 2, 'c': 3} +dctB = {'b': 4, 'c': 3, 'd': 6} + +"""loop over dicts that share (some) keys in Python3""" +for ky in dctA.keys() & dctB.keys(): + print(ky) + +"""loop over dicts that share (some) keys and values in Python3""" +for item in dctA.items() & dctB.items(): + print(item) diff --git a/maxsplit.py b/maxsplit.py old mode 100755 new mode 100644 diff --git a/merge_dict.py b/merge_dict.py index 832096f..80d4df0 100644 --- a/merge_dict.py +++ b/merge_dict.py @@ -1,13 +1,7 @@ -#! /usr/bin/env python3.5 """merge dict's""" d1 = {'a': 1} d2 = {'b': 2} -# python 3.5 -print({**d1, **d2}) - -print(dict(d1.items() | d2.items())) - d1.update(d2) print(d1) diff --git a/merge_dict.py3 b/merge_dict.py3 new file mode 100644 index 0000000..086e677 --- /dev/null +++ b/merge_dict.py3 @@ -0,0 +1,8 @@ +"""merge dict's""" + +d1 = {'a': 1} +d2 = {'b': 2} + +print({**d1, **d2}) + +print(dict(d1.items() | d2.items())) \ No newline at end of file diff --git a/metatable.py b/metatable.py index 040079c..caec968 100644 --- a/metatable.py +++ b/metatable.py @@ -1,5 +1,5 @@ """ -metatable with where the function recieves the dictionary and key. +metatable with where the function receives the dictionary and key. """ from collections import defaultdict diff --git a/namedformatting.py b/namedformatting.py old mode 100755 new mode 100644 index ceda335..6e075ba --- a/namedformatting.py +++ b/namedformatting.py @@ -23,9 +23,4 @@ class Person: me.name = 'Jeff' me.email = 'jeff@usr.com' me.phone = '919-123-4567' -print('My name is {me.name}, my email is {me.email} and my phone number is {me.phone}'.format(me=me)) - -"""f-string (Python 3.6+)""" -name = "Jeff" -age = 24 -print(f"My name is {name} and I'm {age} years old.") +print('My name is {me.name}, my email is {me.email} and my phone number is {me.phone}'.format(me=me)) \ No newline at end of file diff --git a/namedformatting.py3 b/namedformatting.py3 new file mode 100644 index 0000000..04e5ac4 --- /dev/null +++ b/namedformatting.py3 @@ -0,0 +1,4 @@ +"""f-string (Python 3.6+)""" +name = "Jeff" +age = 24 +print(f"My name is {name} and I'm {age} years old.") \ No newline at end of file diff --git a/removeduplicatefromlist.py b/removeduplicatefromlist.py old mode 100755 new mode 100644 diff --git a/reverselist.py b/reverselist.py old mode 100755 new mode 100644 diff --git a/setglobalvariables.py b/setglobalvariables.py old mode 100755 new mode 100644 diff --git a/setoperators.py b/setoperators.py old mode 100755 new mode 100644 diff --git a/socketmsghandling.py b/socketmsghandling.py index c315b4c..94508fd 100644 --- a/socketmsghandling.py +++ b/socketmsghandling.py @@ -1,19 +1,23 @@ import socket import functools -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -conn = s.connect(('localhost', 80)) -msgs = [] +ConnectionRefusedError = socket.error -# normal way -# while True: -# msg = coon.recv(1024) -# if recv: -# msgs.append(msg) -# else: # when no msg come, break -# break +msgs = [] +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +try: + conn = s.connect(('localhost', 80)) + # normal way + # while True: + # msg = coon.recv(1024) + # if recv: + # msgs.append(msg) + # else: # when no msg come, break + # break -# hack way with iter and functools.partial -# this circle will auto break when msg is empty '' -for msg in iter(functools.partial(conn.recv, 1024), b''): - msgs.append(msg) + # hack way with iter and functools.partial + # this circle will auto break when msg is empty '' + for msg in iter(functools.partial(conn.recv, 1024), b''): + msgs.append(msg) +except (socket.error, ConnectionRefusedError): + pass \ No newline at end of file diff --git a/stepslice.py b/stepslice.py old mode 100755 new mode 100644 diff --git a/switch_case_statments_with_dict.py b/switch_case_statments_with_dict.py old mode 100755 new mode 100644 diff --git a/valueswapping.py b/valueswapping.py old mode 100755 new mode 100644 index 1f18a66..70011c8 --- a/valueswapping.py +++ b/valueswapping.py @@ -1,6 +1,11 @@ #! /usr/bin/env python3 -"""pythonic way of value swapping""" +# Type of variable: Number a, b = 5, 10 print(a, b) a, b = b, a print(a, b) +# Type of variable: List +myList = [1, 2, 3, 4, 5] +print("Initial Array :", myList) +myList[0], myList[1] = myList[1], myList[0] +print("Swapped Array :", myList) diff --git a/whileelse.py b/whileelse.py old mode 100755 new mode 100644