0%

python-2.0

python2.0

这也是关于python的一些记录,与其他python不矛盾,也不一定相互独立。

1.python+matlab

python和matlab关于.mat数据的交换

1
2
3
4
scipy.io.loadmat(file_name, mdict=None, appendmat=True, **kwargs)
scipy.io.savemat(file_name, mdict, appendmat=True, format='5',
long_field_names=False, do_compression=False, oned_as='row')

2.python与文件IO

主要参考:python cookbook

2.1 文本.txt

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
# t:rt模式下,python在读取文本时会自动把\r\n转换成\n.

# read
# read the entire file as a single string
with open('some.txt', 'rt') as f:
data = f.read()

# read lines
with open('some.txt', 'rt') as f:
for line in f:

#write
with open('some.txt', 'wt') as f:
f.write(text1)

with open('some.txt', 'wt') as f:
print(line1, file=f)

# 换行模式,默认情况下,python会自动识别,或者传入newline,
# newline可以取的值有None, \n, \r, ‘\r\n',用于区分换行符,但是这个参数只对文本模式有效;
with open('some.txt', 'rt', newline='') as f:
pass

# 编码错误问题 errors: replace, ignore
with open('sample.txt', 'rt', encoding='ascii', errors='replace') as f:
pass

2.2 print的分隔符与行尾符

1
2
3
4
5
6
7
# print seq end
print('ACME', 50, seq=',', end='!!\n')
ACME,50!!

row = ('ACME', 50)
print(*row, seq=',', end='!!\n')
ACME,50!!

2.3 二进制数据

1
2
3
4
5
6
7
# 二进制数据,比如图片、声音等

with open('some.bin', 'rb') as f:
data = f.read()

with open('some.bin', 'wb') as f:
f.write(b'hello')

2.4 模拟普通文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 模拟文本文件
import io
s = io.StringIO()
# s = io.StringIO('hello world\n')
s.write('hello world\n')
print('this is a test', file=s)
s.getvalue()
'hello world\nthis is a test'
s.read(4)
s.read()
# 模拟二进制文件
s = io.BytesIO()
s.write(b'binary data')
s.getvalue()
b'binary data'

2.5 压缩文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# gzip,bz2
import gzip
with gzip.open('some.gz', 'rt') as f:
text = f.read()
with gzip.open('some.gz', 'wt') as f:
f.write(text)
-------------------------------------
import bz2
with bz2.open('some.bz2', 'rt') as f:
text = f.read()
with bz2.open('some.bz2', 'wt') as f:
f.write(text)
------------------------------------
from zipfile import ZipFile
with ZipFile(zip_file) as z:
z.extractall(path=save_dir)

2.6 csv

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# csv
# 其实namedtuple继承自OrderedDict有序字典
# read
------
import csv
from collections import namedtuple
with open('stock.csv') as f:
# 第一种:row是列表,访问:row[0]
f_csv = csv.reader(f)
headers = next(f_csv)
for row in f_csv:
pass

# 第二种:命名元组,访问:Row.Symbol
f_csv = csv.reader(f)
headers = next(f_csv)
# headers = [ re.sub('[^a-zA-Z_]', '_', h) for h in next(f_csv) ]
Row = namedtuple('Row', headers)
for r in f_csv:
row = Row(*r)
pass

# 第三种:字典序列,访问:row['Sysbol']
f_csv = csv.DictReader(f)
for row in f_csv:
pass

# write
-------
# 第一种:类表
headers = ['Symbol','Price','Date','Time','Change','Volume']
rows = [('AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800),
('AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500),
('AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000),
]
with open('stock.csv', 'w') as f:
f_csv = csv.writer(f)
f_csv.writerow(headers)
f_csv.writerows(rows)

# 第二种:字典
headers = ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
rows = [{'Symbol':'AA', 'Price':39.48, 'Date':'6/11/2007',
'Time':'9:36am', 'Change':-0.18, 'Volume':181800},
{'Symbol':'AIG', 'Price': 71.38, 'Date':'6/11/2007',
'Time':'9:36am', 'Change':-0.15, 'Volume': 195500},
{'Symbol':'AXP', 'Price': 62.58, 'Date':'6/11/2007',
'Time':'9:36am', 'Change':-0.46, 'Volume': 935000},
]
with open('stocks.csv','w') as f:
f_csv = csv.DictWriter(f, headers)
f_csv.writeheader()
f_csv.writerows(rows)

# 以tab分割
-----
with open('stock.tsv') as f:
f_tsv = csv.reader(f, delimiter='\t')
for row in f_tsv:
pass

# 类型转换
---------
# 第一种:tuple
col_types = [str, float, str, str, float, int]
with open('stocks.csv') as f:
f_csv = csv.reader(f)
headers = next(f_csv)
for row in f_csv:
# Apply conversions to the row items
row = tuple(convert(value) for convert, value in zip(col_types, row))

# 第二种:dict
print('Reading as dicts with type conversion')
field_types = [ ('Price', float),
('Change', float),
('Volume', int) ]
with open('stocks.csv') as f:
for row in csv.DictReader(f):
row.update((key, conversion(row[key]))
for key, conversion in field_types)
print(row)

# 高级操作
--------
# pandas.read_csv()

2.7 json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# json
# write & read
--------------
# 第一种 dict----str
import json
data = {
'name' : 'ACME','shares' : 100,
'price' : 542.23
}
json_str = json.dumps(data)
daa = json.loads(json_str)
# 第二种 dict----file
with open('data.json', 'w') as f:
json.dump(data, f)
with open('data.json', 'r') as f:
data = json.load(f)

3. sys.path

sys.path:动态地改变Python搜索路径

1
2
3
4
5
6
import sys
sys.path.append(’引用模块的地址')

#或者
import sys
sys.path.insert(0, '引用模块的地址')

4. os.path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
os.path.abspath(path) #返回绝对路径
os.path.basename(path) #返回文件名
os.path.exists(path) #路径存在则返回True,路径损坏返回False
os.path.dirname(path) #返回文件路径
os.path.expanduser(path) #把path中包含的"~"和"~user"转换成用户目录
os.path.isabs(path) #判断是否为绝对路径
os.path.isfile(path) #判断路径是否为文件
os.path.isdir(path) #判断路径是否为目录
os.path.join(path1[, path2[, ...]]) #把目录和文件名合成一个路径
os.path.samefile(path1, path2) #判断目录或文件是否相同
os.path.split(path) #把路径分割成dirname和basename,返回一个元组
os.path.splitext(path) #分割路径,返回路径名和文件扩展名的元组
os.path.walk(path, visit, arg)


5. glob.glob

1
2
3
4
5
import glob
listglob = []
listglob = glob.glob(r"/home/xxx/picture/*.png")
listglob.sort()
print(listglob)

6. argparse

参考链接:

不是很适合交互式调试 命令行参数
分为位置参数和选项参数

位置参数

1
2
3
4
5
6
7
8
9
10
import argparse
parser = argparse.ArgumentParser(description="say something about this application !!")
parser.add_argument('name', type=int, help="i can tell you how to set a name argument")

result = parser.parse_args()

print(result.name)

$python main.py taylor
taylor

选项参数

1
2
3
4
5
6
7
8
9
10
import argparse
parser = argparse.ArgumentParser(description="say something about this application !!")
parser.add_argument("-a","--age", help="this is an optional argument")
result = parser.parse_args()
print(result.age)

$python main.py --age 888
888
$python main.py --age=888
888

特殊的选项参数

起着开关的作用:action=”store_true”

1
2
3
4
5
6
7
8
import argparse
parser = argparse.ArgumentParser(description="say something about this application !!")
parser.add_argument("-a", "--age", help="this is an optional argument", action="store_true")
result = parser.parse_args()
print(result.age)

$python main.py -a
True

指定选项:choices=[0, 1, 2]

1
2
3
4
5
6
import argparse
parser = argparse.ArgumentParser(description="say something about this application !!")
parser.add_argument("-a", "--age", help="this is an optional argument", type=int, choices=[0, 1, 2])
result = parser.parse_args()
print(result.age)
1

nargs

  • N (整数) N个命令行参数被保存在一个list中
  • ‘?’ 如果存在该参数且给出了参数值,则从命令行取得该参数,如果存在该参数但未给出参数值,则从const关键字中取得参数值,如果不存在该参数,则将生成默认值。
  • ‘*’命令行参数被保存在一个list中
  • ‘+’命令行参数被保存在一个list中,要求至少要有一个参数,否则报错
  • argparse.REMAINDER 其余的命令行参数保存到一个list中
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
32
33
34
35
36
37
38
39
40
41
42
43
# N
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs=2)
>>> parser.add_argument('bar', nargs=1)
>>> parser.parse_args('c --foo a b'.split())
Namespace(bar=['c'], foo=['a', 'b'])

# ?
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='?', const='c', default='d')
>>> parser.add_argument('bar', nargs='?', default='d')
>>> parser.parse_args('XX --foo YY'.split())
Namespace(bar='XX', foo='YY')
>>> parser.parse_args('XX --foo'.split())
Namespace(bar='XX', foo='c')
>>> parser.parse_args(''.split())
Namespace(bar='d', foo='d')

# *
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='*')
>>> parser.add_argument('--bar', nargs='*')
>>> parser.add_argument('baz', nargs='*')
>>> parser.parse_args('a b --foo x y --bar 1 2'.split())
Namespace(bar=['1', '2'], baz=['a', 'b'], foo=['x', 'y'])

# +
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('foo', nargs='+')
>>> parser.parse_args('a b'.split())
Namespace(foo=['a', 'b'])
>>> parser.parse_args(''.split())
usage: PROG [-h] foo [foo ...]
PROG: error: too few arguments

# argparse.REMAINDER
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')

计数

1
2
parser.add_argument("-v", "--verbosity",
action="count", default=0, help="increase output verbosity")

自定义函数

我本来想实现一个直接list生成tuple的函数,后来才发现是每个str进行转换,所以对list进行了单独处理。

1
2
3
4
5
6
7
8
9
10
11
12
def str2int(v):
print(v, type(v))

parser = argparse.ArgumentParser()
parser.add_argument('--image_size', type=str2int, nargs='+', default=256,
help='image resolution, eg. 256 128')
config = parser.parse_args('--image_size 256 128'.split())
print(config)

256 str
128 str
--image_size ['256', '128']

7. defaultdict

遍历生成字典

1
2
3
4
5
6
7
8
9
10
# 第一种
counts = {}
for k in strings:
counts[k]=counts.setdault(k, 0)+1

# 第二种
from collections import defaultdict
dd = defaultdict(int)
for k in strings:
counts[k]=counts[k]+1

8. shuti

1
2
3
4
5
6
7
8
9
10
11
shutil.copy 复制文件
shutil.copyfile( src, dst) 从源src复制到dst中去。当然前提是目标地址是具备可写权限。抛出的异常信息为IOException. 如果当前的dst已存在的话就会被覆盖掉
shutil.move( src, dst) 移动文件或重命名
shutil.copymode( src, dst) 只是会复制其权限其他的东西是不会被复制的
shutil.copystat( src, dst) 复制权限、最后访问时间、最后修改时间
shutil.copy( src, dst) 复制一个文件到一个文件或一个目录
shutil.copy2( src, dst) 在copy上的基础上再复制文件最后访问时间与修改时间也复制过来了,类似于cp –p的东西
shutil.copy2( src, dst) 如果两个位置的文件系统是一样的话相当于是rename操作,只是改名;如果是不在相同的文件系统的话就是做move操作
shutil.copytree( olddir, newdir, True/Flase)
把olddir拷贝一份newdir,如果第3个参数是True,则复制目录时将保持文件夹下的符号连接,如果第3个参数是False,则将在复制的目录下生成物理副本来替代符号连接
shutil.rmtree( src ) 递归删除一个目录以及目录内的所有内容

9. pickle

1
2
3
pickle
python codebook

注释:序列化对象,将对象obj保存到文件file中去。参数protocol是序列化模式,默认是0(ASCII协议,表示以文本的形式进行序列化),protocol的值还可以是1和2(1和2表示以二进制的形式进行序列化。其中,1是老式的二进制协议;2是新二进制协议)。file表示保存到的类文件对象,file必须有write()接口,file可以是一个以’w’打开的文件或者是一个StringIO对象,也可以是任何可以实现write()接口的对象。

10.重定向

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
32
33
34
35
36
37
38
39
40
41
42
43
44
from __future__ import absolute_import
import os
import sys

class Logger(object):
def __init__(self, fpath=None):
self.console = sys.stdout
self.file = None
if fpath is not None:
mkdir_if_missing(os.path.dirname(fpath))
self.file = open(fpath, 'w')

def __del__(self):
self.close()

def __enter__(self):
pass

def __exit__(self, *args):
self.close()

def write(self, msg):
self.console.write(msg)
if self.file is not None:
self.file.write(msg)

def flush(self):
self.console.flush()
if self.file is not None:
self.file.flush()
os.fsync(self.file.fileno())

def close(self):
self.console.close()
if self.file is not None:
self.file.close()

def mkdir_if_missing(path):
if not os.path.exists(path):
os.makedirs(path)

if __name__ == '__main__':
sys.stdout = Logger(fpath='./log.txt')
print('2222222222')

11. 其他

1
2
# id2labels
trainval_ids2labels = dict(zip(trainval_ids, range(len(trainval_ids))))

12. path

1
2
3
4
5
6
seg_path.mkdir()
args.data_root = Path(args.data_root)
args.img_root = args.data_root / 'images'
args.ann_root = args.data_root / 'annotations'
for ann_path in args.ann_root.iterdir():
ann_path.name.split('_')

13. list dict tuple set

list dict tuple set
索引 支持 不支持 支持 不支持
有无序 有序 无序 有序 无序
+* 支持 支持
append, extend update 不支持 add(item), update(iter)
单个元素删除 不支持 discard, remove, pop,
单个元素修改 支持 支持 不支持
整体删除 支持 clear del del, clear
内置函数 items(), setdefault(k,v),fromkeys() cmp,len,max,tuple
初始化 set(),{}
其他 元素可以为list 不能有可变元素list,dict,set等
其他 拆包
其他
  • tuple一旦创建,增删改都需要以一个整体为单位进行
  • 集合:子集(<, issubset),并集 |, 交集 &,差集 -,对称差 ^

14. 函数嵌套引起的变量引用问题

问题:

1
2
3
4
5
6
7
8
9
10
def fun1():
res = []
count = 0
def fun2():
res.append(1)
print(count)
count += 1
fun2()
fun1()
# res.append(1) print(count) 可以执行,但是count += 1无法执行,会报错

python引用变量的顺序:当前作用域局部变量,外层作用域变量,当前模块中的全局变量,python内置变量。每个变量只能有一种身份。

第一种情况(直接修改全局变量和外层变量 报错)

1
2
3
4
5
6
# 直接修改全局变量 报错
gcount = 0
def global_test():
gcount+=1
print (gcount)
global_test()
1
2
3
4
5
6
7
8
# 直接修改外层变量 报错
def fun1():
gcount = 0
def global_test():
gcount+=1
print (gcount)
global_test()
fun1()

报错原因:可以将python引用变量的顺序记为身份由低到高,并且python允许访问修改有局部变量身份的变量,但是只允许访问更高等级身份的变量。

第二种情况(global修改全局变量 成功,修改外层变量 报错)

1
2
3
4
5
6
7
8
9
# 修改全局变量 成功
# global 修饰后,使函数对全局变量有修改权限。
gcount = 0

def global_test():
global gcount
gcount+=1
print (gcount)
global_test()

或者global可以定义一个还没有出现的变量,而nonlocal不行

1
2
3
4
5
6
7
8
# 成功
# 此时,gcount 是全局变量,且函数对其有修改权限
def global_test():
global gcount
gcount = 1
print (gcount)
global_test()
print(gcount)
1
2
3
4
5
6
7
8
9
10
11
# 修改外层变量 报错
# 此时有两个 gcount,一个全局变量 global gcount,一个外层作用域 gcount.
def fun1():
gcount = 0

def global_test():
global gcount
gcount+=1
print (gcount)
global_test()
fun1()

注意,global 只能在变量第一次声明时使用

其中global声明gcount为全局变量,可以修改

第三种情况(nonlocal修改全局变量 报错,修改外层变量 成功)

1
2
3
4
5
6
7
8
9
10
11
12
# nonlocal修改全局变量 报错
# nonlocal 只用用于修饰外层作用域出现过的变量。
count = 0
def fun1():
def make_counter():
def counter():
nonlocal count
count += 1
print(count)
counter()
make_counter()
fun1()
1
2
3
4
5
6
7
8
9
10
11
12
13
# nonlocal修改外层变量 成功
# 多个外层的都可以访问到,从内而外
def fun1():
count = 0
def make_counter():
count = 1
def counter():
nonlocal count
count += 1
print(count)
counter()
make_counter()
fun1()

或者nonlocal不可以定义一个还没有出现的变量,而global可以

1
2
3
4
5
6
7
8
9
10
11
12
# 报错
def fun1():
def make_counter():
def counter():
nonlocal count
count = 1
print(count)
counter()
print(count)
make_counter()
print(count)
fun1()

nonlocal的特殊用法,应该是属于装饰器那一块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter

def make_counter_test():
mc = make_counter()
print(mc())
print(mc())
print(mc())
make_counter_test()
1
2
3

第四种情况(直接访问 成功)

1
2
3
4
5
# 直接访问全局变量 成功
gcount = 0
def global_test():
print(gcount)
global_test()
1
2
3
4
5
6
7
# 直接访问外层变量 成功
def fun1():
gcount = 0
def global_test():
print(gcount)
global_test()
fun1()

允许访问高级身份的变量

第五种情况

1
2
3
4
5
6
7
8
9
10
11
12
13
# 成功
def add_b():
global b
b = 42
def do_global():
global b
b = b + 10
print(b)
do_global()
print(b)
add_b()
# 52 52
# b都是一个b,全局变量b,并且add_b域和go_global域对其具有访问和修改权
1
2
3
4
5
6
7
8
9
10
11
12
# 报错
def add_b():
global b
b = 42
def do_global():
nonlocal b
b = b + 10
print(b)
do_global()
print(b)
add_b()
# global b之后b是全局变量,add_b 中没有局部变量b,也就是说 do_global 中使用 non_local 进行修饰的时候,外层作用域没有变量b,因此报错

更多函数嵌套的变量访问:https://www.cnblogs.com/z360519549/p/5172020.html

1
2
3
4
5
6
7
8
9
10
11
12
def add_b():
#global b
#b = 42
def do_global():
global b
b = 10
print(b)
do_global()
print(b)
add_b()
print(b)
# 10 10 10
1
2
3
4
5
6
7
8
9
10
11
12
13
def add_b():
#global b
#b = 42
def do_global():
global b
b = 10
print(b)
do_global()
b = b + 20 # 报错
print(b)
add_b()
b = b + 30
print(" b = %s " % b)

https://blog.csdn.net/xcyansun/article/details/79672634找到了新的答案

再回到最原始的问题,为什么res可以,而count不行,因为res是list,res.append()之后不会改变其id(res),但是count+=1会改变id(count)

1
2
3
4
5
6
count = 0
print(id(count))
# 1572891680
count+=1
print(id(count))
# 1572891712

15. iter, next, for , 迭代器,迭代对象

区分迭代器和可迭代对象的原则是:

  • 可迭代对象 Iterable :只有 iter() 方法的对象称为可迭代对象,并且iter方法返回 返回一个迭代器(生成器)。
  • 迭代器 Iterator :具有 iter() 方法和 next() 方法的对象称为迭代器对象。该方法能够自动返回下一个结果,当到达序列结尾时,引发 StopIteration 异常。iter 返回的是它自身 self, next 返回的下一个值,直到结束抛出Stop异常
  • 迭代器是将一个可迭代对象添加了迭代遍历特性后变换而成的对象。
  • iter()方法接受一个可迭代对象,该方法的返回值是一个迭代器(Iterator)
  • for 会自动调用 iter()方法
  • 列表、元组等都是可迭代对象

可迭代对象

1
2
3
4
from collections import Iterable, Iterator

print( isinstance([1,2,3], Iterable)) # True
print( isinstance([1,2,3], Iterator)) # False

16. for xx in iter(object, sentinel)

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
class TestIter(object):

def __init__(self):
self.l=[1,2,3,4]
self.i=iter(self.l)
def __call__(self): #定义了__call__方法的类的实例是可调用的
item = next(self.i)
print ("__call__ is called,which would return",item)
return item
def __iter__(self): #支持迭代协议(即定义有__iter__()函数)
print ("__iter__ is called!!")
return iter(self.l)

t = TestIter() # t是可调用的
t1 = iter(t, 3) # t必须是callable的,否则无法返回callable_iterator
print("#"*10)
print(callable(t))
print("#"*10)
for i in iter(t, 3): # 调用 callable
print("#"*10)
print(i)

# for i in t 等价于 for i in iter(t):
for i in t:
print("#"*10)
print(i)

for i in iter(t):
print("#"*10)
print(i)

17 正则表达式

groups() = [ group(1), group(2)…]
group() = group(0) = 匹配正则表达式整体结果
group(1), group(2) = 第1/2个小括号匹配到的字符串 比如 res = re.match(‘(www).(runoob)’, ‘www.runoob.com’), group(1)=”www”, group(2) = “runoob”

命名组
(?P…),
后面引用 (?P=name):re.match(r’(?i)(?P[\w]+) (?P=pattern)’,s)
全局引用 \g: re.sub(r’(?i)aa(?P[\w]+)’,r’bb\g‘,astr)