PyTricks
PyTricks copied to clipboard
New tricks
Tuples
tuple syntax
a = 1
# >>> a
# 1
# >>> a,
# (1, )
unpacking iterable of length 1
a, = (1, )
unpacking with starred expression
a,*b,c = range(10)
# >>> a
# 0
# >>> b
# [1, 2, 3, 4, 5, 6, 7, 8]
# >>> c
# 9
a,*b,d,e,f = range(10)
# >>> (a,b,c,d,e,f)
# (0, [1, 2, 3, 4, 5, 6], 9, 7, 8, 9)
loop over dicts that share (some) keys
dctA = {'a': 1, 'b': 2, 'c': 3}
dctB = {'b': 4, 'c': 5, 'd': 6}
for ky in set(dctA) & set(dctB):
print ky
this one is much slower:
for ky in dctA:
if ky in dctB:
print ky
lookup deep nested value in dicts
nested = {'a': {'b': {'c': {'d': 1}}}}
print nested.get('a', {}).get('b', {}).get('c', {}).get('d')
print nested.get('x', {}).get('y', {}).get('z', {}).get('0')
This is almost just as fast as completly testing whether the variable exists and IMO more readable.
Copy lists
a = [1, 2, 3, 4, 5]
cpyA = list(a)
cpyB = a[:]
cpyB is faster
Startswith
lst = range(10000)
def string_startswith():
for _ in lst:
'blasdfsf'.startswith('__')
'__aqqqqqqqqqqqqqqqqqsdfsf'.startswith('__')
def string_eq_first_two():
for _ in lst:
'blasdfsf'[:2] == '__'
'__aqqqqqqqqqqqqqqqqqsdfsf'[:2] == '__'
The second one is faster
Hey agumonkey, thanks for your contribution. I added your last example to the collection. Your first two examples doesn't really show off a trick to me, that's why I didn't add them. Anyway, thanks for your support.
Hey obeleh, thanks for your contribution. From your examples I added two to the collection. The remaining are good to know as well, but I'm not looking for code snippets, that concentrate on performance. Anyway, thanks for your support.
@brennerm
They sit between tricks and easy to overlook syntax. Here's another thing I only found recently:
slice operator accepts None
# useful to have a value to denote unknown lengths
#
# here with range pairs
ranges = [(0,6), (6,None)]
for beg,end in ranges:
print('aabbccddeeff'[beg:end])
@agumonkey Yeah you can use [0:None], but you can write it like this as well:
print('aabbccddeeff'[0:])
For me this is more readable.
@brennerm
It's unrelated, ability to pass a a value to [:] is rarely shown and very valuable. (see this example).
Never seen this trick before so I played around a bit. Named formatting, more examples:
d = {'Jeff Smith': {'name': 'Jeff', 'age': 24}}
person = 'Jeff Smith'
print("My name is {name} and I'm {age} years old.".format(**d[person]))
Is it possible to do something like the following (which doesn't work)?
d = {'Jeff Smith': {'name': 'Jeff', 'age': {'years': 24, 'decades': 2.4}}}
person = 'Jeff Smith'
period = 'decades'
print("Hi my name is {name} and I'm {age[{0}]} {0} old.".format(period,**d[person]))
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-95-ff05fa5df228> in <module>()
1 period = 'decades'
----> 2 print('Hi my name is {name} and I\'m {age[{0}]} {0} old.'.format(period,**d[p]))
KeyError: '{0}'
@agumonkey Agree, I will add an array slicing example
@bash-j I don't really understand what you' re trying to accomplish, cause your code doesn't make sense to me. What is your expected output?
@brennerm I would like to pass the argument 'decades' as the dict key and description so it prints, 'Hi my name is Jeff and I'm 2.4 decades old.'
@brennerm
I think @bash-j wants to be able to use nested dicts, and asks if format has a syntax to address sub-elements.
The way to access nested dicts is like this:
d = {'Jeff Smith': {'name': 'Jeff', 'age': {'years': 24, 'decades': 2.4}}}
"My name is {name} and I'm {age[decades]} decades old.".format(**d['Jeff Smith'])
But I suppose he wants to use the corresponding 'years' and 'decade' string as well.
@brennerm
Oh I see, accessing both key and value. I agree it's not a great idea. Better have ... 'age' : {'value' : 24, 'type' : 'years'} ... Anyway, I didn't remember the '{key[subkey]}' syntax.
Tried it with 2 level nested dicts :
d = {'name':'john', 'age': {'years' : 24, 'type': {'name': 'year(s)'}}}
'{name} is {age[years]} {age[type][name]}'.format(**d)
N level nested dicts works too : {root[sub][subsub][subsubsub]}
.
I thought that format would replace the {0} in age[{0}] with 'decades' first before attempting the dictionary look up.
I found that chaining two format functions together works:
print("Hi my name is {{name}} and I'm {{age[{0}]}} {0} old.".format('decades').format(**d['Jeff Smith']))
Trick for socket.recv
coon = socket.connect(bind_address)
msgs = []
# 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(coon.recv, 1024), b'')):
msgs.append(msg)
property cache with Descriptor
class PropertyCache(object):
""" a decorator to cache property
"""
def __init__(self, func):
self.func = func
def __get__(self, obj, cls):
if not obj:
return self
value = self.func(obj)
setattr(obj, self.func.__name__, value)
return value
compound Boolean statements shortening trick:
Requiring two (or more) objects both be in a given set required as many "object in set ?" Boolean statements coupled by an and, repeating the same set name for each object. The resulting compound Boolean statement can be long especially when there are many objects and/or the set being tested has a long name. Normally you'd have to write:
if A in my_dictionary[key].adjacent_nodes and B in my_dictionary[key].adjacent_nodes:
do_stuff()
I found that with python, you can easily eliminate all the redundant references to the same set in these compound Boolean statements:
if A and B in my_dictionary[key].adjacent_nodes:
do_stuff()
adding a check for another item in the same set would be just as easy, add minimal verbosity, and be more readable using the trick:
if A and B and not C in my_dictionary[key].adjacent_nodes
I basically tried it because trying code is so easy in python, and it worked, I was pleasantly surprised but this could easily be very common knowledge that I missed in my readings. Either way, thank you all for gathering this collection of tricks, many of which were new to me and their usefulness immediately apparent.
A simple calculator created using operator
module.
#!/usr/bin/env python3
# Created with help of an answer on stackoverflow. Don't have the exact link.
import operator
ops = {
"+": operator.add,
"-": operator.sub,
"/": operator.truediv,
"*": operator.mul
}
x = input("Enter an operator [OPTIONS: +, -, *, /]: ")
y = int(input("Enter number: "))
z = int(input("Enter number: "))
print (ops[x](y, z))
@dharmit
Funny, conditionalfunctional.py inspired writing the similar thing, albeit not interactive, more an assembler POV:
import operator
ops = {
'add': operator.add,
'sub': operator.sub,
'mul': operator.mul,
'div': operator.truediv
}
def run(op, a, b):
return ops.get(op, 1)(int(a), int(b))
for inst in [
'add 1 2',
'mul 3 4',
'div 121 11',
'sub 9 10'
]:
v = run(*(inst.split()))
print(v)
Using globals().update()
to set global variables from a dict, instead of using for
loop and exec()
.
#! /usr/bin/env python3
"""set global variables from dict"""
d = {'a': 1, 'b': 'var2', 'c': [1, 2, 3]}
globals().update(d)
print(a, b, c)
A simple way to remove duplicate items in a list.
#! /usr/bin/env python3
"""remove duplicate items from list"""
items = [1, 2, 2, 3, 3, 3]
newitems = list(set(items))
print(newitems)
merged your pull request and added you to the CONTRIBUTORS ;)
@tutoringsteve Thanks for your contribution!
Control white spaces in a string easily.
#! /usr/bin/env python3
"""control the whitespaces in string"""
s = 'The Little Price'
# justify string to be at least width wide
# by adding whitespaces
width = 20
s1 = s.ljust(width)
s2 = s.rjust(width)
s3 = s.center(width)
print(s1) # 'The Little Price '
print(s2) # ' The Little Price'
print(s3) # ' The Little Price '
# strip whitespaces in two sides of string
print(s3.lstrip()) # 'The Little Price '
print(s3.rstrip()) # ' The Little Price'
print(s3.strip()) # 'The Little Price'
@Kzinglzy Please add an example that shows how to use the descriptor.
@brennerm
example for the property cache decriptor:
class TestClass:
@cache_property
def property_to_be_cached(self):
print('compute')
return 'result'
ts = TestClass()
print 'first time:\n', ts.property_to_be_cached
print 'second time:\n', ts.property_to_be_cached
and the output will be:
first time:
compute!!
result
second time:
result
which the func just compute once : )
actually, the result has store in the
TestClass.__dict__