python常用用法积累


print

a, b, c隔行打印

isinstance

isinstance(e.reason, socket.timeout)

是在urllib实例看到的

数组

一个数组(不论是字符型还是数值型),另一个元组引用它,更改新的元组后,旧元组也会改变

’xx’.join([‘a’, ‘b’, ‘c’])

1
2
print(’xx'.join(['a', 'b', 'c']))
>>> axxbxxc
1
2
print(*['a', 'b', 'c'])
>>> a b c

[表达式 for r in x]

得到数组

格式化字符串

  • ‘kdjkf%skdk%d’%(‘xxx’, 5)
  • ‘{0}dfsef{1}’.format(4, 5)

time

  • sleep

    1
    2
    3
    def fun(arg):
    print("hello"+ ", %s"%arg)
    time.sleep(2)##

进程和线程

参考

threadpool模块

参考

1
2
3
4
5
6
7
8
9
10
11
12
13
import threadpool
import time

li = ['wangming', 'lifang', 'zhoujie']
def fun(arg):
print("hello"+ ", %s"%arg)
time.sleep(2)
sta_time = time.time()
pool = threadpool.ThreadPool(10)
requests = threadpool.makeRequests(fun, li)
[pool.putRequest(req) for req in requests]
pool.wait()
print("total time is :%d"%(time.time()-sta_time))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def hello(m, n, o):
""""""
print("m = %s, n = %s, o = %s" % (m, n, o))


if __name__ == '__main__':
# 方法1
lst_vars_1 = ['1', '2', '3']
lst_vars_2 = ['4', '5', '6']
func_var = [(lst_vars_1, None), (lst_vars_2, None)]
# # 方法2
# dict_vars_1 = {'m': '1', 'n': '2', 'o': '3'}
# dict_vars_2 = {'m': '4', 'n': '5', 'o': '6'}
# func_var = [(None, dict_vars_1), (None, dict_vars_2)]

pool = threadpool.ThreadPool(2)
requests = threadpool.makeRequests(hello, func_var)
[pool.putRequest(req) for req in requests]
pool.wait()

Tf7UsJ.png

multiprocessing模块

process

适合少量进程

pool

适合大量进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import os, time, random
from multiprocessing import Pool

def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end - start)))

if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(8)
for i in range(9):
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')

T58Run.png

subprocess模块

url

适用于子进程是外部程序

threading模块

1
2
3
4
5
6
7
8
9
10
11
def thread_job():
print("This is an added thread, number is %s"% threading.current_thread())
def main():

print(threading.active_count()) // 已有线程个数
print(threading.enumerate()) // 显示已有线程
print(threading.current_thread()) // 正在执行的线程
added_thread = threading.Thread(target=thread_job) // 添加子线程
added_thread.start()
if __name__ == '__main__':
main()

T5dyXF.png

join()

用来控制主线程后续任务,在子进程执行完毕后再执行

1
2
3
4
5
6
7
8
9
10
11
12
13
def thread_job():
print("T1 start\n")
for i in range(10):
time.sleep(0.1)
print("T1 finish\n")
def main():
added_thread = threading.Thread(target=thread_job, name='T1')
added_thread.start()
added_thread.join() // 不加这句,会先执行all done,再t1 finish
print('all done\n')

if __name__ == '__main__':
main()

T501sS.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def thread_job():
print("T1 start\n")
for i in range(10):
time.sleep(0.1)
print("T1 finish\n")
def T2_job():
print("T2 start\n")
print("T2 finish\n")
def main():
added_thread = threading.Thread(target=thread_job, name='T1')
T2_thread = threading.Thread(target=T2_job, name='T2')
added_thread.start()
T2_thread.start()
added_thread.join()
print('all done\n')

if __name__ == '__main__':
main()

random

random

1
2
import random
random.random() >>> 生成01的小数

range

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def thread_job():
print("T1 start\n")
for i in range(10):
time.sleep(0.1)
print("T1 finish\n")
def T2_job():
print("T2 start\n")
print("T2 finish\n")
def main():
added_thread = threading.Thread(target=thread_job, name='T1')
T2_thread = threading.Thread(target=T2_job, name='T2')
added_thread.start()
T2_thread.start()
added_thread.join()
print('all done\n')

if __name__ == '__main__':
main()
1
2
3
li = [xxxxx]
for i in range(l, len(li), step=5):
a = li[i:i+5]

generator

1
2
1.python yield生成的generator不可以用下标取
2.一旦迭代了,就没了,长度变为零
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
b = 0
def fun():
a = "no"
if a == 'no':
b = 1
print(b)
for i in range(1, 16):
yield i


f = fun()
for i in f:
print(i)


1 真正去迭代时,才执行的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Generator长度的获取

1
2
3
4
5
len(list(gen))

sum(1 for _ in gen)

# 这些方法一旦迭代,此generator就没用了

参考文档

Generator复制

1
2
3
import itertools
generator1, generator2 = itertools.tee(generator,2)
此时不能再用最初的generator,否则会导致后两个不能用

参考链接

yield

1
2
3
yield不能与return一起用;与if一起用也有问题,直接不进入if(不管if是在生成generator的循环里,还是在函数里的任何位置,都直接不执行)

http://www.py.cn/jishu/jichu/27217.html

cursor

1
2
1.mongodb的find方法生成的cursor可以用下标或去,也可以用下标截取
2.如果要多次获取值,可以提前用clone()方法克隆

list_iterator

1
在使用Beautiful soup进行网页解析时,用find_all查找产生的iterator不是subscriptable

hasattr, setattr, getattr

hasattr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
hasattr(object, name)
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False

>>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> hasattr(t, "name") #判断对象有name属性
True
>>> hasattr(t, "run") #判断对象有run方法
True
>>>

setattr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
给对象的属性赋值,若属性不存在,先创建再赋值

>>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> hasattr(t, "age") #判断属性是否存在
False
>>> setattr(t, "age", "18") #为属相赋值,并没有返回值
>>> hasattr(t, "age") #属性存在了
True
>>>

getattr

1
2
3
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> getattr(t, "name") #获取name属性,存在就打印出来。
'xiaohua'
>>> getattr(t, "run") #获取run方法,存在就打印出方法的内存地址。
<bound method test.run of <__main__.test instance at 0x0269C878>>
>>> getattr(t, "run")() #获取run方法,后面加括号可以将这个方法运行。
'HelloWord'
>>> getattr(t, "age") #获取一个不存在的属性。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: test instance has no attribute 'age'
>>> getattr(t, "age","18") #若属性不存在,返回一个默认值。
'18'
>>>

综合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
一种综合的用法是:判断一个对象的属性是否存在,若不存在就添加该属性。

>>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> getattr(t, "age") #age属性不存在
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: test instance has no attribute 'age'
>>> getattr(t, "age", setattr(t, "age", "18")) #age属性不存在时,设置该属性
'18'
>>> getattr(t, "age") #可检测设置成功
'18'

Flask库

参考链接

官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.
from flask import Flask,g

app = Flask(__name__,static_url_path='/xx')

@app.before_request
def f1():
g.x1 = 123

@app.route('/index')
def index():
print(g.x1)
return 'hello world'

if __name__ == '__main__':
app.run()
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
2.
from flask import Flask,g,request,render_template
from utils import login_log,login_ip

app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World!'


@app.route('/login/',methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
username = request.form.get('username')
password = request.form.get('password')

     # 使用g对象
g.username = username
g.ip = password
login_log()
login_ip()
return '恭喜登录成功!'

if __name__ == '__main__':
app.run()

钩子函数

1
2
3
4
5
6
7
8
9
10
11
12
13
钩子的理解:

在程序正常运行的时候,程序按照A函数—->B函数的顺序依次运行;钩子函数可以插入到A函数到B函数运行中间从而,程序运行顺序变成了A—->钩子函数—->B函数。

Flask项目中有两个上下文,一个是应用上下文(app),另外一个是请求上下文(request)。请求上下文request和应用上下文current_app都是一个全局变量。所有请求都共享的。Flask有特殊的机制可以保证每次请求的数据都是隔离的,即A请求所产生的数据不会影响到B请求。所以可以直接导入request对象,也不会被一些脏数据影响了,并且不需要在每个函数中使用request的时候传入request对象。这两个上下文具体的实现方式和原理可以没必要详细了解。只要了解这两个上下文的四个属性就可以了:

1)request:请求上下文上的对象。这个对象一般用来保存一些请求的变量。比如method、args、form等。

2)session:请求上下文上的对象。这个对象一般用来保存一些会话信息。

3)current_app:返回当前的app。

4)g:应用上下文上的对象。处理请求时用作临时存储的对象

常用的钩子函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
before_first_request:处理第一次请求之前执行。

@app.before_first_request
def first_request():
print 'first time request'

before_request:在每次请求之前执行。通常可以用这个装饰器来给视图函数增加一些变量。

@app.before_request
def before_request():
if not hasattr(g,'user'):
setattr(g,'user','xxxx')

teardown_appcontext:不管是否有异常,注册的函数都会在每次请求之后执行。

@app.teardown_appcontext
def teardown(exc=None):
if exc is None:
db.session.commit()
else:
db.session.rollback()
db.session.remove()

random.randint

1
randint(a, b) # 返回整数包含a, b

random.choice

1
random.choice([xxxx])  # 随机从列表中选择一个

list[a:b]

1
index为b的取不到

datetime

1
2
3
4
5
6
7
8
9
import datetime

threeDayAgo = datetime.datetime.today() - datetime.timedelta(3)
print(threeDayAgo)
otherStyleTime = threeDayAgo.strftime("%Y-%m-%d %H:%M:%S")
print(otherStyleTime)

2022-03-07 15:40:17.218960
2022-03-07 15:40:17
1
2
3
(date.today() + timedelta(days=-i)).strftime("%Y-%m-%d")

2022-03-08

时间戳

当前时间

1
2
3
1.now = datetime.datetime.now()

2.t = time.time()

指定日期

1
2
3
4
5
1.datetime.datetime.strptime(t, '%Y%m%d')

2.int(time.mktime(time.strptime(t,"%Y%m%d")))

t的时间格式要
1
2
3
4
# 获取时间戳;2022-03-08
def secondsTime(self, t):
d = datetime.strptime(t, "%Y-%m-%d")
return time.mktime(d.timetuple())

时间戳转化为固定格式时间

1
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(1648803511))

re正则表达式

1
2
3
4
1.去除字符串中非数字字符
re.sub('\D', '', 'a10b打') # \D代表非数字,\d代表数字

re.sub('\D', '-', '2022年3月10')

类方法,普通方法,静态方法,类属性,实例属性

1
2
实例可以调用 类方法,普通方法,静态方法
类可以调用 类方法,静态方法
1
2
3
4
5
实例方法(普通方法)——————————————————————随着实例属性的改变而改变

类方法(无论是类调用还是实例调用)———————————————都是类属性的值,不随实例属性的变化而变化

静态方法————————————————————————————不可以访问类属性,故直接输出传入方法的值
1
2
3
4
5
6
类属性:实例也可以访问类属性,但类不能访问实例属性
实例属性:(def _init_(self):下带self的变量)

当类属性和实例属性名字相同时,通过实例访问属性是访问的实例属性,当del 实例.属性时,再访问的是类属性

实例属性和类属性尽量不要取相同名字
1
2
3
4
5
实例属性属于各个实例所有,互不干扰;

类属性属于类所有,所有实例共享一个属性;

不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。
1
2
3
4
5
6
7
8
9
10
class o:
i = 1
def __init__(self):
self.i += 2


if __name__ == '__main__':
for i in range(20):
a = o()
print(a.i, o.i)

参考

参考

私有属性

1
2
3
self.__name = 'xxxx'

此为私有属性,通过'实例.xxx'不能访问;当创建相应的方法可以操作(使用主要的一个功能是可以检测参数)

参考

b””和f””和r””

1
2
3
4
5
6
7
8
9
1.f" "
import time
t0 = time.time()
time.sleep(1)
name = 'processing'
# 以 f开头表示在字符串内支持大括号内的python 表达式
print(f'{name} done in {time.time() - t0:.2f} s')

>>> processing done in 1.00 s
1
2
3
4
2.r"" 的作用是去除转义字符.

即如果是“\n”那么表示一个反斜杠字符,一个字母n,而不是表示换行了。
以r开头的字符,常用于正则表达式,对应着re模块
1
2
3
4
5
3.
b" "前缀表示:后面字符串是bytes 类型
在 Python3 中,bytes 和 str 的互相转换方式是
str.encode('utf-8')
bytes.decode('utf-8')

将列表所有元素整合成字符串

1
2
l = [xxxxx]
''.

邮件功能

发邮件

qq

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
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication


class SendEmail:
def email(self,body, attach):
# 发送邮箱
sender = '2364076207@qq.com'
# 接收邮箱
receivers = '2364076207@qq.com'

msg = MIMEMultipart()
#邮箱的主题
msg['Subject'] = 'BiliBili爬取报告'
msg['From'] = sender
msg['To'] = receivers

content = MIMEText(body,'html','utf-8')
msg.attach(content)
#添加附件,并命名
attachment = MIMEApplication(open(attach, 'rb').read())
attachment.add_header('Content-Disposition', 'attachment', filename='qr_code.png')
msg.attach(attachment)

try:
#连接邮箱的服务器及端口号,以163邮箱为例
smtpObj = smtplib.SMTP_SSL('smtp.qq.com','465')
#登录邮箱:用户名及密码
smtpObj.login(user='2364076207@qq.com', password='yxcupvssuhibdjab')
smtpObj.sendmail(sender, receivers, str(msg))
smtpObj.quit()
print("邮件发送成功")
except smtplib.SMTPException:
print("Error: 无法发送邮件")


if __name__ == '__main__':
#以同一目录中的report.html为例
with open(r"C:\Users\Ty\Desktop\jd_maotai\aa.txt",'r',encoding="utf-8") as file:
body=file.read()
#以同一目录中的report.rar为例添加附件
#SendEmail().email('aaaads',r"C:\Users\Ty\Desktop\jd_maotai\qr_code.png")

163

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
# coding: utf-8

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.header import Header

# 设置smtplib所需的参数
# 下面的发件人,收件人是用于邮件传输的。
smtpserver = 'smtp.163.com'
username = 'email18315138179@163.com'
password = 'YIHELTPKQMKUZHUN'
sender = 'email18315138179@163.com'
# receiver='XXX@126.com'
# 收件人为多个收件人
receiver = ['email18315138179@163.com']

subject = 'Python email test'
# 通过Header对象编码的文本,包含utf-8编码信息和Base64编码信息。以下中文名测试ok
# subject = '中文标题'
# subject=Header(subject, 'utf-8').encode()

# 构造邮件对象MIMEMultipart对象
# 下面的主题,发件人,收件人,日期是显示在邮件页面上的。
msg = MIMEMultipart('mixed')
msg['Subject'] = subject
msg['From'] = 'email18315138179@163.com <email18315138179@163.com>'
# msg['To'] = 'XXX@126.com'
# 收件人为多个收件人,通过join将列表转换为以;为间隔的字符串
msg['To'] = ";".join(receiver)
# msg['Date']='2012-3-16'

# 构造文字内容
text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.baidu.com"
text_plain = MIMEText(text, 'plain', 'utf-8')
msg.attach(text_plain)

# 构造图片链接
sendimagefile = open(r'C:\Users\Ty\Desktop\jd_maotai\qr_code.png', 'rb').read()
image = MIMEImage(sendimagefile)
image.add_header('Content-ID', '<image1>')
image["Content-Disposition"] = 'attachment; filename="qr_code.png"'
msg.attach(image)

# 构造附件
sendfile = open(r'C:\Users\Ty\Desktop\jd_maotai\qr_code.png', 'rb').read()
text_att = MIMEText(sendfile, 'base64', 'utf-8')
text_att["Content-Type"] = 'application/octet-stream'

# 以下中文测试不ok
# text_att["Content-Disposition"] = u'attachment; filename="中文附件.txt"'.decode('utf-8')
msg.attach(text_att)

# 发送邮件
smtp = smtplib.SMTP()
smtp.connect('smtp.163.com')
# 我们用set_debuglevel(1)就可以打印出和SMTP服务器交互的所有信息。
# smtp.set_debuglevel(1)
smtp.login(username, password)
smtp.sendmail(sender, receiver, msg.as_string())
smtp.quit()

读取邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
~~~

[参考链接](https://blog.csdn.net/weixin_33694172/article/details/89753224)

[参考链接](https://www.jb51.net/article/193104.htm)

## 字典

### 读取键和值

[参考链接](http://www.zzvips.com/article/178042.html)

## 位置参数、默认参数、可变参数、关键字参数、命名关键字参数

[参考链接](https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888)

~~~python
位置参数:传参可以不用按顺序传
默认参数:对于不常用的参数使用默认值,降低函数调用的复杂度
1
2
3
4
5
6
7
8
可变参数:*args
def fun(*args):
for arg in args:
pass
函数内接收到的是一个tuple
fun(1,2,3)
如果要传入一个list或tuple,可以在前加*
fun(*[1,2,3])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
关键字参数:**kwargs
会把传入的参数组装成字典
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)

>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

和可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
命名关键字参数:
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:

def person(name, age, *, city, job):
print(name, age, city, job)

和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。

调用方式如下:

>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

def person(name, age, *args, city, job):
print(name, age, args, city, job)
命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:

>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'

查看实例的属性和方法

1
dir(0b)

不见黄河心不死,不撞南墙头不回。

本文标题:python常用用法积累

文章作者:TTYONG

发布时间:2020年04月05日 - 09:04

最后更新:2022年04月23日 - 20:04

原始链接:http://tianyong.fun/python%E7%94%A8%E6%B3%95%E7%A7%AF%E7%B4%AF.html

许可协议: 转载请保留原文链接及作者。

多少都是爱
0%