---
# System prepended metadata

title: effective python
tags: [python]

---

effective python
===
###### tags:`python`

# map and filter
```python
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
```
```python
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]




```python
squares=filter(lambda x:x%2==0,a)
[x for x in squares]
```




    [2, 4, 6, 8, 10]




```python
[x**2 for x in a]
```




    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]



# enumerate


```python
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')



```python
# 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


```python
brothers=["brother1","brother2","brother3","brother4"]
for i in zip(lolis,brothers):
    print(i)
```

    ('loli1', 'brother1')
    ('loli2', 'brother2')
    ('loli3', 'brother3')
    ('loli4', 'brother4')


# else after for



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

    0


# reversed iterate


```python
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}




```python
for i in reversed(list_example):
	print(i)
```

    4
    3
    2
    1
    0



```python
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



```python
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



```python
reversed(list_example)
```




    <list_reverseiterator at 0x7fc7b09cb358>




```python
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



```python
for i in countdown(4):
    print(i)
```

    4
    3
    2
    1



```python
count_rev=reversed(countdown(100))
next(count_rev)
```




    1



# for/try/else

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


```python
try:
    print("loli OUOb")
except:
    print("except occure!")
else:
    print("else statment")
finally:
    print("finally statement")
    
```

    loli OUOb
    else statment
    finally statement



```python
for x in [4,5,6,7,8]:
    if x>10:
        break
else:
    print("Hello world!")
```

    Hello world!


# decorator


```python
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加入參數


```python
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


```python
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


```python
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


```python
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


```python
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


```python
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


```python
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



# 關鍵字參數


```python
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


```python
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


```python
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]



```python
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__


```python
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


```python
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


```python
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


```python
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



```python
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'



```python
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



```python
# 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')



```python
# 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'




```python
def convert_bytes_to_str(converted:bytes)->int:
    return bytes(converted).decode('utf-8')
```


```python
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


```python
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



```python
_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


```python
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



```python
# 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



```python
# Time
t1 = time(22, 57, 6, 6)
t2 = datetime.now().time()
print(t1)
print(t2)
```

    22:57:06.000006
    18:33:00.607976



```python
# 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



```python
# 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



```python
# 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


```python
# 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



```python
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>



```python
# 傳遞參數
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>}



```python
# 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



```python
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>



```python
# 利用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


```python
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


```python
# 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



```python
# 經過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



```python
# 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]



```python
# 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\__



```python
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


```python
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



```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


```python
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']



```python
d={"a":0}
dd=[d,d.copy(),{**d}]
for i,v in enumerate(dd):
    v['dd']="#{}".format(i)
print(d)
```

    {'dd': '#0', 'a': 0}



```python
list_tmp=[1,3,4]
llist=lst[:]
llist.append("Wifi!!!!")
print(list_tmp)
```

    [1, 3, 4]



```python
list_tmp=[1,3,4]
llist=list_tmp
llist.append("Wifi!!!!")
print(list_tmp)
```

    [1, 3, 4, 'Wifi!!!!']



```python
list_tmp=[1,3,4]
llist=lst.copy()
llist.append("Wifi!!!!")
print(list_tmp)
```

    [1, 3, 4]



```python
list_tmp=[1,3,4]
llist=[*[list_tmp]]
llist.append("Wifi!!!!")
print(list_tmp)
```

    [1, 3, 4]



```python
# 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



```python
# 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


```python
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 '}').



```python
#可以通共！＋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



```python
#強制顯示正負號
print("{0:+}\n{1:-}\n{0: }".format(3.14, -3.14))
```

    +3.14
    -3.14
     3.14



```python
# 用於表示特殊格式的（二進位to十進位）是否需要符號
print("Binary: {0:b}->{0:#b}".format(3))
```

    Binary: 11->0b11



```python
# 表示,
print("Large Number: {0:}->{0:,}".format(1.25e5))
```

    Large Number: 125000.0->125,000.0



```python
# 0靠右對齊補0
print("Padding: {0:16}->{0:016}".format(3))
```

    Padding:                3->0000000000000003



```python
# 小數點格式優化
from math import pi
print("pi={pi:.2},also={pi:.7}".format(pi=pi))
```

    pi=3.1,also=3.141593



```python
# 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
    ---------------------------------------------------------



```python
# 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%



```python
# 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'



```python

```

## String functions


```python
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'



```python
"""
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



```python
"""
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



```python
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
#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]



```python
#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]



```python
#透過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]



```python
# 當迭代對象教複雜時 可以只按照其中的某些屬性進行排序
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)]



```python
# 可以過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)]



```python
# 和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]



```python
# 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


```python
"""
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


```python
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!
    
