晒晒我家小院子

0%

1
修改不可变数据会抛出TypeError异常
1
print 方法默认调用 sys.stdout.write 方法
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
# 文件路径操作
def print_directory_contents(abs_path):
"""
:param abs_path: 文件夹绝对地址
:return: 该文件夹中文件路径+包含的文件夹的文件路径
"""
import os
for child_path in os.listdir(abs_path):
abs_child_path = os.path.join(abs_path, child_path)
if os.path.isdir(abs_child_path):
print_directory_contents(abs_child_path)
else:
print(abs_child_path)
'''
os.remove()删除文件
os.rename()重命名文件
os.walk()生成目录树下的所有文件名
os.chdir()改变目录
os.mkdir/makedirs 创建目录/多层目录
os.rmdir/removedirs 删除目录/多层目录
os.listdir()列出指定目录的文件
os.getcwd()取得当前工作目录
os.chmod()改变目录权限
os.path.basename()去掉目录路径,返回文件名
os.path.dirname()去掉文件名,返回目录路径
os.path.join()将分离的各部分组合成一个路径名
os.path.split()返回(dirname(),basename())元组
os.path.splitext()(返回 filename,extension)元组
os.path.getatime\ctime\mtime 分别返回最近访问、创建、修改时间
os.path.getsize()返回文件大小
os.path.exists()是否存在
os.path.isabs()是否为绝对路径
os.path.isdir()是否为目录
os.path.isfile()是否为文件
'''
1
2
3
4
# 拷贝
import copy
copy.deepcopy(a) # 深拷贝
# '原子'类型的对象拷贝,都是返回引用,不是新创建
1
2
3
4
5
6
7
8
# random模块
import random
random.random() # [0,1) float
random.uniform(a, b) # [a,b] float
random.randint(a, b) # [a,b] int
random.randrange(a, b, step) # [a,b) step为步长,随机一个数字
random.choice(sequence) # list中随机一个元素
random.shuffle(alist) # 打乱顺序,无返回值
1
2
3
4
# datetime
import datetime
date1 = datetime.date(year=int(100),month=int(2),day=int(22))
print((date1-date1).days + 1)
1
2
3
4
5
6
7
8
9
# sys模块
sys.path 主要是对 Python 解释器的系统环境参数的操作(动态的改变 Python 解释器搜索路径)
sys.argv 命令行参数 List,第一个元素是程序本身代码(即此.py程序)# 有时候带路径
sys.exit(n) 退出程序,正常退出时 exit(0)
sys.maxint 最大的 Int 值
sys.maxunicode 最大的 Unicode 值
sys.stdout 标准输出
sys.stdin 标准输入
sys.stderr 错误输出
1
2
3
4
5
# Python 是强语言类型还是弱语言类型?
Python 是强类型的动态脚本语言。 # 强类型
强类型:不允许不同类型相加。
动态:不使用显示数据类型声明,且确定一个变量的类型是在第一次给它赋值的时候。
脚本语言:一般也是解释型语言,运行代码只需要一个解释器,不需要编译。

Python自省 (introspection)

1
2
3
# PEP8 规范
# 模块和包:除特殊模块 __init__ 之外,模块名称都使用不带下划线的小写字母。若是它们实现一个协议,那么通常使用lib为后缀
# 使用 has 或 is 前缀命名布尔元素 is_connect = True has_member = False
1
2
3
# 性能分析
import cProfile
cProfile.run('func(agrs)') # 字符串

Git常用命令

查看不同

1
git diff

回退

1
2
git reset --hard HEAD^ 
# HEAD 表示当前版本,^和^^, 或者直接是版本id号
1
2
git reset --hard 1094a
# git reset --hard commit_id

查看日志

1
2
3
git log [--pretty=oneline]
# git log --graph命令可以看到分支合并图
git log --graph --pretty=oneline --abbrev-commit

查看历史命令

1
git reflog

查看工作区和版本库里面最新版本的区别

1
git diff HEAD -- readme.txt

丢弃修改

1
2
3
git checkout -- readme.txt
# git checkout -- file
# 只能丢弃未add的
1
2
3
# 如果已经add了,则需要使用git reset HEAD <file>命令,再调用git checkout -- readme.txt
git reset HEAD readme.txt # 撤销add的文件
git checkout -- readme.txt

删除文件

1
2
3
4
5
# 先删除文件,再使用命令删除版本库里面的文件,并且再commit
git rm test.txt
git commit -m "remove test.txt"
# 如果误删则git checkout -- test.txt还原
git checkout -- test.txt

关联仓库

1
2
3
4
git remote add origin "url"
# 把本地库的所有内容推送到远程库上
git push -u origin master
# 由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

推送代码

1
2
git push origin master
# master 是仓库

创建分支

1
2
3
4
# 创建+切换分支
git checkout -b dev
# 创建分支
git branch <name>

切换分支

1
git checkout <name>

查看当前分支

1
2
# 会列出所有分支,当前分支前面会标一个*号
git branch

合并分支

1
2
3
4
# 分支走在了主分支前面,并没有变成两个不同分支
git merge dev
# Fast-forward "快进模式"
# 切换回主分支,再合并(重点理解为什么)

删除分支

1
2
git branch -d dev # 和查看当前分支相同
git branch -D feature-vulcan # 强制删除未合并的分支

禁用Fast-forward :”快进模式”

1
2
git merge --no-ff -m "merge with no-ff" dev
# 因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

保存现场

1
2
3
4
5
6
7
8
9
git stash
# 查看保存的现场
git stash list
# 恢复现场方法一
git stash apply
git stash drop
git stash apply stash@{0} # 好像没什么区别
# 恢复现场方法二
git stash pop # 常用

查看远程库信息

1
2
git remote [-v]
# 加上-v,信息更详细

分支推送原则

  • master分支是主分支,因此要时刻与远程同步;
  • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
  • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
  • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

拷贝远程分支到本地(远程合作常用)

1
2
3
4
5
git checkout -b dev origin/dev
# 设置dev和origin/dev的链接
git branch --set-upstream-to=origin/dev dev
# git branch --set-upstream-to <branch-name> origin/<branch-name>
git pull # 下载更新

特殊命令(多人合作)

1
2
3
git rebase
# rebase操作可以把本地未push的分叉提交历史整理成直线;
# rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

创建标签

1
2
git tag v1.0
# git tag <name>

对commit打标签

1
git tag v0.9 f52c633  # id号

查看标签

1
2
3
4
5
6
7
8
git tag # 查看标签
git show v0.9 # git show <tagname>查看标签信息
# 注意,标签不是按时间顺序列出,而是按字母排序的。

git tag -a v0.1 -m "version 0.1 released" 1094adb
# 还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字

# 标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签

标签操作

1
2
3
4
5
6
7
8
9
10
# 删除标签
git tag -d v0.1 # 命令git tag -d <tagname>可以删除一个本地标签;
# git push origin <tagname> 推送标签到远程库
git push origin v1.0 # 某一个
git push origin --tags # 所有标签

# 如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除
git tag -d v0.9
git push origin :refs/tags/v0.9
# 命令git push origin :refs/tags/<tagname>可以删除一个远程标签。

技巧

1
2
3
# .gitignore文件(不想被git提示的,文件名写入其中即可)
git check-ignore # 查找错误规则
git add -f App.class # 强制添加
1
2
3
4
5
# 别名
git config --global alias.st status # git status改为git st (即status改为st)
# 丧心病狂
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 配置文件cat .git/config ,直接修改[alias]即可还原

1.位置参数

1
2
def power(x):
return x*x

2.默认参数

1
2
3
4
5
def power(x=1):
return x*x
# 必选参数在前,默认参数在后
# 变化大的参数在前,变化小的参数在后
# 变化小的参数可以作为默认参数

3.可变参数

1
2
3
4
5
6
7
def cale(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum

cale(1,2,3)

4.关键字参数

1
2
3
4
5
def person(name, age, **kw)
print('name:',name,'age:',age,'other',kw)
person('Tom', 30)
person('Tom', 30, city='beijing')
person('Tom', 30, **dict1)

5.命名关键字参数

1
2
3
4
5
6
def person(name,age,*,city,job):
# 没有可变参数时
pass
def person1(name,age,*args,city='beijing',job):
# 有可变参数时,不再需要特殊分隔符*
pass

参数组合

1
顺序:必选参数(位置参数),默认参数,可变参数,关键字参数,命名关键字参数

备注

1
2
func(*args,**kw)
对于任意函数,都可以通过类似func(*args,**kw)的形式调用它,无论它的参数是如何定义的。

4G 内存怎么读取一个 5G 的数据?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 方法一:
# 生成器,分多次读取
def my_read(file, separator): # 流对象,分隔符
buffer = ""
while True:
while separator in buffer: # 此处while比if更合适, 处理buffer有多个separator
pos = buffer.index(separator) # 获取第一个下标
yield separator[:pos]
buffer = buffer[pos + len(separator):]
chunk = file.read(2000) # 太小也会降低效率
if not chunk:
yield buffer
break
buffer = buffer + chunk

with open('f.txt', 'r') as f:
for line in my_read(f, separator='\n'):
print(line)
1
2
3
4
# 方法二:
# linux命令split切割成小文件
split -l 300 big.txt -d -a 4 big_ # 系数不是字母而是数字(-d),后缀系数为四位数(-a 4)
split -b 10m big.txt big_ # 按照大小切割

使用python发送邮件

发送邮件,带附件

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
import os
import smtplib
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase


def send_email():
# 邮件一般是由标题,发信人,收件人,邮件内容,附件等构成
msg = MIMEMultipart()
msg['From'] = Header('Worker<1837@qq.com>') # 发件人
msg['To'] = Header('Administrators<17859@163.com>') # 收件人
msg['Subject'] = Header('Work in 2020.', 'utf-8').encode() # 标题
msg.attach(MIMEText('hello, work completed.', 'plain', 'utf-8')) # 内容

zip_path = os.path.join(os.path.abspath('.'), 'test.zip')
with open(zip_path, 'rb') as f:
mime = MIMEBase('zip', 'zip', filename=zip_path)
# 加上必要的头信息:
mime.add_header('Content-Disposition', 'attachment', filename=('utf8', '', 'test1.zip'))
mime.add_header('Content-ID', '<0>')
mime.add_header('X-Attachment-Id', '0')
# 把附件的内容读进来:
mime.set_payload(f.read())
encoders.encode_base64(mime)
msg.attach(mime)

server = smtplib.SMTP("smtp.qq.com", 25)
server.starttls() # 加密
server.login("196@qq.com", "gphf") # 授权码
server.sendmail("186@qq.com", ["17@163.com", ], msg.as_string())
server.quit()


if __name__ == '__main__':
send_email()