Python常用技巧

Python 技巧


文件相关

读取文件

打开文件的话可以先写路径,再写open,open里面可以指定操作,编码等

path='./data.txt'
fb=open(path,encoding='UTF-8')

但是上面这种做法不常用,因为不能保证文件正常关闭,如果发生异常,缓冲区的内容可能不会写入,推荐下面这种方式:
with open(...) as fb:
然后读取文件操作,有四种方式,分别是read,readline,readlines,最后是我常用的for line in fb:
需要注意的是,文件中如果某一行带有换行符,那么肯定会读入换行符,需要我们使用 strip()方法丢弃字符串
read:

调用read()会一次性读取文件全部内容, 速度最快,但当数据过大时不适用。

readline:

使用readline()方法,逐行读取内容,返回结果为list。

with open('/path/to/file', 'r') as f:
    line = f.readline()
    while line:
        line = f.readine()  #这里只能读取一行数据
        ...

像上面这种就是readline的标准写法

readlines():

选择使用readlines()方法,一次性读取文本所有内容,返回结果为list,其中每个元素结尾有"\n"。该方法适合读取配置文件,速度较快,但是文本越大占用内存越大。

这种方法读取的文本内容,每行文本末尾都会带一个’\n’换行符 (可以使用L.rstrip(’\n’)去掉换行符)。注意,python中方法的调用返回的是一个副本,并不会对原有的元素进行修改,如果要修改末尾符号,需要处理赋值给新的字符串。

with open('/path/to/file', 'r') as f:
    line = f.readlines()

for i in line:
    lines.append(i.rstrip('\n'))

最后一种方法是我常用的,感觉是最简洁的写法

with open(...) as fb:
	for line in fb:	#读取文件中的内容
		...

需要注意的是,如果文本文件中一行有回车符,读取进来的字符串始终带有回车符号,我们可以用str的strip操作去除回车符

    line = fb.readline()
    print(type(line))
    print(line)
    print(len(line))
    line=line.strip('\n')
    print(len(line))

输出:
<class 'str'>
戴相龙说中国经济发展为亚洲作出积极贡献		# 这里带有一个换行符
										# 这是print自己的换行符
20										# 带有换行符的长度
19

strip之后回车符就去掉了

strip还有去除文本中指定字符的操作,不过只能左右两边,中间不能去除

文档关于strip的描述:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-exOfPAVm-1584098858349)(G:\MD笔记\Python\Python 技巧.assets\image-20200226100645719.png)]

如果只想处理一边的话,有lstrip和rstrip方法。

另外如果读入进来的文本按照指定符号分割,可以用 split()来按照指定符号来分割字符串,得到的是一个list

line = fb.readline()
print(line)
line=line.split()
print(line)

输出结果:
戴相 龙说中国经济发展为 亚洲作出 积极 贡献

['戴相', '龙说中国经济发展为', '亚洲作出', '积极', '贡献']

文件定位操作

介绍三个函数,一个seek,一个tell

使用seek方法可以很方便的定位当前的文件指针
在这里插入图片描述
一共有两个参数,第一个是是表示偏移量offset,可正可负,第二个参数可选,表示移动的起点,默认值为0,就是文件的初始处
fb.seek(0)可以把文件指针指向第一行,进行重复读取

使用tell方法会返回文件指针当前的位置
在这里插入图片描述
举一个例子:
如果当前有一个特别大的文本文件,不能一次性的读入内存,要求从键盘输入一个行号,然后立刻输出对应行的文本。 由于文件很大,不允许将文件内容全部放到内存中; 同时也不允许从头扫描 文件,得到对应行的文本,因为这样速度太慢

def func():
    pos = 0
    indexes = []
    with open("bigfile.txt") as file:
        while pos < path.getsize("bigfile.txt") - 1:	# getsize返回文件总大小
            indexes.append(pos)							# 增加行号起点
            content = file.readline()					# 读入一行(只是不能一次性读入)
            pos = file.tell()							# 获取当前的文件指针,就是下一行的起始位置
        print(indexes)
        index = eval(input("请输入需要读取的行号(1~%d):" % len(indexes)))
        if type(index) == int and 0 < index <= len(indexes):	#判断一下是否越界
            file.seek(indexes[index - 1])
            content = file.readline()
            print(content.rstrip("\n"))
        else:
            raise ValueError()

写入文件

写入文件我只用write,write接受一个字符串参数,写入到文件中,如fb.write(...)
需要注意的是write不会写入回车符,要自己手动加上


字符串相关

首先要知道str在python中是不可变数据对象,所以不能通过下标去修改值

3.6开始的新特性,字符串前面加一个f

之前很常用format,现在可以用f表达式,更简洁了
看样例

num=10
print(f'num is :{num}')
===result===
num is :10

还可以像原来的format一样加上格式控制

    num=1234
    print(f'num is : {num:>10.2f}')
    ===result===
    num is :    1234.00

逆置str

利用切片可以快速逆置一个str s[::-1]
普通的reversed方法对str并不适用,转不回来 s=str(reversed(s))

如果你非要用的话可以这样''.join(reversed(s))

来自https://stackoverflow.com/questions/931092/reverse-a-string-in-python SO的回答

str转list,int

把字符串的每个元素存放到list中,直接转list即可

s='1234'
L=list(s)
print(L)
['1','2','3','4']

我们常常需要这种操作,将数字的每一位存放到一个list里面,例如: num:1234 => list:[1,2,3,4]
上面这种操作一行代码就能完成,也就是先转换成str , 1234=> ‘1234’ ,再对每一位求值(执行eval),然后得到[1,2,3,4]的map对象,最后手动转成list
list(map(eval,str(num))

字符串数字转int,直接转换即可,这么做的时候要确保str符合int数据规则,比如带有小数点就不行

n=int(s)

int还可指定转换的进制

s='0b1001'
print((int(s,base=2))	#结果是9

另外,python还内置了多个进制转换的函数:

# 获取用户输入十进制数
dec = int(input("输入数字:"))
 
print("十进制数为:", dec)
print("转换为二进制为:", bin(dec))
print("转换为八进制为:", oct(dec))
print("转换为十六进制为:", hex(dec))

搭配int和上面的bin,oct,hex可以实现常见的进制转换

按照规则分隔字符

利用join方法在字符串中每个元素之间插入空格
当然可以自己指定特定的字符

' '.join(s)

将list中的元素转成str

需要用到map函数和repr函数
map不太好解释,repr就是eval的逆操作,即把一串数字变为字符串
在这里插入图片描述
python是不折不扣的强类型程序语言,所以我们插入str的时候要把其它类型的值转成字符串
另外,这种写法是不行的 s2=str(map(repr,L)),s2会指向生成的map对象

    L=[1,2,3,4]
    s2=''.join(map(repr,L))
    print(s2)
    >>>1234

提取文本中的单词

假如我们有一段文本,里面含有多个空格符,逗号,句号等符号,我们需要提取出每一个单词
一种常用的操作是使用re库把其余字符全部转换成’’(假设每个符号后面跟着空格),然后再调用split

import re
re.sub('[,.!-]','',s)
s.split()

一种更好的方法是:
来源: https://www.geeksforgeeks.org/python-extract-words-from-given-string/

# Python3 code to demonstrate 
# to extract words from string 
# using regex( findall() ) 
import re 

# initializing string 
test_string = "Geeksforgeeks, is best @# Computer Science Portal.!!!"

# printing original string 
print ("The original string is : " + test_string) 

# using regex( findall() ) 
# to extract words from string 
res = re.findall(r'\w+', test_string) 

# printing result 
print ("The list of words is : " + str(res)) 

======result======
The original string is : Geeksforgeeks, is best @# Computer Science Portal.!!!
The list of words is : [‘Geeksforgeeks’,is, ‘best’, ‘Computer’, ‘Science’, ‘Portal’]

\w在正则中是匹配任意数字和字母,相当于 [a-zA-Z0-9_],+是匹配1到多次


int相关

取到int的某一位

L=list(str(123))
>>>['1','2','3']

使用map又可以把list中的str转成int,这样就能取到每一位了

int 求和

我们需要求和int的每一位,例如1234 => 10,常用的做法是for循环取得每一位再累加
reduce函数很好的帮我们完成了这种操作

from functools import reduce
print(reduce(lambda x, y: x + y, list(map(eval,str(1234)))))
===result===
10

reduce接受两个参数,第一个是lambda对象,指定执行的操作,第二个是可迭代对象,所以我们需要把1234 转成 [1,2,3,4]来传入


字典

一般用d[i]=d.get(i,0)+1来访问字典

也可以使用

d.setdefault(i,0)
d[i]+=1

我比较喜欢第二种方法

Counter类

文档解释

A Counter is a dict subclass for counting hashable objects. It is an unordered collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. The Counter class is similar to bags or multisets in other languages.

Elements are counted from an iterable or initialized from another mapping (or counter):

在这里插入图片描述
在这里插入图片描述

注意most_common,非常强大,很多情况下我们直接使用Counter能节省很多代码量


排序

复杂排序

sorted在python里面是默认升序的,使用reverse=True来调整成降序,另外也可以设置key成 key = lambda x:-x 来调整成降序
如果排序对象只有一个参数,那么sorted调用结果很明显,如果像[('a',13),('ds',3,),('vdf',4)] 这种涉及到多个参数,那么就会复杂一些

指定参数作为排序依据

如果有多个参数,指定key可以按照某个元素作为排序,例如
按照第二个参数升序排列

    L=[('a',4),('b',3),('a',2)]
    print(sorted(L,key= lambda x:x[1]))
	=====================================
	[('a', 2), ('b', 3), ('a', 4)]

不想写lambda也可以用 itemgetter,效果是一样的

from operator import itemgetter
if __name__ == '__main__':
    L=[('a',4),('b',3),('a',2)]
    print(sorted(L,key= itemgetter(1)))

itemgetter(i)的意思就是获取对象的第i个元素

    get=itemgetter(1)
    print(get([1,2,3]))
	结果是2

如果排序对象是一个object,还可以用attrgetter

attrgetter(*attrs)
返回一个可从操作数中获取 attr 的可调用对象。 如果请求了一个以上的属性,则返回一个属性元组。 属性名称还可包含点号。 例如:
在 f = attrgetter(‘name’) 之后,调用 f(b) 将返回 b.name。
在 f = attrgetter(‘name’, ‘date’) 之后,调用 f(b) 将返回 (b.name, b.date)。
在 f = attrgetter(‘name.first’, ‘name.last’) 之后,调用 f(b) 将返回 (b.name.first, b.name.last)。
来源:https://docs.python.org/zh-cn/3/library/operator.html#operator.attrgetter

文档中的实例
在这里插入图片描述
在这里插入图片描述

指定多个排序条件

如果我们有这样的结构L=[('a',4,2),('b',3,1),('a',2,7)] 需要对第二个参数升序,如果相等,则对第三个参数升序,那么我们可以这样做

    # 1. 
    L = [('a', 4, 2), ('b', 3, 1), ('a', 4, 7)]
    print(sorted(L,key= itemgetter(1,2)))
  	# 2.
	L = [('a', 4, 2), ('b', 3, 1), ('a', 4, 7)]
    print(sorted(L, key=lambda x: (x[1], x[2])))  
    ====
    [('b', 3, 1), ('a', 4, 2), ('a', 4, 7)]

如果是要求相等时第三个元素降序呢?

    L = [('a', 4, 2), ('b', 3, 1), ('a', 4, 7)]
    print(sorted(L, key=lambda x: (x[1], -x[2])))
    ===
    [('b', 3, 1), ('a', 4, 7), ('a', 4, 2)]

在第二个参数前面加上一个符号即可
需要注意的是,如果我们指定reverse,那么reverse是对每个排序条件都起作用的,例如

    L = [('a', 4, 2), ('b', 3, 1), ('a', 4, 7)]
    print(sorted(L, key=lambda x: (x[1], x[2]),reverse=True))
	===
	[('a', 4, 7), ('a', 4, 2), ('b', 3, 1)]

可以看到排列结果中,第二,第三个参数都是降序的形式。如果想要第三个参数升序,那么在x[2]前面加符号即可。
问题来了,如果我们需要比较字符串类型怎么办?
例如这个:我们对第二个参数降序,第三个参数升序,第三个参数是字符串,没办法加负号处理

    L = [('a', 4, 'aa'), ('b', 3, 'ba'), ('a', 4, 'ac')]
    print(sorted(L, key=lambda x: (x[1], -x[2]))

这里有很多种方法,第一种方法就是排序两次,python的排序是保证稳定的,所以我们可以放心的排序

    L = [('a', 4, 'aa'), ('b', 3, 'ba'), ('a', 4, 'ac')]
    t=sorted(L, key=lambda x: x[1])
    print(t)
    t=sorted(t,key=lambda x:x[2],reverse=True)
    print(t)
	===
	[('b', 3, 'ba'), ('a', 4, 'aa'), ('a', 4, 'ac')]
	[('b', 3, 'ba'), ('a', 4, 'ac'), ('a', 4, 'aa')]

可以看到第一遍排序是对x[1]升序,第二次排序是对x[2]降序

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值