Python Naming Rule¶
# see: PEP 8
# for class
#
# good:
# MyClass
# bad:
# myClass, my_class
MyClass
# for func, module, package, variables
#
# good:
# var_underscore_separate
# bad:
# varCamel, VarCamel
var_underscore_separate
# for public use
var
# for internal use
_var
# convention to avoid conflict keyword
var_
# for private use in class
__var
# for protect use in class
_var_
# "magic" method or attributes
# ex: __init__, __file__, __main__
__var__
# for "internal" use throwaway variable
# usually used in loop
# ex: [_ for _ in range(10)]
# or variable not used
# for _, a in [(1,2),(3,4)]: print a
_
Using __future__
backport features¶
# PEP 236 - Back to the __future__
# backport python3 print_function in python2
>>> print "Hello World" # print is a statement
Hello World
>>> from __future__ import print_function
>>> print "Hello World"
File "<stdin>", line 1
print "Hello World"
^
SyntaxError: invalid syntax
>>> print("Hello World") # print become a function
Hello World
# backport python3 unicode_literals in python2
>>> type("Guido") # string type is str in python2
<type 'str'>
>>> from __future__ import unicode_literals
>>> type("Guido") # string type become unicode
<type 'unicode'>
# backport PEP 238 -- Changing the Division Operator
>>> 1/2
0
>>> from __future__ import division
>>> 1/2 # return a float (classic division)
0.5
>>> 1//2 # return a int (floor division)
0
Note
from __future__ import feature
is a future statement.
It use for backporting features of other python version to
current python version, not like original import.
Check object attributes¶
# example of check list attributes
>>> dir(list)
['__add__', '__class__', ...]
Define a function __doc__
¶
# Define a function document
>>> def Example():
... """ This is an example function """
... print "Example function"
...
>>> Example.__doc__
' This is an example function '
# Or using help function
>>> help(Example)
Check instance type¶
>>> ex = 10
>>> isinstance(ex,int)
True
Check, Get, Set attribute¶
>>> class Example(object):
... def __init__(self):
... self.name = "ex"
... def printex(self):
... print "This is an example"
...
# Check object has attributes
# hasattr(obj, 'attr')
>>> ex = Example()
>>> hasattr(ex,"name")
True
>>> hasattr(ex,"printex")
True
>>> hasattr(ex,"print")
False
# Get object attribute
# getattr(obj, 'attr')
>>> getattr(ex,'name')
'ex'
# Set object attribute
# setattr(obj, 'attr', value)
>>> setattr(ex,'name','example')
>>> ex.name
'example'
Check inheritance¶
>>> class Example(object):
... def __init__(self):
... self.name = "ex"
... def printex(self):
... print "This is an Example"
...
>>> issubclass(Example, object)
True
Check all global variables¶
# globals() return a dictionary
# {'variable name': variable value}
>>> globals()
{'args': (1, 2, 3, 4, 5), ...}
Check callable¶
>>> a = 10
>>> def fun():
... print "I am callable"
...
>>> callable(a)
False
>>> callable(fun)
True
Get function/class name¶
>>> class ExampleClass(object):
... pass
...
>>> def example_function():
... pass
...
>>> ex = ExampleClass()
>>> ex.__class__.__name__
'ExampleClass'
>>> example_function.__name__
'example_function'
__new__
& __init__
¶
# __init__ will invoke
>>> class ClassA(object):
... def __new__(cls, arg):
... print '__new__ ' + arg
... return object.__new__(cls, arg)
... def __init__(self, arg):
... print '__init__ ' + arg
...
>>> o = ClassA("Hello")
__new__ Hello
__init__ Hello
# __init__ won't be invoke
>>> class ClassB(object):
... def __new__(cls, arg):
... print '__new__ ' + arg
... return object
... def __init__(self, arg):
... print '__init__ ' + arg
...
>>> o = ClassB("Hello")
__new__ Hello
The diamond problem¶
# The problem of multiple inheritance in searching a method
>>> def foo_a(self):
... print("This is ClsA")
...
>>> def foo_b(self):
... print("This is ClsB")
...
>>> def foo_c(self):
... print("This is ClsC")
...
>>> class Type(type):
... def __repr__(cls):
... return cls.__name__
...
>>> ClsA = Type("ClsA", (object,), {'foo': foo_a})
>>> ClsB = Type("ClsB", (ClsA,), {'foo': foo_b})
>>> ClsC = Type("ClsC", (ClsA,), {'foo': foo_c})
>>> ClsD = Type("ClsD", (ClsB, ClsC), {})
>>> ClsD.mro()
[ClsD, ClsB, ClsC, ClsA, <type 'object'>]
>>> ClsD().foo()
This is ClsB
Representations of your class behave¶
>>> class Example(object):
... def __str__(self):
... return "Example __str__"
... def __repr__(self):
... return "Example __repr__"
...
>>> print str(Example())
Example __str__
>>> Example()
Example __repr__
Break up a long string¶
# original long string
>>> s = 'This is a very very very long python string'
>>> s
'This is a very very very long python string'
# single quote with an escaping backslash
>>> s = "This is a very very very " \
... "long python string"
>>> s
'This is a very very very long python string'
# using brackets
>>> s = ("This is a very very very "
... "long python string")
>>> s
'This is a very very very long python string'
# using '+'
>>> s = ("This is a very very very " +
... "long python string")
>>> s
'This is a very very very long python string'
# using triple-quote with an escaping backslash
>>> s = '''This is a very very very \
... long python string'''
>>> s
'This is a very very very long python string'
Get list item SMART¶
>>> a = [1, 2, 3, 4, 5]
>>> a[0]
1
>>> a[-1]
5
>>> a[0:]
[1, 2, 3, 4, 5]
>>> a[:-1]
[1, 2, 3, 4]
# a[start:end:step]
>>> a[0:-1:2]
[1, 3]
# using slice object
# slice(start,end,step)
>>> s = slice(0, -1, 2)
>>> a[s]
[1, 3]
# Get index and item in loop
>>> a = range(3)
>>> for idx, item in enumerate(a):
... print (idx,item),
...
(0, 0) (1, 1) (2, 2)
# Transfer two list into tuple list
>>> a = [1, 2, 3, 4, 5]
>>> b = [2, 4, 5, 6, 8]
>>> zip(a, b)
[(1, 2), (2, 4), (3, 5), (4, 6), (5, 8)]
# with filter
>>> [x for x in range(5) if x > 1]
[2, 3, 4]
>>> l = ['1', '2', 3, 'Hello', 4]
>>> predicate = lambda x: isinstance(x, int)
>>> filter(predicate, l)
[3, 4]
# collect distinct objects
>>> a = [1, 2, 3, 3, 3]
>>> list({_ for _ in a})
[1, 2, 3]
# or
>>> list(set(a))
[1, 2, 3]
# reverse
>>> a = [1, 2, 3, 4, 5]
>>> a[::-1]
[5, 4, 3, 2, 1]
Get dictionary item SMART¶
# get dictionary all keys
>>> a = {"1":1, "2":2, "3":3}
>>> b = {"2":2, "3":3, "4":4}
>>> a.keys()
['1', '3', '2']
# get dictionary key and value as tuple
>>> a.items()
[('1', 1), ('3', 3), ('2', 2)]
# find same key between two dictionary
>>> [_ for _ in a.keys() if _ in b.keys()]
['3', '2']
# better way
>>> c = set(a).intersection(set(b))
>>> list(c)
['3', '2']
# or
>>> [_ for _ in a if _ in b]
['3', '2']
# update dictionary
>>> a.update(b)
>>> a
{'1': 1, '3': 3, '2': 2, '4': 4}
Set a list/dict SMART¶
# get a list with init value
>>> ex = [0] * 10
>>> ex
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# extend two list
>>> a = [1, 2, 3]; b = ['a', 'b']
>>> a + b
[1, 2, 3, 'a', 'b']
# using list comprehension
>>> [x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> fn = lambda x: x**2
>>> [fn(x) for x in range(5)]
[0, 1, 4, 9, 16]
>>> {'{0}'.format(x): x for x in range(3)}
{'1': 1, '0': 0, '2': 2}
# using builtin function "map"
>>> map(fn, range(5))
[0, 1, 4, 9, 16]
set
operations¶
# set comprehension
>>> a = [1, 2, 5, 6, 6, 6, 7]
>>> s = {x for x in a}
>>> s
set([1, 2, 5, 6, 7])
>>> s = {x for x in a if x > 3}
>>> s
set([5, 6, 7])
>>> s = {x if x > 3 else -1 for x in a}
>>> s
set([6, 5, -1, 7])
# uniquify list
>>> a = [1, 2, 2, 2, 3, 4, 5, 5]
>>> a
[1, 2, 2, 2, 3, 4, 5, 5]
>>> ua = list(set(a))
>>> ua
[1, 2, 3, 4, 5]
# union two set
>>> a = set([1, 2, 2, 2, 3])
>>> b = set([5, 5, 6, 6, 7])
>>> a | b
set([1, 2, 3, 5, 6, 7])
# or
>>> a = [1, 2, 2, 2, 3]
>>> b = [5, 5, 6, 6, 7]
>>> set(a + b)
set([1, 2, 3, 5, 6, 7])
# append item to set
>>> a = set([1, 2, 3, 3, 3])
>>> a.add(5)
>>> a
set([1, 2, 3, 5])
# or
>>> a = set([1, 2, 3, 3, 3])
>>> a |= set([1, 2, 3, 4, 5, 6])
>>> a
set([1, 2, 3, 4, 5, 6])
# intersection two set
>>> a = set([1, 2, 2, 2, 3])
>>> b = set([1, 5, 5, 6, 6, 7])
>>> a & b
set([1])
# get two list common items
>>> a = [1, 1, 2, 3]
>>> b = [1, 3, 5, 5, 6, 6]
>>> com = list(set(a) & set(b))
>>> com
[1, 3]
# b contains a
>>> a = set([1, 2])
>>> b = set([1, 2, 5, 6])
>>> a <=b
True
# a contains b
>>> a = set([1, 2, 5, 6])
>>> b = set([1, 5, 6])
>>> a >= b
True
# set diff
>>> a = set([1, 2, 3])
>>> b = set([1, 5, 6, 7, 7])
>>> a - b
set([2, 3])
# symmetric diff
>>> a = set([1,2,3])
>>> b = set([1, 5, 6, 7, 7])
>>> a ^ b
set([2, 3, 5, 6, 7])
NamedTuple¶
# namedtuple(typename, field_names)
# replace define class without method
>>> from collections import namedtuple
>>> Example = namedtuple("Example",'a b c')
>>> e = Example(1, 2, 3)
>>> print e.a, e[1], e[1] + e.b
1 2 4
__iter__
- Delegating Iteration¶
# __iter__ return an iterator object
# Be careful: list is an "iterable" object not an "iterator"
>>> class Example(object):
... def __init__(self,list_):
... self._list = list_
... def __iter__(self):
... return iter(self._list)
...
>>> ex = Example([1, 2, 3, 4, 5])
>>> for _ in ex: print _,
...
1 2 3 4 5
Using Generator as Iterator¶
# see: PEP289
>>> a = (_ for _ in range(10))
>>> for _ in a: print _,
...
0 1 2 3 4 5 6 7 8 9
# equivalent to
>>> def generator():
... for _ in range(10):
... yield _
...
>>> for _ in generator(): print _,
...
0 1 2 3 4 5 6 7 8 9
Emulating a list¶
>>> class EmuList(object):
... def __init__(self, list_):
... self._list = list_
... def __repr__(self):
... return "EmuList: " + repr(self._list)
... def append(self, item):
... self._list.append(item)
... def remove(self, item):
... self._list.remove(item)
... def __len__(self):
... return len(self._list)
... def __getitem__(self, sliced):
... return self._list[sliced]
... def __setitem__(self, sliced, val):
... self._list[sliced] = val
... def __delitem__(self, sliced):
... del self._list[sliced]
... def __contains__(self, item):
... return item in self._list
... def __iter__(self):
... return iter(self._list)
...
>>> emul = EmuList(range(5))
>>> emul
EmuList: [0, 1, 2, 3, 4]
>>> emul[1:3] # __getitem__
[1, 2]
>>> emul[0:4:2] # __getitem__
[0, 2]
>>> len(emul) # __len__
5
>>> emul.append(5)
>>> emul
EmuList: [0, 1, 2, 3, 4, 5]
>>> emul.remove(2)
>>> emul
EmuList: [0, 1, 3, 4, 5]
>>> emul[3] = 6 # __setitem__
>>> emul
EmuList: [0, 1, 3, 6, 5]
>>> 0 in emul # __contains__
True
Emulating a dictionary¶
>>> class EmuDict(object):
... def __init__(self, dict_):
... self._dict = dict_
... def __repr__(self):
... return "EmuDict: " + repr(self._dict)
... def __getitem__(self, key):
... return self._dict[key]
... def __setitem__(self, key, val):
... self._dict[key] = val
... def __delitem__(self, key):
... del self._dict[key]
... def __contains__(self, key):
... return key in self._dict
... def __iter__(self):
... return iter(self._dict.keys())
...
>>> _ = {"1":1, "2":2, "3":3}
>>> emud = EmuDict(_)
>>> emud # __repr__
EmuDict: {'1': 1, '2': 2, '3': 3}
>>> emud['1'] # __getitem__
1
>>> emud['5'] = 5 # __setitem__
>>> emud
EmuDict: {'1': 1, '2': 2, '3': 3, '5': 5}
>>> del emud['2'] # __delitem__
>>> emud
EmuDict: {'1': 1, '3': 3, '5': 5}
>>> for _ in emud: print emud[_], # __iter__
...
1 3 5
>>> '1' in emud # __contains__
True
Emulating a matrix multiplication¶
# PEP 465 - "@" represent matrix multiplication
#
# Need Python-3.5 or above
>>> class Arr:
... def __init__(self, *arg):
... self._arr = arg
... def __matmul__(self, other):
... if not isinstance(other, Arr):
... raise TypeError
... if len(self) != len(other):
... raise ValueError
... return sum([x*y for x, y in zip(self._arr, other._arr)])
... def __imatmul__(self, other):
... if not isinstance(other, Arr):
... raise TypeError
... if len(self) != len(other):
... raise ValueError
... res = sum([x*y for x, y in zip(self._arr, other._arr)])
... self._arr = [res]
... return self
... def __len__(self):
... return len(self._arr)
... def __str__(self):
... return self.__repr__()
... def __repr__(self):
... return "Arr({})".format(repr(self._arr))
...
>>> a = Arr(9, 5, 2, 7)
>>> b = Arr(5, 5, 6, 6)
>>> a @ b # __matmul__
124
>>> a @= b # __imatmul__
>>> a
Arr([124])
Decorator¶
# see: PEP318
>>> from functools import wraps
>>> def decorator(func):
... @wraps(func)
... def wrapper(*args, **kwargs):
... print "Before calling {}.".format(func.__name___)
... ret = func(*args, **kwargs)
... print "After calling {}.".format(func.__name___)
... return ret
... return wrapper
...
>>> @decorator
... def example():
... print "Inside example function."
...
>>> example()
Before calling example.
Inside example function.
After calling example.
# equivalent to
... def example():
... print "Inside example function."
...
>>> example = decorator(example)
>>> example()
Before calling example.
Inside example function.
After calling example.
Note
@wraps
preserve attributes of the original function,
otherwise attributes of decorated function will be replaced
by wrapper function
# without @wraps
>>> def decorator(func):
... def wrapper(*args, **kwargs):
... print('wrap function')
... return func(*args, **kwargs)
... return wrapper
...
>>> @decorator
... def example(*a, **kw):
... pass
...
>>> example.__name__ # attr of function lose
'wrapper'
# with @wraps
>>> from functools import wraps
>>> def decorator(func):
... @wraps(func)
... def wrapper(*args, **kwargs):
... print('wrap function')
... return func(*args, **kwargs)
... return wrapper
...
>>> @decorator
... def example(*a, **kw):
... pass
...
>>> example.__name__ # attr of function preserve
'example'
Decorator with arguments¶
>>> from functools import wraps
>>> def decorator_with_argument(val):
... def decorator(func):
... @wraps(func)
... def wrapper(*args, **kwargs):
... print "Val is {0}".format(val)
... return func(*args, **kwargs)
... return wrapper
... return decorator
...
>>> @decorator_with_argument(10)
... def example():
... print "This is example function."
...
>>> example()
Val is 10
This is example function.
# equivalent to
>>> def example():
... print "This is example function."
...
>>> example = decorator_with_argument(10)(example)
>>> example()
Val is 10
This is example function.
for: exp else: exp¶
# see document: More Control Flow Tools
# forloop’s else clause runs when no break occurs
>>> for _ in range(5):
... print _,
... else:
... print "\nno break occurred"
...
0 1 2 3 4
no break occurred
>>> for _ in range(5):
... if _ % 2 == 0:
... print "break occurred"
... break
... else:
... print "no break occurred"
...
break occurred
# above statement equivalent to
flag = False
for _ in range(5):
if _ % 2 == 0:
flag = True
print "break occurred"
break
if flag == False:
print "no break occurred"
try: exp else: exp¶
# No exception occur will go into else.
>>> try:
... print "No exception"
... except:
... pass
... else:
... print "No exception occurred"
...
No exception
No exception occurred
Lambda function¶
>>> fn = lambda x: x**2
>>> fn(3)
9
>>> (lambda x: x**2)(3)
9
>>> (lambda x: [x*_ for _ in range(5)])(2)
[0, 2, 4, 6, 8]
>>> (lambda x: x if x>3 else 3)(5)
5
# multiline lambda example
>>> (lambda x:
... True
... if x>0
... else
... False)(3)
True
Option arguments - (*args, **kwargs)¶
>>> def example(a, b=None, *args, **kwargs):
... print a, b
... print args
... print kwargs
...
>>> example(1, "var", 2, 3, word="hello")
1 var
(2, 3)
{'word': 'hello'}
>>> a_tuple = (1, 2, 3, 4, 5)
>>> a_dict = {"1":1, "2":2, "3":3}
>>> example(1, "var", *a_tuple, **a_dict)
1 var
(1, 2, 3, 4, 5)
{'1': 1, '2': 2, '3': 3}
type()
declare (create) a class
¶
>>> def fib(self, n):
... if n <= 2:
... return 1
... return fib(self, n-1) + fib(self, n-2)
...
>>> Fib = type('Fib', (object,), {'val': 10,
... 'fib': fib})
>>> f = Fib()
>>> f.val
10
>>> f.fib(f.val)
55
# equal to
>>> class Fib(object):
... val = 10
... def fib(self, n):
... if n <=2:
... return 1
... return self.fib(n-1)+self.fib(n-2)
...
>>> f = Fib()
>>> f.val
10
>>> f.fib(f.val)
55
Callable object¶
>>> class CallableObject(object):
... def example(self, *args, **kwargs):
... print "I am callable!"
... def __call__(self, *args, **kwargs):
... self.example(*args, **kwargs)
...
>>> ex = CallableObject()
>>> ex()
I am callable!
Context Manager - with
statement¶
# replace try: ... finally: ...
# see: PEP343
# common use in open and close
import socket
class Socket(object):
def __init__(self,host,port):
self.host = host
self.port = port
def __enter__(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((self.host,self.port))
sock.listen(5)
self.sock = sock
return self.sock
def __exit__(self,*exc_info):
if exc_info[0] is not None:
import traceback
traceback.print_exception(*exc_info)
self.sock.close()
if __name__=="__main__":
host = 'localhost'
port = 5566
with Socket(host, port) as s:
while True:
conn, addr = s.accept()
msg = conn.recv(1024)
print msg
conn.send(msg)
conn.close()
Using @contextmanager
¶
from contextlib import contextmanager
@contextmanager
def opening(filename, mode='r'):
f = open(filename, mode)
try:
yield f
finally:
f.close()
with opening('example.txt') as fd:
fd.read()
Using with
statement open file¶
>>> with open("/etc/passwd",'r') as f:
... content = f.read()
Reading file chunk¶
>>> chunk_size = 16
>>> content = ''
>>> with open('/etc/hosts') as f:
... for c in iter(lambda: f.read(chunk_size), ''):
... content += c
...
>>> print(content)
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
10.245.1.3 www.registry.io
Property - Managed attributes¶
>>> class Example(object):
... def __init__(self, value):
... self._val = value
... @property
... def val(self):
... return self._val
... @val.setter
... def val(self, value):
... if not isintance(value, int):
... raise TypeError("Expected int")
... self._val = value
... @val.deleter
... def val(self):
... del self._val
...
>>> ex = Example(123)
>>> ex.val = "str"
Traceback (most recent call last):
File "", line 1, in
File "test.py", line 12, in val
raise TypeError("Expected int")
TypeError: Expected int
# equivalent to
>>> class Example(object):
... def __init__(self, value):
... self._val = value
...
... def _val_getter(self):
... return self._val
...
... def _val_setter(self, value):
... if not isintance(value, int):
... raise TypeError("Expected int")
... self._val = value
...
... def _val_deleter(self):
... del self._val
...
... val = property(fget=_val_getter, fset=_val_setter, fdel=_val_deleter, doc=None)
...
Computed attributes - Using property¶
>>> class Example(object):
... @property
... def square3(self):
... return 2**3
...
>>> ex = Example()
>>> ex.square3
8
Note
@property
compute the value of attribute only when we need.
Not store in memory previously.
Descriptor - manage attributes¶
>>> class Integer(object):
... def __init__(self, name):
... self._name = name
... def __get__(self, inst, cls):
... if inst is None:
... return self
... else:
... return inst.__dict__[self._name]
... def __set__(self, inst, value):
... if not isinstance(value, int):
... raise TypeError("Expected int")
... inst.__dict__[self._name] = value
... def __delete__(self,inst):
... del inst.__dict__[self._name]
...
>>> class Example(object):
... x = Integer('x')
... def __init__(self, val):
... self.x = val
...
>>> ex1 = Example(1)
>>> ex1.x
1
>>> ex2 = Example("str")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
File "<stdin>", line 11, in __set__
TypeError: Expected an int
>>> ex3 = Example(3)
>>> hasattr(ex3, 'x')
True
>>> del ex3.x
>>> hasattr(ex3, 'x')
False
@staticmethod
, @classmethod
¶
# @classmethod: bound to class
# @staticmethod: like python function but in class
>>> class example(object):
... @classmethod
... def clsmethod(cls):
... print "I am classmethod"
... @staticmethod
... def stmethod():
... print "I am staticmethod"
... def instmethod(self):
... print "I am instancemethod"
...
>>> ex = example()
>>> ex.clsmethod()
I am classmethod
>>> ex.stmethod()
I am staticmethod
>>> ex.instmethod()
I am instancemethod
>>> example.clsmethod()
I am classmethod
>>> example.stmethod()
I am staticmethod
>>> example.instmethod()
Traceback (most recent call last):
File "", line 1, in
TypeError: unbound method instmethod() ...
Abstract method - Metaclass¶
# usually using in define methods but not implement
>>> from abc import ABCMeta, abstractmethod
>>> class base(object):
... __metaclass__ = ABCMeta
... @abstractmethod
... def absmethod(self):
... """ Abstract method """
...
>>> class example(base):
... def absmethod(self):
... print "abstract"
...
>>> ex = example()
>>> ex.absmethod()
abstract
# another better way to define a meta class
>>> class base(object):
... def absmethod(self):
... raise NotImplementedError
...
>>> class example(base):
... def absmethod(self):
... print "abstract"
...
>>> ex = example()
>>> ex.absmethod()
abstract
Common Use Magic¶
# see python document: data model
# For command class
__main__
__name__
__file__
__module__
__all__
__dict__
__class__
__doc__
__init__(self, [...)
__str__(self)
__repr__(self)
__del__(self)
# For Descriptor
__get__(self, instance, owner)
__set__(self, instance, value)
__delete__(self, instance)
# For Context Manager
__enter__(self)
__exit__(self, exc_ty, exc_val, tb)
# Emulating container types
__len__(self)
__getitem__(self, key)
__setitem__(self, key, value)
__delitem__(self, key)
__iter__(self)
__contains__(self, value)
# Controlling Attribute Access
__getattr__(self, name)
__setattr__(self, name, value)
__delattr__(self, name)
__getattribute__(self, name)
# Callable object
__call__(self, [args...])
# Compare related
__cmp__(self, other)
__eq__(self, other)
__ne__(self, other)
__lt__(self, other)
__gt__(self, other)
__le__(self, other)
__ge__(self, other)
# arithmetical operation related
__add__(self, other)
__sub__(self, other)
__mul__(self, other)
__div__(self, other)
__mod__(self, other)
__and__(self, other)
__or__(self, other)
__xor__(self, other)
Parsing csv string¶
# python2 and python3 compatible
>>> try:
... from StringIO import StringIO # for py2
... except ImportError:
... from io import StringIO # for py3
...
>>> import csv
>>> s = "foo,bar,baz"
>>> f = StringIO(s)
>>> for x in csv.reader(f): print(x)
...
['foo', 'bar', 'baz']
# or
>>> import csv
>>> s = "foo,bar,baz"
>>> for x in csv.reader([s]): print(x)
...
['foo', 'bar', 'baz']
Using annotation to check type¶
# need python3 (PEP: 3107)
from functools import wraps
import inspect
ANNO_EMPTY = inspect._empty
def check_args(sig, *a, **k):
bind = sig.bind(*a, **k)
params = sig.parameters
for name, val in bind.arguments.items():
anno = params[name].annotation
if anno is ANNO_EMPTY:
continue
if isinstance(val, anno):
continue
atype = type(val)
raise TypeError(f"type({name}) is '{anno}', not '{atype}'")
def check_ret(sig, ret):
anno = sig.return_annotation
if anno is ANNO_EMPTY:
return ret
elif isinstance(ret, anno):
return ret
rtype = type(ret)
raise TypeError(f"type(ret) is '{anno}', not '{rtype}'")
def typechecked(func):
sig = inspect.signature(func)
@wraps(func)
def wrapper(*a, **k):
check_args(sig, *a, **k)
return check_ret(sig, func(*a, **k))
return wrapper
@typechecked
def test1(a: int)->int:
return a
@typechecked
def test2(a: int):
return a
@typechecked
def test3(a)->str:
return a
@typechecked
def test4(a, b: str, c: str="c")->list:
return [a, b, c]
print(test1(9527))
print(test2(9487))
print(test3("Hello Python3"))
print(test4(9487, "bb", c="cc"))
try:
print(test3(9487))
except TypeError as e:
print(e)
try:
print(test4(5566, 9527))
except TypeError as e:
print(e)
try:
print(test4(123, "b", c=5566))
except TypeError as e:
print(e)
output:
9527
9487
Hello Python3
[9487, 'bb', 'cc']
type(ret) is '<class 'str'>', not '<class 'int'>'
type(b) is '<class 'str'>', not '<class 'int'>'
type(c) is '<class 'str'>', not '<class 'int'>'