Try   HackMD

effective python

tags:python

map and filter

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
squares = map(lambda x: x ** 2, a)
[x for x in squares]
​​​​[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
squares=filter(lambda x:x%2==0,a)
[x for x in squares]
​​​​[2, 4, 6, 8, 10]
[x**2 for x in a]
​​​​[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

enumerate

lolis=['loli1','loli2','loli3','loli4','loli5']
for index,value in enumerate(lolis):
    print((index,value))
​​​​(0, 'loli1')
​​​​(1, 'loli2')
​​​​(2, 'loli3')
​​​​(3, 'loli4')
​​​​(4, 'loli5')
# change start from index
for index,value in enumerate(lolis,5):
    print((index,value))
​​​​(5, 'loli1')
​​​​(6, 'loli2')
​​​​(7, 'loli3')
​​​​(8, 'loli4')
​​​​(9, 'loli5')

zip

brothers=["brother1","brother2","brother3","brother4"]
for i in zip(lolis,brothers):
    print(i)
​​​​('loli1', 'brother1')
​​​​('loli2', 'brother2')
​​​​('loli3', 'brother3')
​​​​('loli4', 'brother4')

else after for

for i in range(2):
	print(i)
	if i % 2 == 0:
		break
else:
	print('loop finish')
​​​​0

reversed iterate

list_example = [i for i in range(5)]
iter_example = (i for i in range(5)) 
set_example = {i for i in range(5)}
list_example
iter_example
set_example
​​​​[0, 1, 2, 3, 4]






​​​​<generator object <genexpr> at 0x7fc7b0a6f990>






​​​​{0, 1, 2, 3, 4}
for i in reversed(list_example):
	print(i)
​​​​4
​​​​3
​​​​2
​​​​1
​​​​0
for i in reversed(iter_example):
	print(i)
​​​​---------------------------------------------------------------------------

​​​​TypeError                                 Traceback (most recent call last)

​​​​<ipython-input-30-06c418582e31> in <module>()
​​​​----> 1 for i in reversed(iter_example):
​​​​      2         print(i)


​​​​TypeError: argument to reversed() must be a sequence
for i in reversed(set_example):
	print(i)
​​​​---------------------------------------------------------------------------

​​​​TypeError                                 Traceback (most recent call last)

​​​​<ipython-input-31-5660da0e6339> in <module>()
​​​​----> 1 for i in reversed(set_example):
​​​​      2         print(i)


​​​​TypeError: argument to reversed() must be a sequence
reversed(list_example)
​​​​<list_reverseiterator at 0x7fc7b09cb358>
class countdown(object):
    def __init__(self,start):
        self.start=start
    def __iter__(self):
        n=self.start
        while n>0:
            yield n
            n-=1
    def __reversed__(self):
        n=1
        while n<=self.start:
            yield n
            n+=1
            
for i in reversed(countdown(4)):
    print(i)
​​​​1
​​​​2
​​​​3
​​​​4
for i in countdown(4):
    print(i)
​​​​4
​​​​3
​​​​2
​​​​1
count_rev=reversed(countdown(100))
next(count_rev)
​​​​1

for/try/else

若執行try沒有發生異常,則執行else,for 則是執行時若沒有break,則會執行else

try:
    print("loli OUOb")
except:
    print("except occure!")
else:
    print("else statment")
finally:
    print("finally statement")
    
​​​​loli OUOb
​​​​else statment
​​​​finally statement
for x in [4,5,6,7,8]:
    if x>10:
        break
else:
    print("Hello world!")
​​​​Hello world!

decorator

def more(fun):
    def new_fun(*args,**kwargs):
        print('current fun:',fun.__name__)
        print('arguments"',args)
        print('key arguments:',kwargs)
        result=fun(*args,**kwargs)
        print('result:',result)
        return result
    return new_fun

@more
def add(a,b):
    return a+b

add(5,10)
​​​​current fun: add
​​​​arguments" (5, 10)
​​​​key arguments: {}
​​​​result: 15





​​​​15

在decorater加入參數

def read_file(filename=''):
    def more(fun):
        print(filename)
        def new_fun(*args,**kwargs):
            print('current fun:',fun.__name__)
            print('arguments"',args)
            print('key arguments:',kwargs)
            result=fun(*args,**kwargs)
            print('result:',result)
            return result
        return new_fun
    return more

# pass argument into decorator
@read_file(filename='log.txt')
def add(a, b):
	return a + b

@more
def add(a, b):
	return a + b

print(add.__name__)  # decorate func name wiil change
​​​​log.txt
​​​​new_fun

functools.wraps

from functools import wraps

def decorator_fun(fun):
	@wraps(fun)
	def new_fun(*args, **kwargs):
		result = fun(*args, **kwargs)
		print(result)
		return result
	return new_fun
	
@decorator_fun
def add(a, b):
	return a + b

print(add.__name__)
add(5,10)
​​​​add
​​​​15





​​​​15

using the call method

from functools import wraps

class logResult(object):
    def __init__(self, filename='results.txt'):
        self.filename = filename

    def __call__(self, fun):
        @wraps(fun)
        def new_fun(*args, **kwargs):
            result = fun(*args, **kwargs)
            with open(filename, 'a') as f:
                f.write(result + '\n')
            return result
            self.send_notification()
        return new_fun

    def send_notification(self):
        pass

@logResult('log.txt')
def add(a, b):
    return a + b
print(add.__name__)
​​​​add

iterable

def loop(items):
    for i in items:
        yield i

foo = loop([1, 2, 3, 4])
for i in foo:
    print(i)

# the list of generator can only be print once
# will print nothing   
for i in foo:
    print(i)
​​​​1
​​​​2
​​​​3
​​​​4

use itrable class to iterate again

class LoopIter(object):
	def __init__(self, data):
		self.data = data
	def __iter__(self):
		for index, letter in enumerate(self.data):
			if letter == 'a':
				yield index
                
string = 'this is a test to find a\' index'
indexs = LoopIter(string)

print('loop 1')
for _ in indexs:
	print(_)

# can be print twice
print('loop 2')
for _ in indexs:
	print(_)
​​​​loop 1
​​​​8
​​​​23
​​​​loop 2
​​​​8
​​​​23

but the _iter_ method can only be iterate by for loop.
If you wan't to iterate by next you have to use the iter function

string = 'this is a test to find a\' index'
indexs = LoopIter(string)

# next(indexs) # TypeError: 'LoopIter' object is not an iterator

iter_indexs = iter(indexs)
next(iter_indexs)
​​​​8

sending multiple argument into function

def square(*args):
    result=0
    for i in args:
        result+=i**2
    return result

square(1,2,3,4,5)
square(*[1,3,4,5,6,7])
​​​​55






​​​​136

關鍵字參數

def get_indexs(array, *, target='', judge=True):
	for index, item in enumerate(array):
		if judge and item == target:
			yield index
		elif not judge and item != target:
			yield index

array = [1, 2, 3, 4, 1]
result = get_indexs(array, target=1, judge=True)
print(*result)
# can ignore 
result = get_indexs(array, target=1)
print(*result)
​​​​0 4
​​​​0 4

you have to specfic the argument

result=get_indexs(array,1,False)
​​​​---------------------------------------------------------------------------

​​​​TypeError                                 Traceback (most recent call last)

​​​​<ipython-input-98-de1480137b59> in <module>()
​​​​----> 1 result=get_indexs(array,1,False)
​​​​

​​​​TypeError: get_indexs() takes 1 positional argument but 3 were given

default argument in function

def get_default(value=[]):
	return value
	
result = get_default()
result.append(1)
result2 = get_default()
result2.append(2)
print(result) # [1, 2]
print(result2) # [1, 2]
​​​​[1, 2]
​​​​[1, 2]
def get_default(value=None):
	if value is None:
		return []
	return value
	
result = get_default()
result.append(1)
result2 = get_default()
result2.append(2)
print(result) # [1]
print(result2) # [2]
​​​​[1]
​​​​[2]

classmethod and staticmethod__call__

class Parrotlet(object):
    size=15
    def __init__(self,*,name='',color=''):
        self.name=name
        self.color=color
    def color(self):
        return self.color
    @staticmethod
    def talk(message):
        print(message)
    @classmethod
    def bar(clz,name,color):
        print("New parrotlet!",clz.__name__)
        parrot=Parrotlet(name=name,color=color)
        return parrot
    
parrot1=Parrotlet(name='parrot1',color='green')
parrot1.size
parrot1.color
parrot1.talk("Hello world")
parrot2=parrot1.bar('parrot1','red')
parrot2.talk("parrot2 talk")

parrot2.size=20 # parrot2's attribute
assert parrot2.size!=(parrot1.size==Parrotlet.size)
Parrotlet.size=20
assert parrot2.size==parrot1.size==Parrotlet.size
​​​​15






​​​​'green'



​​​​Hello world
​​​​New parrotlet! Parrotlet
​​​​parrot2 talk

_call_ method

class Get_index(object):
    def __init__(self):
        pass
    def __call__(self,array,target):
        for index, item in enumerate(array):
            if item == target:
                yield index
                

get_index=Get_index()
print(*get_index([1,2,3,4,3,5,6],3))
​​​​2 4

split

def concat(sp="/",*args,**kwargs):
    if args:
        return  sp.join((str(i) for i in args))
    if kwargs:
        for k in kwargs.keys():
            print("{}{}{}".format(k,sep,kwargs[k]))
    return None

concat2("~",hello="world",python="rocks")
print(concat("/",*("G",100,"cm",)))
print(concat("GGC","GCC"))

#unpacking
d={"hello":"world","python":"rocks"}
print({**d}["python"]) # get d["python"]

user={"name":"Trey",'website':"http://treyhunner.com"}
defaults={'name':"Anonymous User",'page_name':"Profile page"}
print({**defaults,**user}) # the default user name will be override

print(concat("/",*("Hello python")))
​​​​python~rocks
​​​​hello~world
​​​​G/100/cm
​​​​GCC
​​​​rocks
​​​​{'name': 'Trey', 'page_name': 'Profile page', 'website': 'http://treyhunner.com'}
​​​​H/e/l/l/o/ /p/y/t/h/o/n

bytes

print(b'python')
"""
Bytes 代表的是(二進位)數字的序列,
通過 ASCII 编碼之後才是我們看到的字符形式
"""
print("print ascii number")
print(b"Python"[0])
print(b"P"[0]) 
# print(b"嗨") # can only contain ASCII chacters
​​​​b'python'
​​​​print ascii number
​​​​80
​​​​80
print("print hex number when it is out of ascii range")
# convert the word out of ASCII range(31-127) to hex number
print(b'\xAF'[0])
print(b'\xaa'[0])
print(b'\xAB')
​​​​print hex number when it is out of ascii range
​​​​175
​​​​170
​​​​b'\xab'
print("convert number to ascii")
# convert number to  ascii
print(bytes([24]))
print(bytes([65,60,55]))
print("convert hex to bytes")
# convert hex to bytes
print(bytes.fromhex("7A 7C"))
print(b'ASCII'.hex())
print(int(b' '.hex(), base=16)) #have space
​​​​convert number to ascii
​​​​b'\x18'
​​​​b'A<7'
​​​​convert hex to bytes
​​​​b'z|'
​​​​4153434949
​​​​32
# encode
print("A".encode('ascii')) 
print("A".encode('ascii')[0])# find value in ascii

# encode by unicode 
snake = '拉拉拉拉'
try:
    snake.encode('ascii')
except UnicodeEncodeError as err:
    print(err)

# use UTF-8
print(snake.encode()) # utf-8 by default

# bytearray is like byte "list",we can change it's 
# element but can't change byte's.
ba=bytearray(b"Hello World")
ba[0:1]=b"W"
print(ba)
​​​​b'A'
​​​​65
​​​​'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
​​​​b'\xe6\x8b\x89\xe6\x8b\x89\xe6\x8b\x89\xe6\x8b\x89'
​​​​bytearray(b'Wello World')
# bytes object  
b = b'example'  
  
 # str object  
s = "example"  
  
 # str to bytes  
bytes(s, encoding = "utf8")  
  
 # bytes to str  
str(b, encoding = "utf-8")  
  
 # an alternative method  
 # str to bytes  
str.encode(s)  
  
 # bytes to str  
bytes.decode(b) 
​​​​'example'
def convert_bytes_to_str(converted:bytes)->int:
    return bytes(converted).decode('utf-8')
import json
string=b'{"tmst":954473276,"time":"2017-06-26T15:52:55.802041+08:00","chan":5,"rfch":0,"freq":916.200000,"stat":1,"modu":"LORA","datr":"SF7BW125","codr":"4/5","lsnr":6.8,"rssi":-41,"size":15,"data":"QHhWNBKAEAAPyKqiGZ5W"}'
json.loads(string.decode('utf-8'))
​​​​{'chan': 5,
​​​​ 'codr': '4/5',
​​​​ 'data': 'QHhWNBKAEAAPyKqiGZ5W',
​​​​ 'datr': 'SF7BW125',
​​​​ 'freq': 916.2,
​​​​ 'lsnr': 6.8,
​​​​ 'modu': 'LORA',
​​​​ 'rfch': 0,
​​​​ 'rssi': -41,
​​​​ 'size': 15,
​​​​ 'stat': 1,
​​​​ 'time': '2017-06-26T15:52:55.802041+08:00',
​​​​ 'tmst': 954473276}

context manager

from  contextlib import contextmanager
import logging

def my_function():
    logging.debug("Some debug data")
    logging.error("Error log here")
    logging.info("Info here")


@contextmanager
def debug_logging(level):
    logger=logging.getLogger()
    old_level=logger.getEffectiveLevel()
    logger.setLevel(level)
    try:
        yield
    finally:
        logger.setLevel(old_level)


with debug_logging(logging.DEBUG):
    print("Inside:")
    my_function()

print("After")
my_function()
​​​​DEBUG:root:Some debug data
​​​​ERROR:root:Error log here
​​​​INFO:root:Info here
​​​​ERROR:root:Error log here


​​​​Inside:
​​​​After
_G = {"counter": 99, "user": "admin"}

class Refs():
    def __init__(self, name = None):
        self.name = name
        self._G = _G
        self.init = self._G['counter']
    def __enter__(self):
        return self
    def __exit__(self, *args):
        self._G["counter"] = self.init
        return False
    def acc(self, n = 1):
        self._G["counter"] += n
    def dec(self, n = 1):
        self._G["counter"] -= n
    def __str__(self):
        return "COUNTER #{name}: {counter}".format(**self._G, name=self.name)
        
with Refs("ref1") as ref1, Refs("ref2") as ref2:
    for _ in range(3):
        ref1.dec()
        print(ref1)
        ref2.acc(2)
        print(ref2)
print(_G)
​​​​COUNTER #ref1: 98
​​​​COUNTER #ref2: 100
​​​​COUNTER #ref1: 99
​​​​COUNTER #ref2: 101
​​​​COUNTER #ref1: 100
​​​​COUNTER #ref2: 102
​​​​{'user': 'admin', 'counter': 99}

Data and Time

from calendar import TextCalendar, HTMLCalendar
# calendar
tc=TextCalendar(firstweekday=6)
tc.prmonth(2016,5)

from datetime import date, time, datetime

d1=date(2016,3,29)
d2=date.today()
d3=date.fromtimestamp(_time.time())

print(d1)
print(d2)
print(d3)
​​​​      May 2016
​​​​Su Mo Tu We Th Fr Sa
​​​​ 1  2  3  4  5  6  7
​​​​ 8  9 10 11 12 13 14
​​​​15 16 17 18 19 20 21
​​​​22 23 24 25 26 27 28
​​​​29 30 31
​​​​2016-03-29
​​​​2017-06-21
​​​​2017-06-21
# get month year day
print("{}/{}/{}".format(d2.year,d2.month,d2.day))
#return struct_time struct,which can convert to tuple
print("time.struct_time: {}".format(tuple(d2.timetuple())))
print("Monday is 0: {}\nMonday is 1: {}".format(d2.weekday(), d2.isoweekday()))
​​​​2017/6/21
​​​​time.struct_time: (2017, 6, 21, 0, 0, 0, 2, 172, -1)
​​​​Monday is 0: 2
​​​​Monday is 1: 3
# Time
t1 = time(22, 57, 6, 6)
t2 = datetime.now().time()
print(t1)
print(t2)
​​​​22:57:06.000006
​​​​18:33:00.607976
# datetime.datetime
dt1 = datetime(2016, 3, 30, 22, 2)
dt2 = datetime.now()
dt3 = datetime.fromtimestamp(_time.time())
print(dt1)
print(dt2)
print(dt3)
​​​​2016-03-30 22:02:00
​​​​2017-06-21 18:33:15.273695
​​​​2017-06-21 18:33:15.273779
# combine date and time
dt = datetime.now()
dt = datetime.fromtimestamp(_time.time())

d = dt.date()
t = dt.time()

print("Date: {}\nTime: {}".format(d, t))
print("Datetime: {}".format(datetime.combine(date.today(), time(2,3,3))))
​​​​Date: 2017-06-21
​​​​Time: 18:34:31.443875
​​​​Datetime: 2017-06-21 02:03:03
# count day
from datetime import timedelta

td = timedelta(weeks=1, days=2, hours=3,minutes=4, seconds=0, microseconds=0, milliseconds=0)
print("Time duration: {}".format(td))
# minus
current=datetime.now()
today=datetime.combine(date.today(),time(0,0,0))
print("today: ",today)

td=current-today
print("{:.0f}s of Today".format(td.total_seconds()))

today=date.today()
lastyear=today.replace(year=today.year-1)
print(today-lastyear)

t1 = current.time()
t2 = time(0, 0, 0)
try:
    print(t1 - t2)
except TypeError as err:
    print(err)
# strftime & strptime
print(datetime.strftime.__doc__)
print(datetime.strptime.__doc__)

fmat = "%y-%m-%d"
dt = datetime.now()

s = dt.strftime(fmat)
print(s)
print(datetime.strptime(s, fmat))


fmat = "%y/%-m/%-d"
dt = datetime.now()
dt = dt - timedelta(days=22)

print(dt.strftime(fmat))
# or
print("{}/{}/{}".format(dt.strftime("%y"), dt.month, dt.day))
​​​​Time duration: 9 days, 3:04:00
​​​​today:  2017-06-21 00:00:00
​​​​67054s of Today
​​​​365 days, 0:00:00
​​​​unsupported operand type(s) for -: 'datetime.time' and 'datetime.time'
​​​​format -> strftime() style string.
​​​​string, format -> new datetime parsed from a string (like time.strptime()).
​​​​17-06-21
​​​​2017-06-21 00:00:00
​​​​17/5/30
​​​​17/5/30

decorator

# decorator example
def log(func):
    def wrapper():
        print("INFO: Starting {}".format(func.__name__))
        func()
        print("INFO: Finishing {}".format(func.__name__))
    return wrapper

@log
def run():
    print("Running run...")
    
run()
​​​​INFO: Starting run
​​​​Running run...
​​​​INFO: Finishing run
class HTML(object):
    """
     Baking HTML Tags!
    """

    def __init__(self, tag="p"):
        print("LOG: Baking Tag <{}>!".format(tag))
        self.tag = tag

    def __call__(self, func):
        return lambda: "<{0}>{1}</{0}>".format(self.tag, func(), self.tag)


@HTML("html")
@HTML("body")
@HTML("div")
def body():
    return "Hello"


print(body())
​​​​LOG: Baking Tag <html>!
​​​​LOG: Baking Tag <body>!
​​​​LOG: Baking Tag <div>!
​​​​<html><body><div>Hello</div></body></html>
# 傳遞參數
RULES = {}

def route(rule):  # rule is a string
    def decorator(hand):  # hand is a function
        RULES.update({rule: hand})  # 填充到RULES裡面
        return hand

    return decorator


@route("/")
def index():
    print("Hello world!")


def home():
    print("Welcome Home!")

# 將/home 和home()放進RULES
home = route("/home")(home)

index()
home()
print(RULES)  # 印出RULES dict的內容

@route("/login")
def login(user="user", pwd="pwd"):
    print("DB.findOne({{{}, {}}})".format(user, pwd))


login("hail", "python")
print(RULES)
​​​​Hello world!
​​​​Welcome Home!
​​​​{'/home': <function home at 0x7fd11facaa60>, '/': <function index at 0x7fd11faca840>}
​​​​DB.findOne({hail, python})
​​​​{'/home': <function home at 0x7fd11facaa60>, '/': <function index at 0x7fd11faca840>, '/login': <function login at 0x7fd11fa3f400>}
# sending paramerter
def log(f):
    def wraper(*args, **kargs):
        print("INFO: Start Logging")
        f(*args, **kargs)
        print("INFO: Finish Logging")

    return wraper


@log
def run(hello="world"):
    print("Hello {}".format(hello))


run("Python2")
​​​​INFO: Start Logging
​​​​Hello Python2
​​​​INFO: Finish Logging
from functools import update_wrapper
"""
functools.update_wrapper(wrapper, wrapped[, assigned][, updated])
"""


class HTML(object):
    """
        Baking HTML Tags!
    """

    def __init__(self, tag="p"):
        print("LOG: Baking Tag <{}>!".format(tag))
        self.tag = tag

    def __call__(self, func):
        def wraper():
            return "<{0}>{1}</{0}>".format(self.tag, func(), self.tag)

        update_wrapper(wraper, func)
        return wraper


@HTML("body")
def body():
    """
        return body content!
    """
    return "Hello, body!"


print(body.__name__)
print(body.__doc__)
print(body())
​​​​LOG: Baking Tag <body>!
​​​​body
​​​​
​​​​        return body content!
​​​​    
​​​​<body>Hello, body!</body>
# 利用partial 修飾
from functools import update_wrapper, partial

def my_wraps(wrapped):
    print(update_wrapper,wrapped)
    return partial(update_wrapper, wrapped=wrapped)

def log(func):
    @my_wraps(func)
    def wraper():
        print("INFO: Starting {}".format(func.__name__))
        func()
        print("INFO: Finishing {}".format(func.__name__))

    return wraper


@log
def run():
    """
    Docs' of run
    """
    print("Running run...")


print(run.__name__)
print(run.__doc__)
print(run())
​​​​<function update_wrapper at 0x7fd1515ebd08> <function run at 0x7fd11fa84510>
​​​​run
​​​​
​​​​    Docs' of run
​​​​    
​​​​INFO: Starting run
​​​​Running run...
​​​​INFO: Finishing run
​​​​None

heap and queue

from heapq import heapify,heappop,heappush
print(heapq.__all__)

heap=[]
heappush(heap,3)
heappush(heap,2)
heappush(heap,1)
print(heap)

# use heapify to turn list to heap 

heap=list(reversed(range(5)))
print("List: ",heap)
heapify(heap)
print("Heap: ",heap)

# heap 每次pop 出來的元素都會是最小的
heap=[2,3,4,1,2,4,6,7,11]
heapify(heap)
print(heappop(heap))
print(heappop(heap))
print(heappop(heap))
print(heappop(heap))
print(heap)
​​​​['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop']
​​​​[1, 3, 2]
​​​​List:  [4, 3, 2, 1, 0]
​​​​Heap:  [0, 1, 2, 4, 3]
​​​​1
​​​​2
​​​​2
​​​​3
​​​​[4, 6, 4, 7, 11]

queue

# queue.PriorityQueue 
from queue import PriorityQueue as PQueue
pq=PQueue()
pq.put((5*-1,'Python'))
pq.put((4*-1,'C'))
pq.put((4,'JS'))
pq.put((3*-1,'Java'))
pq.put((2*-1,'C++'))
print('Inside PriorityQueue: ',pq.queue)
while not pq.empty():
    print(pq.get()[1])
​​​​Inside PriorityQueue:  [(-5, 'Python'), (-4, 'C'), (4, 'JS'), (-3, 'Java'), (-2, 'C++')]
​​​​Python
​​​​C
​​​​Java
​​​​C++
​​​​JS
# 經過list.sort()的list一定是heap 反之未必,只有經過heapify()的heap 才是heap
# 而經過heappush()和heappop()都會對heap進行重新整理
import random
from heapq import nlargest,nsmallest
rand_list = [random.randrange(1, 100) for _ in range(5)]
rand_list.sort()
print("List: ", rand_list)
print("Poped: ", heappop(rand_list))
heappush(rand_list, 4)

print("Heap: ", rand_list)
print("N largest: ",nlargest(10,heap))
print("N smallest: ",nsmallest(10,heap))
print(len(heap))
​​​​List:  [19, 37, 45, 83, 85]
​​​​Poped:  19
​​​​Heap:  [4, 37, 45, 85, 83]
​​​​N largest:  [11, 7, 6, 4, 4]
​​​​N smallest:  [4, 4, 6, 7, 11]
​​​​5
# merge heap
from heapq import merge
heapA = sorted([random.randrange(1, 100) for _ in range(3)])
heapB = sorted([random.randrange(1, 100) for _ in range(3)])
print(heapA)
print(heapB)
merged = []
for i in merge(heapA, heapB):
    merged.append(i)
print(merged)
​​​​[18, 61, 85]
​​​​[14, 47, 75]
​​​​[14, 18, 47, 61, 75, 85]
# heappushpop and heap replace
from heapq import heapreplace,heappushpop
lstA = [1,2,3,4,5]
lstB = [1,2,3,4,5]

poped = heapreplace(lstA, 0)
print("lstA: ", lstA, "poped: ", poped)

# pop and push
poped = heappop(lstB)
heappush(lstB, 0)
print("lstB: ", lstA, "poped: ", poped)

print("*"*30)

poped = heappushpop(lstA, 9)
print("lstA: ", lstA, "poped: ", poped)

# is equal to...
heappush(lstB, 9)
poped = heappop(lstB)
print("lstB: ", lstB, "poped: ", poped)
​​​​lstA:  [0, 2, 3, 4, 5] poped:  1
​​​​lstB:  [0, 2, 3, 4, 5] poped:  1
​​​​******************************
​​​​lstA:  [2, 4, 3, 9, 5] poped:  0
​​​​lstB:  [2, 4, 3, 5, 9] poped:  0

_hash_ and _eq_

class Point:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, that):
        if not isinstance(that, Point):
            return False
        return self.x == that.x and self.y == that.y

    def __hash__(self):
        return 41 * (41 + self.x) + self.y


p1 = Point(1, 1)
p2 = Point(1, 1)
pset = {p1}
print(p2 in pset)


class Point:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, that):
        if not isinstance(that, Point):
            return False
        return self.x == that.x and self.y == that.y


class Point3D(Point):

    def __init__(self, x, y, z):
        super(Point3D, self).__init__(x, y)
        self.z = z

    def __eq__(self, that):
        if not isinstance(that, Point3D):
            return False
        return super(Point3D, self).__eq__(that) and self.z == that.z


p1 = Point(1, 1)
p2 = Point3D(1, 1, 1)
print(p1 == p2)

​​​​True
​​​​False

property

class Ball:
    def __init__(self, radius):
        if radius <= 0:
            raise ValueError('must be integer')
        self.__radius = radius
    
    def getRadius(self):
        return self.__radius
        
    def setRadius(self, radius):
        self.__radius = radius
        
    def delRadius(self):
        del self.__radius
    radius = property(getRadius, setRadius, delRadius, 'radius blablabla')

ball=Ball(12)
print (ball.radius)
ball.radius=123
print (ball.radius)


import math
class Ball:
    def __init__(self, radius):
        if radius <= 0:
            raise ValueError('must be integer')
        self.__radius = radius
    
    @property
    def radius(self):
        return self.__radius
    
    @property
    def volumn(self):
        return 4.0 / 3.0 * math.pi * self.__radius ** 3
    
    @volumn.setter
    def volumn(self, volumn):
        if volumn <= 0:
            raise ValueError('must be integer')
        self.__radius = ((3.0 * volumn) / (4.0 * math.pi)) ** (1.0 / 3.0)
        
ball = Ball(10.0)
print(ball.volumn)
ball.volumn = 5000
print(ball.radius)
​​​​12
​​​​123
​​​​4188.790204786391
​​​​10.60784417947055

profile

sending email by python

import smtplib

GMAIL_USER = 'EMAILADDRSS@gmail.com'
GMAIL_PASS = 'PASSWORD'
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587

def send_email(recipient, subject, text):
    smtpserver = smtplib.SMTP(SMTP_SERVER,SMTP_PORT)
    smtpserver.ehlo() #
    smtpserver.starttls() #
    smtp.ehlo #
    smtpserver.login(GMAIL_USER, GMAIL_PASS)
    header = 'TO:' + recipient + '\n' + 'From:' + GMAIL_USER
    msg = header + '\n' + text +'\n\n'
    smtpserver.sendmail(GMAIL_USER, recipient, msg)
    smtpserver.close()

shallow copy and deep copy

lst=[1,2,3]
# copy list in four ways
llst=[lst[:],lst,lst.copy(),[*lst]]

print(id(lst))
print(llst[0] is lst)
print(llst[1] is lst)
print(llst[2] is lst)
print(llst[3] is lst)

for i,v in enumerate(llst):
    v.append("#{}".format(i))
print(lst)
​​​​140245585483016
​​​​False
​​​​True
​​​​False
​​​​False
​​​​[1, 2, 3, '#1']
d={"a":0}
dd=[d,d.copy(),{**d}]
for i,v in enumerate(dd):
    v['dd']="#{}".format(i)
print(d)
​​​​{'dd': '#0', 'a': 0}
list_tmp=[1,3,4]
llist=lst[:]
llist.append("Wifi!!!!")
print(list_tmp)
​​​​[1, 3, 4]
list_tmp=[1,3,4]
llist=list_tmp
llist.append("Wifi!!!!")
print(list_tmp)
​​​​[1, 3, 4, 'Wifi!!!!']
list_tmp=[1,3,4]
llist=lst.copy()
llist.append("Wifi!!!!")
print(list_tmp)
​​​​[1, 3, 4]
list_tmp=[1,3,4]
llist=[*[list_tmp]]
llist.append("Wifi!!!!")
print(list_tmp)
​​​​[1, 3, 4]
# shallow copy 
d={"a":{"b":[0]}}
dd=[d,d.copy(),{**d}]

print(dd[0] is d)
print(dd[1] is d)
print(dd[2] is d)
​​​​True
​​​​False
​​​​False
# deepcopy 
from copy import deepcopy
# list
lst=[0,1,[2,3]]
lst2=deepcopy(lst)
lst2[2].append(4)
print(lst2)
print(lst)

# dict
d={"a":{"b":[0]}}
d2=deepcopy(d)
d2["a"]["b"].append(1)
print(d2)
print(d)
​​​​[0, 1, [2, 3, 4]]
​​​​[0, 1, [2, 3]]
​​​​{'a': {'b': [0, 1]}}
​​​​{'a': {'b': [0]}}

String format

print("{lang}.{suffix}".format(**{"lang":"Python","suffix":"py"}))
print("{} {}".format(*["Python","C++"]))

data={'name':'Python','score':100}
print("Name:{0[name]}, Score:{0[score]}".format(data))

langs=["Hello","hello!"]
print("{0[0]} vs {0[1]}".format(langs))

print("\n=======\nHelp(format):\n{.__doc__}".format(str.format))
​​​​Python.py
​​​​Python C++
​​​​Name:Python, Score:100
​​​​Hello vs hello!
​​​​
​​​​=======
​​​​Help(format):
​​​​S.format(*args, **kwargs) -> str
​​​​
​​​​Return a formatted version of S, using substitutions from args and kwargs.
​​​​The substitutions are identified by braces ('{' and '}').
#可以通共!+r|s|a的方式對替換的變量進行轉換:
#"{!r}"對變量調用repr()
#"{!s}"對變量調用str()
#"{!a}"對變量調用ascii()

#align 代表方向
#fill為填充的字符(默認空白)
for align, text in zip("<^>",["left","center","right"]):
    print("{:{fill}{align}16}".format(text, fill=align,align=align))

print("{:0=10}".format(100))
​​​​left<<<<<<<<<<<<
​​​​^^^^^center^^^^^
​​​​>>>>>>>>>>>right
​​​​0000000100
#強制顯示正負號
print("{0:+}\n{1:-}\n{0: }".format(3.14, -3.14))
​​​​+3.14
​​​​-3.14
​​​​ 3.14
# 用於表示特殊格式的(二進位to十進位)是否需要符號
print("Binary: {0:b}->{0:#b}".format(3))
​​​​Binary: 11->0b11
# 表示,
print("Large Number: {0:}->{0:,}".format(1.25e5))
​​​​Large Number: 125000.0->125,000.0
# 0靠右對齊補0
print("Padding: {0:16}->{0:016}".format(3))
​​​​Padding:                3->0000000000000003
# 小數點格式優化
from math import pi
print("pi={pi:.2},also={pi:.7}".format(pi=pi))
​​​​pi=3.1,also=3.141593
# Integer 
for t in "b c d #o #x #X n".split():
    print("Type {0:>2} of {1} shows:{1:{t}}".format(t,97,t=t))
print("---------------------------------------------------------")
​​​​Type  b of 97 shows:1100001
​​​​Type  c of 97 shows:a
​​​​Type  d of 97 shows:97
​​​​Type #o of 97 shows:0o141
​​​​Type #x of 97 shows:0x61
​​​​Type #X of 97 shows:0X61
​​​​Type  n of 97 shows:97
​​​​---------------------------------------------------------
# Float
for t,n in zip("eEfFgGn%",[1234,123,2.3,22.11,1,2,3.1415,0.98886]):
    print("Type {} shows:{:.2{t}}".format(t,n,t=t))
​​​​Type e shows:1.23e+03
​​​​Type E shows:1.23E+02
​​​​Type f shows:2.30
​​​​Type F shows:22.11
​​​​Type g shows:1
​​​​Type G shows:2
​​​​Type n shows:3.1
​​​​Type % shows:98.89%
# string
# 如果數字要印出來不用+s
try:
    print("{:s}".format(1234555))
except:
    print("{}".format(12345))
​​​​---------------------------------------------------------------------------

​​​​ValueError                                Traceback (most recent call last)

​​​​<ipython-input-51-15f35bbfb6a3> in <module>()
​​​​      2 # 如果數字要印出來不用+s
​​​​      3 
​​​​----> 4 print("{:s}".format(1234555))
​​​​

​​​​ValueError: Unknown format code 's' for object of type 'int'

String functions

hello = [i.upper()for i in 'hello']
s = u'你好'
print(s)
print(len(s))
print(s.encode())
​​​​你好
​​​​2
​​​​b'\xe4\xbd\xa0\xe5\xa5\xbd'
"""
unicode common func
"""
str1 = "Hello World"
print(",".join(str1.split()))
print("http://www.google.com".split("/", 2))  # 限定切分切兩次

str2 = "coffee"
print(str2.find('f'))
print(str2.index('f'))  # where the index is
print(str2.rfind('f'))  # find from right
print(str2.find('a'))
print(str2.rfind('a'))
# print(str2.index('a')) # if not in substring than raise ValueError
​​​​Hello,World
​​​​['http:', '', 'www.google.com']
​​​​2
​​​​2
​​​​3
​​​​-1
​​​​-1
"""
stripe
"""
print(" hello world    ".strip())
print("helloworld".strip("heo"))
print("[" + "          i         ".lstrip() + "]")
print("[" + "          i         ".rstrip() + "]")
print("[" + "          i         ".strip() + "]")


print("{}\n{}\n{}\n{}\n{}".format(
    "hello, WORLD".upper(),
    "hello, WORLD".lower(),
    "hello, WORLD".swapcase(),
    "hello, WORLD".capitalize(),
    "hello, WORLD".title()))
​​​​hello world
​​​​lloworld
​​​​[i         ]
​​​​[          i]
​​​​[i]
​​​​HELLO, WORLD
​​​​hello, world
​​​​HELLO, world
​​​​Hello, world
​​​​Hello, World
print("""
{}|{}
{}|{}
{}|{}
{}|{}
{}|{}
{}|{}
""".format(
    "Python".startswith("P"), "Python".startswith("y"),
    "Python".endswith("n"), "Python".endswith("o"),
    "i23o6".isalnum(), "1 2 3 0 6".isalnum(),
    "isalpha".isalpha(), "isa1pha".isalpha(),
    "python".islower(), "Python".islower(),
    "PYTHON".isupper(), "Python".isupper(),
))

print("HIHI".zfill(8))  # 回傳以 0 塞滿 width 的新字串
​​​​True|False
​​​​True|False
​​​​True|False
​​​​True|False
​​​​True|False
​​​​True|False
​​​​
​​​​0000HIHI

sorted

#Python 提供兩種排序方法,一種是針對List的原地排序list.sort()另一個是針對所有可迭代對象的sorted()

from random import randrange
lst=[randrange(1,100) for _ in range(10)]
print(lst)
lst.sort()
print(lst)
​​​​[16, 73, 80, 49, 30, 57, 19, 38, 80, 53]
​​​​[16, 19, 30, 38, 49, 53, 57, 73, 80, 80]
#sorted() 不限於list,且會生成一個新的排序後的list,原有對象不受影響

lst=[randrange(1,100) for _ in range(10)]
tup=tuple(lst)

print(sorted(lst))
print(tup)
print(sorted(tup))
​​​​[4, 25, 58, 65, 66, 67, 72, 76, 89, 94]
​​​​(72, 58, 67, 4, 65, 89, 76, 66, 94, 25)
​​​​[4, 25, 58, 65, 66, 67, 72, 76, 89, 94]
#透過key 指定排序
lst2=[randrange(1,100) for _ in range(10)]
print(lst2)
print(sorted(lst2,key=abs)) # 透過絕對值進行排序
​​​​[93, 36, 9, 67, 86, 55, 19, 23, 30, 84]
​​​​[9, 19, 23, 30, 36, 55, 67, 84, 86, 93]
# 當迭代對象教複雜時 可以只按照其中的某些屬性進行排序
lst3=list(zip("Today is a good day,so I have to go to school.".split(),[randrange(1,10) for _ in range(13)]))
print(lst3)
print(sorted(lst3,key=lambda item:item[1])) # 透過key進行排序(可改0)
​​​​[('Today', 3), ('is', 3), ('a', 4), ('good', 6), ('day,so', 3), ('I', 3), ('have', 3), ('to', 7), ('go', 1), ('to', 8), ('school.', 1)]
​​​​[('go', 1), ('school.', 1), ('Today', 3), ('is', 3), ('day,so', 3), ('I', 3), ('have', 3), ('a', 4), ('good', 6), ('to', 7), ('to', 8)]
# 可以過operator 獲取元素的屬性
from operator import itemgetter, attrgetter
print("-"*20)
print(sorted(lst3, key=itemgetter(1)))
​​​​--------------------
​​​​[('go', 1), ('school.', 1), ('Today', 3), ('is', 3), ('day,so', 3), ('I', 3), ('have', 3), ('a', 4), ('good', 6), ('to', 7), ('to', 8)]
# 和lambda item:item[1]))作用相同
fitemgetter=lambda ind:lambda item: item[ind]
print(sorted(lst3,key=fitemgetter(1)))

class P(object):
    def __init__(self, w, n):
        self.w=w
        self.n=n
    def __repr__(self):
        return "{}=>{}".format(self.w, self.n)
ps=[P(i[0],i[1]) for i in lst3]

print(sorted(ps,key=attrgetter('n')))
​​​​[('go', 1), ('school.', 1), ('Today', 3), ('is', 3), ('day,so', 3), ('I', 3), ('have', 3), ('a', 4), ('good', 6), ('to', 7), ('to', 8)]
​​​​[go=>1, school.=>1, Today=>3, is=>3, day,so=>3, I=>3, have=>3, a=>4, good=>6, to=>7, to=>8]
# python3 cmp using 
from functools import cmp_to_key as new_cmp_to_key
#new_cmp_to_key work like this
def cmp_to_key(mycmp):
    # convert a cmp= function into a kye= function 
    class K:
        def __init__(self,obj,*args):
            self.obj=obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj)
    return K
def reverse_cmp(x, y):
    return y[1]-x[1]
print(sorted(lst3,key=cmp_to_key(reverse_cmp)))
​​​​[('to', 8), ('go', 1), ('school.', 1), ('to', 7), ('good', 6), ('a', 4), ('Today', 3), ('is', 3), ('day,so', 3), ('I', 3), ('have', 3)]

testdoc

"""
This is the "example" module.

The example module supplies one function, factorial().  For example,

>>> factorial(5)
120
"""

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> [factorial(long(n)) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(30)
    265252859812191058636308480000000L
    >>> factorial(30L)
    265252859812191058636308480000000L
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    >>> factorial(30.1)
    Traceback (most recent call last):
        ...
    ValueError: n must be exact integer
    >>> factorial(30.0)
    265252859812191058636308480000000L

    It must also not be ridiculously large:
    >>> factorial(1e100)
    Traceback (most recent call last):
        ...
    OverflowError: n too large
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result


if __name__ == "__main__":
    import doctest
    doctest.testmod()

​​​​**********************************************************************
​​​​File "__main__", line 18, in __main__.factorial
​​​​Failed example:
​​​​    [factorial(long(n)) for n in range(6)]
​​​​Exception raised:
​​​​    Traceback (most recent call last):
​​​​      File "/usr/lib/python3.5/doctest.py", line 1321, in __run
​​​​        compileflags, 1), test.globs)
​​​​      File "<doctest __main__.factorial[1]>", line 1, in <module>
​​​​        [factorial(long(n)) for n in range(6)]
​​​​      File "<doctest __main__.factorial[1]>", line 1, in <listcomp>
​​​​        [factorial(long(n)) for n in range(6)]
​​​​    NameError: name 'long' is not defined
​​​​**********************************************************************
​​​​File "__main__", line 20, in __main__.factorial
​​​​Failed example:
​​​​    factorial(30)
​​​​Expected:
​​​​    265252859812191058636308480000000L
​​​​Got:
​​​​    265252859812191058636308480000000
​​​​**********************************************************************
​​​​File "__main__", line 22, in __main__.factorial
​​​​Failed example:
​​​​    factorial(30L)
​​​​Exception raised:
​​​​    Traceback (most recent call last):
​​​​      File "/usr/lib/python3.5/doctest.py", line 1321, in __run
​​​​        compileflags, 1), test.globs)
​​​​      File "<doctest __main__.factorial[3]>", line 1
​​​​        factorial(30L)
​​​​                    ^
​​​​    SyntaxError: invalid syntax
​​​​**********************************************************************
​​​​File "__main__", line 34, in __main__.factorial
​​​​Failed example:
​​​​    factorial(30.0)
​​​​Expected:
​​​​    265252859812191058636308480000000L
​​​​Got:
​​​​    265252859812191058636308480000000
​​​​**********************************************************************
​​​​1 items had failures:
​​​​   4 of   8 in __main__.factorial
​​​​***Test Failed*** 4 failures.

signal

import signal,functools
import time
class TimeoutError(Exception): pass 

def timeout(seconds, error_message = 'Function call timed out'):
    def decorated(func):
        def _handle_timeout(signum, frame):
            raise TimeoutError(error_message)
        def wrapper(*args, **kwargs):
            signal.signal(signal.SIGALRM, _handle_timeout)
            signal.alarm(seconds)
            try:
                result = func(*args, **kwargs)
            finally:
                signal.alarm(0)
            return result
        return functools.wraps(func)(wrapper)
    return decorated

@timeout(10,"hello world!")
def loop():
    while(1):
        time.sleep(5)
loop()
​​​​---------------------------------------------------------------------------

​​​​TimeoutError                              Traceback (most recent call last)

​​​​<ipython-input-73-6e8efc94b623> in <module>()
​​​​     22     while(1):
​​​​     23         time.sleep(5)
​​​​---> 24 loop()
​​​​

​​​​<ipython-input-73-6e8efc94b623> in wrapper(*args, **kwargs)
​​​​     11             signal.alarm(seconds)
​​​​     12             try:
​​​​---> 13                 result = func(*args, **kwargs)
​​​​     14             finally:
​​​​     15                 signal.alarm(0)


​​​​<ipython-input-73-6e8efc94b623> in loop()
​​​​     21 def loop():
​​​​     22     while(1):
​​​​---> 23         time.sleep(5)
​​​​     24 loop()


​​​​<ipython-input-73-6e8efc94b623> in _handle_timeout(signum, frame)
​​​​      6     def decorated(func):
​​​​      7         def _handle_timeout(signum, frame):
​​​​----> 8             raise TimeoutError(error_message)
​​​​      9         def wrapper(*args, **kwargs):
​​​​     10             signal.signal(signal.SIGALRM, _handle_timeout)


​​​​TimeoutError: hello world!