data structure

数据类型

  • None immutable 不是保留关键字,NoneType的一个实例
  • str 'a' "a" immutable
  • tuple元组 (3,4) immutable的对象序列
  • unicode immutable
  • int float long immutable
  • bool immutable
  • list
  • set unique
  • dict key-value
  • np数组

True False

\转义

数字进制

print(0b1110)     # 二进制,以0b开头
print(0o10)       # 八进制,以0o开头
print(0x2A)       # 十六进制,以0x开头

数组

数组index

范围引用: 基本样式[下限:上限:步长]

尾部元素引用(tuple and list)

数组range & xrange

数组range & xrange

xrange不会预先产生所有的值,并将它们保存到列表,而是返回一个逐个产生整数的迭代器

内置的序列函数

enumerate 返回(index, item)

enumerate(collection)
  • sorted 返回有序的list 接受iterable对象参数
  • reversed 按逆序迭代元素 list(reversed(range(10)))

zip(seq1, seq2, ...) 返回tuple的list,舍弃冗余 zip(*some_tuple_list) 如果你多个等长的序列,然后想要每次循环时从各个序列分别取出一个元素,可以利用zip()方便地实现:

ta = [1,2,3] tb = [9,8,7] tc = ['a','b','c'] for (a,b,c) in zip(ta,tb,tc): print(a,b,c)

for i, (a, b) in enumerate(zip(seq1, seq2)):
    print('%d: %s, %s' % (i, a, b))

string

as list

raw_input("input u idiot :")

print "%.2f" % (total)

character in string c = "cats"[0]

method

len(string) and str(object), but dot notation (such as "String".upper()) for the rest

  • len(str)
  • .lower()
  • .upper()
  • str(str)
  • .isalpha()

print "Hello %s" % (name) print "The %s who %s %s!" % ("Knights", "say", "Ni")

numberOfLines = len(fr.readlines())

for line in fr.readlines():
    line = line.strip() # 去掉文本回车
    listFromLine = line.split('\t')

tuple ()

tuple元素不可变,list元素可变

tuple有隐含or的意思,可以作为dict的key

(3,'q') + (0) #(3, 'q', 0)

tup = 4, 5, (7, 9)
a, b, (c ,d) = tup  #d = 9`

tup.cpunt(2) #2出现的次数

list []

l = [item1, item2]

逆向负数索引

  • len(l)
  • l.count(some_value)
  • l.append(item) l.remove(item)
  • l.insert(index, item) l.pop(index)
  • l.index(item1) # in set;use for item in list
  • l.sort()
  • print "--".join(l) #分隔符
  • "+"[None, 4] + [2, (2, 'a')] #[None, 4, 2, (2, 'a')]
  • l.extend(some_list) 合并list
  • l.sort .sort(key=len) 就地排序(按长度)
  • l.is_unique
  • [0]*3 # 初始化[0, 0, 0] 区别np.zeros((3)) [0. 0. 0.]

  • del(l[index])

  • mean(l)
`for itemt in range(0, len(l))
    l.append(["O"] * 5)`

dict {}

与表不同的是,词典的元素没有顺序。你不能通过下标引用元素。词典是通过键来引用

  • dic.get(index, def_value)
  • dic.keys()
  • dic.values()
  • dic.items() 返回dic所有的元素(键值对)
  • dic.clear()
  • del dic['tom']
  • dic.iteritems() #dict的value的iter对象,可用于sorted/reversed

本质上是二元组集

dict(zip(list_a, list_b))

d = {'key1' : 1, 'key2' : 2, ('key3', 'key4') : 7}
print d['key1']    

del d[key]
d.pop('key3', defvalue)
d.get('key3', defvalue)

d.items()
d.keys() #key list
d.values() #value list,**not iterable**

4 in d #False

d.update(some_dict) #合并dict

d.setdefault(key, defval).append(val) #有key append, 无key设置位defval
import collections import defaultdict 
defaulydict(list) #默认defval 为[]

两个相同key的dict可以一起循环

默认只循环key

for key in d
    print d[key]

双项循环

for index, item in enumerate(d):

zip 合并,舍弃冗余项

for a, b in zip(list_a, list_b): #[(a1, b1), (a2, b2) ]

set(集合) set([]) 和 {}

set([1, 2, 2]) #set([1, 2])

集合运算结果是set ;& | - ^ set_a.issubset(set_b) .superset

set有两种 set frozenset(元素不可变,不支持add remove操作)

  • seta.intersection(setb) # seta.intersection(item)也行

sort

operator.itemgetter 返回 获取对象的哪些维的数据 的函数对象

import operator
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
sorted(students, key=lambda student : student[2], reverse=True)
sorted(students, key=operator.itemgetter(2))  # equal
# key=operator.itemgetter(0,2) 对第0个/第2个域排序 ;
# dict 两个域 sorted(dict) 返回格式[(key, value)...]

二分查找

bisect不会判断原序列有序

import bisect
bisect.bisect(some_list.3) #找出插入位置
bisect.insort(some_list.3) #插入位置

动态类型

即使是多个引用指向同一个对象,如果一个引用值发生变化,那么实际上是让这个引用指向一个新的引用,并不影响其他的引用的指向

  • 改变对象自身(in-place change) #做函数参数改变原值
  • 不可变数据对象(immutable object) #做函数参数改变原值(可读),可以用global(局部作用域用nonlocal) 声明成in-place var
    • int str
    • tumple

推导式

在一组序列对象上执行相同的操作,返回序列对象

[expr for val in collection if condition]

{key-expr : value-expr for key, value in enumerate(collection) if condition}

{expr for val in collection if condition}

dict((key-expr, val-expr) for key, val in enumerate(sone_list))
{key-expr : val-expr for key, val in enumerate(sone_list)}

[json.loads(line) for line in open(path)]

for 嵌套

name-expr for names in family for name in names ...

语法

Exception异常

如果无法将异常交给合适的对象,异常将继续向上层抛出,直到被捕捉或者造成主程序报错

  • try: ... except exception: ... else: ... finally: ...
  • raise exception

try: for i in range(100): print re.next() except StopIteration: print 'here is end ',i except: print("Not Type Error & Error noted")

try: assert 1 == 2,'1 is not equal 2' except Exception,e: print '%s:%s' %(e.class.name,e) pass

type convertion类型转换

convertion

int("33")

list(var)

bool(var)

set(var)

hash(var) #hash函数,本质上不是理解的类型转换

判断

type(a)

type(obj).__name__=='dict'

isinstance(a, (int, float))

isinstance(3,(int,float))

None不是保留关键字,而是NoneType的一个实例

二元运算符

is 判断引用相等

== value相等

**次方

& | 逻辑判断or对于整数按位与或

^ 异或

loop

  • range()
  • enumerate() #for (index, value) in enumerate(struct)
  • zip()多个等长的列 # for (a,b,c) in zip(ta,tb,tc):

生成器 yield

定义了 __iter__ next()的对象

class count_iterator(object):

    def __iter__(self):
        return self

    def next(self):
        pass

a_l.extend(b_l) 是一个迭代器方法

但是在你的代码中的是一个生成器,这是不错的,因为:

你不必读两次所有的值
你可以有很多子对象,但不必叫他们都存储在内存里面。
并且这很奏效,因为Python不关心一个方法的参数是不是个链表。Python只希望它是个可以迭代的,所以这个参数可以是链表,元组,字符串,生成器... 这叫做 duck typing,这也是为何Python如此棒的原因之一

生成器是可以迭代的,但是你 只可以读取它一次 ,因为它并不把所有的值放在内存中,它是实时地生成数据

mygenerator = (x*x for x in range(3))
    for i in mygenerator :
...

def createGenerator() :
...    mylist = range(3)
...    for i in mylist :
...        yield i*i

yield 是一个类似 return 的关键字,只是这个函数返回的是个生成器

调用这个函数的时候,函数内部的代码并不立马执行 ,这个函数只是返回一个生成器对象

迭代是一个实现可迭代对象(实现的是 iter() 方法)和迭代器(实现的是 next() 方法)的过程。

itertools包含了很多特殊的迭代方法

I/O file读写

  • Read-only: r
  • Write-only: w
  • Append a file: a
  • Read and Write: r+
  • Binary mode: b
    • Note: Use for binary files, especially on Windows.

open()返回的实际上是一个循环对象,包含有next()方法。而该next()方法每次返回的就是新的一行的内容,到达文件结尾时举出StopIteration

content = f.read(N) # 读取N bytes的数据

content = f.readline() # 读取一行

content = f.readlines() # 读取所有行,储存在列表中,每个元素是一行。

f.write('I like apple') # 将'I like apple'写入文件

关闭文件:

f.close()

with open('x.txt','r') as f:
    data = f.read()

conditional 条件关系

and or not

== !=

if exp:
elif exp:
else: 

while exp:
else

for value in collection/interator:
else: #executed only if for ends normal(e.g. break makes else no-running)

pass
break
continue

嵌套

def a:
    def b:#b只在a执行时定义,a运行结束后销毁

class

metaclass

“元类就是深度的魔法,99%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类。” —— Python界的领袖 Tim Peters

元类的主要用途是创建API

class A声明A是一种类/metaclass(元类)对象,A.metaclass是元类,元类就是用来创建类的“东西”(类的工厂类)。使用class关键字时,Python解释器自动创建这个class对象.

class A(object):
    pass

理解为

A = MetaClass(); obj = A()

背后由type实现。这是因为函数type实际上是一个元类。type就是Python在背后用来创建所有类的元类。type就是创建类对象的类

def foo:
    pass
print foo.__class__ # <type 'function'>
print foo.__class__.__class__ # <type 'type'>

type可以接受一个类的描述作为参数,然后返回一个元类对象

type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))

class FooChild(Foo):
    def echo_bar(self):
        print self.bar
    pass

等价于

# type组装
def echo_bar(self):
    print self.bar
FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})  # 返回一个类对象

自定义metaclass

# 请记住,'type'实际上是一个类,就像'str'和'int'一样
# 所以,你可以从type继承
class UpperAttrMetaClass(type):
    # __new__ 是在__init__之前被调用的特殊方法
    # __new__是用来创建对象并返回之的方法
    # 而__init__只是用来将传入的参数初始化给对象
    # 你很少用到__new__,除非你希望能够控制对象的创建
    # 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__
    # 如果你希望的话,你也可以在__init__中做些事情
    # 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用
    def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr):
        attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
        uppercase_attr = dict((name.upper(), value) for name, value in attrs)
        return type(future_class_name, future_class_parents, uppercase_attr)

装饰器

  • @property
  • @staticmethod
  • @classmethod
def __init__(self, var):
    pass

def func(self):
    pass

# @classmethod因为持有cls参数,可以来调用类的属性,类的方法
@classmethod
def method(cls,...)
    print cls.class_var

公共属性

__class__
__metaclass__  在类的定义时,Python就会用它来创建类,如果没有找到,就会用内建的type来创建这个类
hasattr(Foo, 'bar')

example

所有python对象共有三个属性:id,type,value

class Student(object):
    wtf = 'ttt' # class var
    def __init__(self, name, item):
        self.name = name # obj var
        self. __set_item()
        self.some_list = [] # init others; optional

    def set_age(self, age):
        self.age = age

    def __set_item(self, item): # private method
        self.__item = item # private value

    update_item = __set_item # copy private method

c = Student('jack')
print c.wtf, Student.wtf, c.name, c.age
print c.update_item('some_item')

Multiple Inheritance: class DerivedClassName(Base1, Base2, Base3):

  • child不可访问parent的private 成员
  • 没有重载(不同参数匹配函数)概念,因为每个函数都是一个class对象
  • super(Child, self);父类引用
    class MaleStudent(Student):
        def update_item(self, item):
            super(MaleStudent, self).update_item(self, item)
            self.    data = data

function

函数是特殊的class

  • 每个def都是一个带call(args...)的class定义
  • function无继承结构,所以加载文件不会执行作用域的代码

var_lam = lambda x,y: some_expression(x,y)

没有显式return,隐式返回None

  • type(arg)

    def func(a, b=2) return

a 入元组args;bkwargs入kwargs

可以返回tuple(多个值)

function args & unpacking (*args, **kwargs)

  • 按需 按序 读必需/非必需参数
  • 包裹传递
    • def func(*name): name as tumple
    • def func(**dict): dict前加**

* ** vs zip

* (tuple/list)unpacking to tuple

** dict unpacking to tuple

zip list/tuple packing to [tuple]

summary

先位置,再关键字,再包裹位置,再包裹关键字,并且根据上面所说的原理细细分辨。

包裹和解包裹并不是相反操作,是两个相对独立的过程。

lambda 匿名函数对象(as data)

var = lambda x: x-expr

reduce(lambda a, b: a * b, xrange(1, 5))

操作函数对象的函数

Python 3.X中,map(),filter(),reduce()的返回值是一个循环对象。可以利用list()函数,将该循环对象转换成表

map

re = map((lambda x,y: x+y),[1,2,3],[6,7,9])

filter

如果函数对象返回的是True,则该次的元素被储存于返回的表中

reduce

reduce()函数在3.0里面不能直接用的,它被定义在了functools包里面,需要引入包

reduce函数的第一个参数也是函数,但有一个要求,就是这个函数自身能接收两个参数。reduce可以累进地将函数作用于各个参数

reduce((lambda x,y: x+y),[1,2,5,7,9]) 相当于(((1+2)+5)+7)+9

skill

  • if name == 'main': pass` prevent code running on module loading
  • def variable_args(args, *kwargs):
  • object_name. # all attributions
  • funcname? modulename?
  • who whos

写法

if condition: some_code

somecode ; some_other_code

code \
code

add sys path

import sys
sys.path.append("../../base/")
import Network #自定义import 空两行

add 自定义的path

import sys
new_path = '/home/emma/user_defined_modules'
if new_path not in sys.path:
    sys.path.append(new_path)

内存对象判断

id(a) == id(b)

path

  • 程序所在的文件夹
  • 标准库的安装路径
  • 操作系统环境变量PYTHONPATH所包含的路径

sys.path # 查看当前的search path;;export PYTHONPATH=$PYTHONPATH:/.../

package

A directory that contains many modules

A special file called init.py (which may be empty) tells Python that the directory is a Python package, from which modules can be imported

查询

  • dir() module.file#查询一个类或者对象所有属性
  • hasattr(obj, attr_name) # attr_name是一个字符串
  • getattr(obj, attr_name)
  • help() some? #查询说明文档

使用obj.class.name来查询对象所属的类/名称;.base查询某个类的父类;module.file 看module文件位置

查询函数的参数 `import inspect print(inspect.getargspec(func))

@ipython>>> %psearch np.diag* 寻找函数 or help xxx

@numpy>>> numpy.lookfor('convolution') or numpy.lookfor('remove', module='os')

脚本与命令行context结合

可以使用下面方法运行一个Python脚本,在脚本运行结束后,直接进入Python命令行。这样做的好处是脚本的对象不会被清空,可以通过命令行直接调用。

$python -i script.py

附录A 常用序列方法

附录B import 查询 进制数

附录C 内置函数清单

附录D 字符串格式化