Python---编程语言基础

目录
1. 零散概念
2. 数据类型
3. 控制流语句
4. 常用功能
4.1 正则表达式
4.2 读写文件
4.3 调试
4.4 处理 HTML
4.5 处理 Excel
4.6 处理 PDF
4.7 处理 Word
4.8 处理 CSV 简化表格
4.9 处理 JSON
4.10 时间、计时器、多线程
4.11 处理 邮件
4.12 处理 短信
4.13 处理 图片
4.14 GUI 自动化(控制键盘和鼠标)

交互式环境
mac 打开终端输入idle回车,出现python终端,回车出现>>>
可输入2+2回车输出4
文件编辑窗口
File | New File 新建python文件
File | Save As 保存文件
编辑文件
cmd+S保存
Run | Run Module 运行文件
File | Open 打开刚才的文件

例:
#注释
print('hello world!')
x='a';
print('hello'+x)
print(len(x))
x=input()
print(str(int(x)+10)+'ss')

1. 零散概念
导入其他文件
形式1(推荐)
import random, sys, os, math,copy,pprint,pyperclip
print(random.randint(1, 10))
sys.exit() 结束程序
arr2=copy.copy(arr) 复制一份
copy.deepcopy() 列表中含有列表时使用
pprint.pprint(dic) 漂亮打印
pyperclip.copy('Hello world!') 粘贴
pyperclip.paste() 拷贝

形式2(可以不用前缀)
from random import *
print(randint(1, 10))

表达式
值和操作符的组合

函数
def hello():
print('Howdy!')
hello()

def hello(name):
print('Hello ' + name)
return 'hello'
x=hello('Bob')

异常处理
try:
return 42 / 0 except ZeroDivisionError:

try:
3/1
42/0
except ZeroDivisionError:


作用域
局部作用域
函数内赋值的变量
全局作用域
在所有函数之外赋值的变量

global(用于函数内修改全局变量)
def spam():
global eggs
eggs = 'spam'
eggs = 'global'
spam()
print(eggs)

注释
# 注释

常用函数
打印函数
print('hello')
print() 打印空行
print('Hello', end='') 不换行(用空字符串替换回车)
print('cats', 'dogs', 'mice') cats dogs mice
print('cats', 'dogs', 'mice', sep=',') 以空格隔开

获取输入函数
x=input()

获取字符串长度函数
x=len('hello')

整型/浮点型 转字符串函数
str=str(3)
str=str(3.2)

字符串/浮点型 转整型数字函数
x=int('3')
x=int(3.3)

整型/字符串 转浮点型函数
f=float(3)
f=float('3.2')

变量
变量用来保存值:
x=3
str='hello'
f=5.0

变量名的命名规则:
1.只能是一个词。
2.只能包含字母、数字和下划线。
3.不能以数字开头。

区分大小写
见名知意
驼峰式

方法
支持链式调用

各种数据类型都有内置的方法

操作符
比较操作符 (结果为布尔类型)
== 等于
!= 不等于
< 小于
> 大于
<= 小于等于
>= 大于等于

'hello'=='hello' 返回True
42=='42' 返回False
'hello'!='ss' 返回True
<、>、<=和>=操作符仅用于数字

布尔操作符

and
or
not

计算操作符(优先级从高到低)
** 指数 2**3 8
% 取模/取余数 22 % 8 6
// 整除/商数取整 22 // 8 2
/ 除法 22/8 2.75
* 乘法 3*5 15
- 减法 5-2 3
+ 加法 2+2 4

赋值操作符
=
+=
-=
*=
/=
%=

2.数据类型
整型 -2, 0,1

浮点型 -1.25, 1.0,

字符串 'aa' "aa" "aa'a'aa"
str='hello'
str[0]
str[-1]
str[1:2]
str[1:]
str[:3]
'h' in str
'x' not in str
for i in str:
不同于列表,字符串是“不可变的”
str2=str[0:1] + 'the' + str[1:2]

转义字符
\' 单引号
\" 双引号
\t 制表符
\n 换行符
\\ 倒斜杠
原始字符串(原样输出)
r"xxx\nxxx"
多行字符串(不需要转义)
str='''sss'ss
sss'''
多行注释
"""这是注释
这是注释
"""

方法
并没有改变原字符串
str2=str.upper() 转大写
str2=str.lower() 转小写
str2=str.isupper() 是否全大写
str2=str.islower() 是否全小写
is=str.isalpha() 是否只包含字母,并且非空
is=str.isalnum() 是否只包含字母和数字,并且非空;
is=str.isdecimal() 是否只包含数字字符,并且非空;
is=str.isspace() 是否只包含空格、制表符和换行,并且非空
is=str.istitle() 仅包含以大写字母开头、后面都是小写字母
is=str.startswith('xx') 是否以xx开头
is=str.endswith('xx') 是否以xx结尾
str=','.join(['s','b']) 列表拼接字符串
arr="xx,xx".split(',') 字符串分割为列表(默认空格)
'Hello'.ljust(10) 左对齐,长度为10
'Hello'.rjust(10) 右对齐,长度为10
'Hello'.center(20) 中心对齐,长度为10
'Hello'.ljust(20, '-') 左对齐,长度为10,空余部分填入-
'Hello'.rjust(20, '-') 右对齐,长度为10,空余部分填入-
'Hello'.center(20, '-') 中心对齐,长度为10,空余部分填入-
str.strip() 去除两边的空白字符(空格、制表符和换行)
str.lstrip() 去除左边的空白字符
str.rstrip() 去除右边的空白字符
str.strip('sbX') 去除两边(直到碰到不同单词)的s、b、X字符
粘贴复制(需导入pyperclip)
pyperclip.copy('Hello world!')
pyperclip.paste()

布尔型 True、False2种

NoneType None唯一值

列表
arr=['cat', True, None, 3.1415]
arr[0]第一个 arr[-1]最后一个 arr[0:4]0~3 arr[0:]所有 arr[:2]0~1 arr[:]所有
len(arr) 数组的长度
arr[0]='hello' 修改
['h','e']+['l','l'] 拼接
['h','e']*2 复制
del arr[0] 删除
arr=arr+['world'] 追加元素
for i in arr: 循环
'cat' in arr 返回true
6 not in arr
size, color, disposition = arr 必须严格相等
index=arr.index('hello') 返回下标
arr.append('moose') 追加元素
arr.insert(1, 'chicken') 插入元素
arr.remove('bat') 删除元素
arr.sort() 排序(不能同时数字字母)
列表中的缩进不是代码块
arr2=arr 修改arr2影响arr
arr=[[1,2],[3,4]]
arr[0][0]

元组
eggs = ('hello', 42, 0.5)
eggs[0]
eggs[0:2]
len(eggs)
同字符串,不可变

字典(无序,键:整型、浮点型、字符串或元组)
myCat = {'size': 'fat', 'color': 'gray', 'disposition': 'loud'}
myCat2 = {100: 'fat', 400: 'gray', 50: 'loud'}
s=myCat['size']
myCat['size']='hello'
arr=myCat.values()
arr=myCat.keys()
eggs=myCat.items()
isH='size' in myCat
isNoH='size' not in myCat
value=myCat.get('cups', 0) 存在键则返回,不存在返回指定值
myCat.setdefault('color', 'black') 不存在键时设置值,存在不设

tuple(['cat', 'dog', 5]) 列表转换为元组
list(('cat', 'dog', 5)) 元组转换为列表
list('hello') 字符串转换为列表

type(('hello',) 元组类型
type(('hello')) 字符串类型

字符串不可以和数字相+
字符串可以通过+进行拼接
字符串*正整型: 复制
字符串==数字 得到false
10.0==10 得到true
None ==print('Hello!') 得到true
0、0.0 和' '(空字符串)被认为是 False

字典列表经常嵌套

3.控制流语句
代码块
1.缩进增加时:代码块开始。
2.代码块可包含其他代码块。
3.缩进减少为零,或减少为外面包围代码块的缩进:代码块就结束。

条件语句
if语句

if name == 'Alice':
print('Hi, Alice.')

if else 语句

if name == 'Alice':
print('Hi, Alice.')
else:
print('Hello, stranger.')

if elif else语句

if name == 'Alice':
print('Hi, Alice.')
elif age < 12:
print('You are not Alice, kiddo.')
elif age > 2000:
print('Unlike you, Alice is not an undead, immortal vampire.')
elif age > 100:
print('You are not Alice, grannie.')
else:
print('You are neither Alice nor a little kid.')

循环语句
while语句

spam = 0
while spam < 5:
if spam==0:
continue
spam = spam + 1
if spam==3:
break

continue 跳出本次循环
break 跳出循环

for语句

#0-4
for i in range(5):
print('Jimmy Five Times (' + str(i) + ')')

#12-15
for i in range(12, 16):
print(i)

#0 2 4 6 8
for i in range(0, 10, 2):
print(i)

#5-0
for i in range(5, -1, -1):
print(i)

4. 常用功能
4.1 正则表达式
所有正则表达式的函数都在 re 模块中
import re

1.创建正则表达式,返回Regex 对象
phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
2.没有找到则返回None,找到则返回 Match 对象
mo = phoneNumRegex.search('My number is 415-555-4242.')
3.获取匹配的文本
str=mo.group()

search返回一条,findall返回一组(有分组则返回元组列表,否则字符串列表)
phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')

分组
phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
mo = phoneNumRegex.search('My number is 415-555-4242.')
mo.group(1) 0或不填 返回整个文本,1:第一段
mo.groups() 获取所有分段
areaCode, mainNumber = mo.groups() 获取各分段值

匹配a或b,返回找到匹配的第一个
heroRegex = re.compile (r'a|b')
可选匹配(有或没有wo)
batRegex = re.compile(r'Bat(wo)?man')
零次或多次匹配
batRegex = re.compile(r'Bat(wo)*man')
一次或多次匹配
batRegex = re.compile(r'Bat(wo)+man')
指定次数匹配
haRegex = re.compile(r'(Ha){3}')
指定次或更多次匹配
haRegex = re.compile(r'(Ha){3,}')
0到指定次匹配
haRegex = re.compile(r'(Ha){,3}')
指定次到指定次匹配(默认会返回符合最多次即贪心)
haRegex = re.compile(r'(Ha){2,3}')
指定次到指定次匹配(非贪心,23都满足时返回最少次)
haRegex = re.compile(r'(Ha){2,3}?')

字符分类
\d 0 到 9 的任何数字
\D 除 0 到 9 的数字以外的任何字符
\w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
\W 除字母、数字和下划线以外的任何字符
\s 空格、制表符或换行符(可以认为是匹配“空白”字符)
\S 除空格、制表符和换行符以外的任何字符


[a-zA-Z0-9] 匹配所 有小写字母、大写字母和数字
[aeiouAEIOU] 将匹配所有元音字符
[^aeiouAEIOU] 将匹配所有非元音字符
[0-5] 0-5任意数字
\d+ 一个或多个数字

以Hello开始,任意数字结尾
beginsWithHello = re.compile(r'^Hello\d$')

通配符

.匹配除了换行之外的所有 字符
atRegex = re.compile(r'.at')
(.*)匹配任意文本
atRegex = re.compile(r'(.*)')
匹配任意文本 非贪心(取短优先)
atRegex = re.compile(r'(.*?)')
匹配任意文本(包括换行)
newlineRegex = re.compile('.*', re.DOTALL)

不区分大小写
robocop = re.compile(r'robocop', re.I)

将符合正则的字符串替换为指定字符串
namesRegex.sub('sb', '要验证的文本')
\1代表符合正则的字符串的第一位文本
namesRegex.sub('\1', '要验证的文本')

复杂正则(优化可读性)

phoneRegex = re.compile(r'''(
(\d{3}|\(\d{3}\))? # area code
(\s|-|\.)? # separator
\d{3} # first 3 digits
(\s|-|\.) # separator
\d{4} # last 4 digits
(\s*(ext|x|ext.)\s*\d{2,5})? # extension
)''', re.VERBOSE)

忽略大小写+任意字符包含换行+优化可读性
someRegexValue = re.compile('foo', re.IGNORECASE | re.DOTALL | re.VERBOSE)

4.2 读写文件
文件有两个关键属性:
“文件名” .后为扩展名,指出了文件的类型

“路径” 路径指明了文件在计算机上的位置
绝对路径 :总是从根文件夹开始
相对路径 :相对当前工作目录

文件分为:
纯文本 只包含基本文本字符,不包含字 体、大小和颜色信息
二进制文件 字处理文档、PDF、图像、电子表格 和可执行程序

文件夹名称和文件名在 Windows 和 OS X 上是不区分大小写的,但在 Linux 上是区分大小写的
./ 当前文件夹下 可省
../ 父文件夹下
. 当前文件夹路径

import os

路径
Windows上使用倒斜杠作作为路径分隔符,OS X和Linux上使用正斜杠。
解决:
os.path.join('usr', 'bin', 'spam') OS:usr/bin/spam Windows:usr\\bin\\spam

当前工作路径
s.getcwd()

跳转到其他路径
os.chdir('/其他路径')

创建新文件夹
os.makedirs('/文件夹路径')

相对路径转绝对路径
os.path.abspath(path)

是否是绝对路径
os.path.isabs(path)

start路径到path路径的相对路径,start不存在时默认当前路径
os.path.relpath(path, start)

文件路径最后一个/ 前的所有字符串(文件所处的路径)
os.path.dirname(path)
文件路径最后一个/ 后的所有字符串(即文件名)
os.path.basename(path)
分割 文件所处的路径和文件名
eggs=os.path.split(calcFilePath)
分割 /或\\
calcFilePath.split(os.path.sep)

获取文件大小(文件的字节数)
os.path.getsize(path)
获取所有文件
os.listdir('C:\\Windows\\System32')

是否存在该路径
os.path.exists('C:\\Windows')
是否是文件夹
os.path.isdir('C:\\Windows\\System32')
是否是文件
os.path.isfile('C:\\Windows\\System32')

读写文件
1.open
2.read write
3.close

打开文件(默认 只读)
helloFile = open('/Users/用户名/hello.txt')
打开文件(只读)
helloFile = open('/Users/用户名/hello.txt','r')
打开文件(只写-覆写)
helloFile = open('/Users/用户名/hello.txt','w')
打开文件(只写-追加)
helloFile = open('/Users/用户名/hello.txt','a')

读取文件(一个大字符串)
helloContent = helloFile.read()
读取文件(一个列表:以行为项)
arr=sonnetFile.readlines()

写入文件
helloFile.write('Hello world!\n')

关闭文件
helloFile.close()

用 shelve 模块保存变量
import shelve

保存
>>> shelfFile = shelve.open('mydata')
>>> cats = ['Zophie', 'Pooka', 'Simon']
>>> shelfFile['cats'] = cats
>>> shelfFile.close()

读取
>>> shelfFile = shelve.open('mydata')
>>> shelfFile['cats']
>>> shelfFile.close()


获取所有键
>>> list(shelfFile.keys())
获取所有值
>>> list(shelfFile.values())
获取文件类型
>>> type(shelfFile)

用 pprint.pformat()函数保存基础数据类型变量(优化可读性,文本文件)
import pprint

保存
>>> fileObj = open('myCats.py', 'w')
>>> fileObj.write('cats = ' + pprint.pformat(cats) + '\n')
>>> fileObj.close()

读取
>>> import myCats
>>> myCats.cats
>>> myCats.cats[0]['name']

组织文件
shutil 模块(或称为 shell 工具)
import shutil

复制文件(可修改文件名)
shutil.copy('源路径', '目标路径')

复制文件夹
shutil.copytree('源路径', ''目标路径')

移动文件(可修改文件名,会覆写,目标路径不存在则异常)
shutil.move('源路径', '目标路径')

永久删除文件
os.unlink(path)
永久删除文件夹(内容必须为空)
os.rmdir(path)
永久删除文件夹及内容
shutil.rmtree(path)

send2trash安全删除
import send2trash

删除并放入垃圾箱
send2trash.send2trash('bacon.txt')

遍历目录树
os.walk('路径')

for folderName, subfolders, filenames in os.walk('C:\\delicious'):
print('The current folder is ' + folderName)
for subfolder in subfolders:
print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
for filename in filenames:
print('FILE INSIDE ' + folderName + ': '+ filename)
print('')

压缩文件(zipfile 模块)
import zipfile


>>> import zipfile, os
1.移动到目标路径
>>> os.chdir('目标路径')
2.创建压缩文件
>>> exampleZip = zipfile.ZipFile('example.zip')
获取压缩内容列表
>>> exampleZip.namelist()
获取压缩内容文件
>>> spamInfo = exampleZip.getinfo('spam.txt')
获取压缩前大小
>>> spamInfo.file_size
获取压缩后大小
>>> spamInfo.compress_size
获取压缩效率
>>> 'Compressed file is %sx smaller!' % (round(spamInfo.file_size / spamInfo .compress_size, 2))
'Compressed file is 3.63x smaller!'
3.关闭压缩
>>> exampleZip.close()


解压缩(放到当前目录下)
exampleZip.extractall()
解压缩(到指定路径)
exampleZip.extractall('目标路径')

解压缩单个文件(放到当前目录下)
exampleZip.extract('spam.txt')
解压缩单个文件(到指定路径)
exampleZip.extract('spam.txt','目标路径')

向压缩文件添加文件(w:覆写 ,a:追加)
>>> newZip = zipfile.ZipFile('new.zip', 'w')
>>> newZip.write('spam.txt', compress_type=zipfile.ZIP_DEFLATED)
>>> newZip.close()

4.3 调试
主动抛出异常

try:
raise Exception('This is the error message.')
except Exception as err:
print('An exception happened: ' + str(err))

查看反向跟踪,定位错误点

发生错误时,调试器会自动生成错误信息(反向跟踪,包含出错消息、导致该错误的代码行号,以及导致该错误的函数调用的序列。这 个序列称为“调用栈”)。


优化可读性
import traceback
try:
raise Exception('This is the error message.')
except:
errorFile = open('errorInfo.txt', 'w')
errorFile.write(traceback.format_exc())
errorFile.close()
print('The traceback info was written to errorInfo.txt.')

断言
条件不满足时异常

assert hello == 'open', 'The pod bay doors need to be "open".'

运行python时加 -O 禁用断言(提高速度)

日志
import logging
相对print(),想禁用则禁用

放置在程序顶部
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
打印日志
logging.debug('Start of program')
logging.debug('hello')
logging.debug('End of program')

禁用日志
logging.disable(logging.CRITICAL)

日志级别
DEBUG logging.debug() 最低级别。
INFO logging.info() 用于记录程序中一般事件的信息
WARNING logging.warning() 用于表示可能的问题
ERROR logging.error() 用于记录错误
CRITICAL logging.critical() 最高级别。用于表示致命的错误


将日志记录到文件
logging.basicConfig(filename='myProgramLog.txt', level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')

启用调试器(运行程序后暂停到第一行,显示全局变量和局部变量)
控制端输入idle | 菜单栏Debug下Debugger
Go到下一个断点或结束
Step执行一行并暂停(遇到函数跳进)
Over执行一行并暂停(遇到函数跳过)
Out跳出当前函数
Quit停止调试

断点
设置在特定的代码行上,当程序执行到达该行时,它迫使调试器 暂停
代码行上右键 | Set Breakpoint

4.4 处理HTML
webbrowser 模块(python自带)---打开浏览器并加载网页
import webbrowser

打开浏览器并加载指定url页面
webbrowser.open('http://www.baidu.com/')

获取命令行参数(hello.py param1 param2) 参数以空格分割
import sys
if len(sys.argv) > 1: 大于1说明有参数(0:是该文件)
address = ' '.join(sys.argv[1:])

获取剪贴板内容
import pyperclip
address = pyperclip.paste()

requests 模块(需安装pip install requests)
import requests

下载文件
res = requests.get('http://www.gutenberg.org/cache/epub/1112/pg1112.txt')
是否下载成功
res.status_code == requests.codes.ok
下载失败则异常
res.raise_for_status()
保存下载文件
playFile = open('RomeoAndJuliet.txt', 'wb') 以二进制打开(用来保存Unicode编码)
for chunk in res.iter_content(100000): 每次保存100000字节
playFile.write(chunk)
playFile.close()

 

HTML
右键查看源代码
Safari偏好设置|高级|勾选显示开发菜单 cmd+shift+I打开开发调试栏

BeautifulSoup 模块解析 HTML(安装: pip install beautifulsoup4)
import bs4
soup = bs4.BeautifulSoup(res.text)
寻找元素(返回一个Tag对象的列表)
arr=soup.select('div') 获取指定类型的元素
soup.select('#author') 获取指定id的元素
soup.select('.notice') 获取指定类的元素
soup.select('div span') 获取指定【类型 子类型】的元素
soup.select('div > span') 获取指定【类型 直接子类型】的元素
soup.select('input[name]') 获取【指定类型含有指定属性】的元素
soup.select('input[type="button"]') 获取【指定类型的input元素】的元素
其他形式(参考css选择器)

len(arr)
获取该html标签
str(arr[0])
获取标签内的文本
arr[0].getText()
获取属性(返回字典)
arr[0].attrs
获取属性值
arr[0].get('id')

selenium 模块控制浏览器
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('http://www.baidu.com')
寻找元素(区分大小写,没有找到则NoSuchElement 异常)
webEle=browser.find_element_by_class_name(name) 指定类的元素
browser.find_elements_by_class_name(name)
browser.find_element_by_css_selector(selector) 指定selector的元素
browser.find_elements_by_css_selector(selector)
browser.find_element_by_id(id) 指定id的元素
browser.find_elements_by_id(id)
browser.find_element_by_link_text(text) 指定text的<a>元素
browser.find_elements_by_link_text(text)
browser.find_element_by_partial_link_text(text) 包含text的<a>元素
browser.find_elements_by_partial_link_text(text)
browser.find_element_by_name(name) 包含指定name属性的元素
browser.find_elements_by_name(name)
browser.find_element_by_tag_name(name) 包含指定name标签的元素
browser.find_elements_by_tag_name(name)

元素方法
tag_name 获取 标签名
get_attribute(name) 获取 属性值
text 获取 文本
clear() 清除输入(如:文本框)的文本
is_displayed() 是否禁用
is_enabled() 是否可用
is_selected() 是否被选中
location 坐标'x'和'y'

跳转链接
linkElem.click()
设置值
formElem.send_keys('值')
提交表单
formElem.submit()

转义字符
from selenium.webdriver. common.keys import Keys
Keys.DOWN, Keys.UP, Keys.LEFT,Keys.RIGHT 键盘箭头键
Keys.ENTER, Keys.RETURN 回车和换行键
Keys.HOME, Keys.END, Keys.PAGE_DOWN,Keys.PAGE_UP Home键、End 键、PageUp 键和 Page Down 键
Keys.ESCAPE, Keys.BACK_SPACE,Keys.DELETE Esc、Backspace 和字母键
Keys.F1, Keys.F2, . . . , Keys.F12 键盘顶部的F1到F12键
Keys.TAB Tab 键

htmlElem.send_keys(Keys.END)

点击浏览器按钮
browser.back() 返回
browser.forward() 前进
browser.refresh() 刷新
browser.quit() 关闭窗口

selenium
截取页面快照
运行定制的 JavaScript
修改浏览器的 cookie

4.5 处理Excel
处理Excel表格
一个 Excel 电子表格文档称为一个工作簿,扩展名为.xlsx
每个工作簿可以包含多个表(也称为工作表)
用户当前查看的表(或关闭 Excel 前最后查看的表),称为活动表
openpyxl 模块
安装

导入
import openpyxl

打开excel
返回一个 workbook 数据类型的值。这 个 workbook 对象代表这个 Excel 文件
必须当前目录
wb = openpyxl.load_workbook('example.xlsx')

获取所有表名
wb.get_sheet_names()

获取活动表(当前表)
anotherSheet = wb.get_active_sheet()

获取指定表
sheet = wb.get_sheet_by_name('Sheet3')

获取表名
sheet.title


获取指定格(列:A 行:1)
cell=sheet['A2']
cell=sheet.cell(row=1, column=2)
获取某格的值
cell.value
获取某格的行
cell.row
获取某格的列
cell.column
获取某格的坐标
cell.coordinate


获取最大行
sheet.get_highest_row()
获取最大列
sheet.get_highest_column()


列字母和数字之间的转换
from openpyxl.cell import get_column_letter, column_index_from_string
获取指定列的字母
get_column_letter(1)
获取指定字母位于第几列
column_index_from_string('A')


获取指定一片格
到了一个 Generator 对象(包含所有格子)
A1-C3
tuple(sheet['A1':'C3'])
所有第一列
sheet.columns[1]

保存(调用后才会保存更改)
wb.save('example_copy.xlsx')

 

创建Excel(默认:有一个表名:Sheet)
wb = openpyxl.Workbook()
创建表
wb.create_sheet()
创建表(在指定位置,指定标题)
wb.create_sheet(index=0, title='First Sheet')

删除指定表
wb.remove_sheet(wb.get_sheet_by_name('Middle Sheet'))

设置指定格子值
sheet['A1'] = 'Hello world!'


设置行高
sheet.row_dimensions[1].height = 70
设置列宽
sheet.column_dimensions['B'].width = 20


合并单元格
sheet.merge_cells('A1:D3')
分拆单元格
sheet.unmerge_cells('A1:D3')


滚动时固定窗格(b2左上,不含b2)
sheet.freeze_panes = 'B2'

设置单元格风格
from openpyxl.styles import Font, Style

italic24Font = Font(size=24, italic=True)
styleObj = Style(font=italic24Font)
sheet['A'].style/styleObj

公式
格(b9)的值等于 b1和b8的和
sheet['B9'] = '=SUM(B1:B8)'
必须加data_only才能看到计算结果,否则只能看到公式
wbDataOnly = openpyxl.load_workbook('writeFormula.xlsx', data_only=True)

Font
name 字符串
size 整型
bold 布尔型
italic 布尔型

图表
1.创建Reference对象(矩形区域)
Worksheet 对象、左上角、右下角(第一行:1)
refObj = openpyxl.charts.Reference(sheet, (1, 1), (10, 1))
2.创建Series对象(传入Reference对象)
seriesObj = openpyxl.charts.Series(refObj, title='First series')
3.创建一个Chart对象
chartObj = openpyxl.charts.BarChart() 柱状图
openpyxl.charts.LineChart() 折线图
openpyxl.charts.ScatterChart() 散点图
openpyxl.charts.PieChart() 饼图
4.将Series对象添加到Chart对象
chartObj.append(seriesObj)
5.可选设置 Chart对象的drawing.top、drawing.left、drawing.width 和 drawing.height
chartObj.drawing.top = 50
chartObj.drawing.left = 100
chartObj.drawing.width = 300
chartObj.drawing.height = 200

6.将Chart对象添加到Worksheet对象
sheet.add_chart(chartObj)

4.6 处理 PDF
处理 PDF

PDF(Portable Document Format).pdf 文件扩展名
安装
pip install PyPDF2
导入
import PyPDF2

打开文件
pdfFileObj = open('meetingminutes.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)

是否加密(没解密去读文件会异常)
pdfReader.isEncrypted
解密
pdfReader.decrypt('口令')
加密
dfWriter.encrypt('口令')

获取页数
pdfReader.numPages
获取指定页
pageObj = pdfReader.getPage(0)
获取指定页中的文本
pageObj.extractText()

 

创建pdf
PyPDF2写入PDF的能力,仅限于从其他 PDF 中拷贝页面、旋转 页面、重叠页面和加密文件

拷贝
不能在 PdfFileWriter 对象中间插入页面,只能在末尾
pdf1File = open('meetingminutes.pdf', 'rb')
pdf1Reader = PyPDF2.PdfFileReader(pdf1File)
pdfWriter = PyPDF2.PdfFileWriter()
pdfWriter.addPage(pdf1Reader.getPage(0))
pdfOutputFile = open('combinedminutes.pdf', 'wb')
pdfWriter.write(pdfOutputFile)
pdfOutputFile.close()

旋转
page.rotateClockwise(90)

叠加页面(标志、时间戳或水印)
page1.mergePage(page2)

4.7 处理 Word
Word 文档
.docx 文件 扩展名
Word 文档中的文本不仅仅是字符串。它包含与之相关的字体、大小、颜色和 其他样式信息。
python-docx 模块
安装
pip install python-docx
导入
import docx

Document 对象表示整个文档
Document 对象包含 一个 Paragraph 对象的列表,表示文档中的段落
每个 Paragraph 对象都包含一个 Run 对象(样式划分)的列表

获取doc
doc = docx.Document('demo.docx')

获取段落数
len(doc.paragraphs)

获取指定段的文本
doc.paragraphs[0].text

获取指定段中run的个数
doc.paragraphs[1].runs

获取指定段指定run的文本
(doc.paragraphs[1].runs[0]).text


自定义函数
【readDocx.py文件】
#! pythonHello
import docx
def getText(filename):
doc = docx.Document(filename)
fullText = []
for para in doc.paragraphs:
fullText.append(para.text)
return '\n'.join(fullText)
【使用】
import readDocx
readDocx.getText('demo.docx')




设置段落、Run样式、链接的样式
自定义样式

获取指定段落样式
doc.paragraphs[0].style
获取指定段落指定run样式
doc.paragraphs[1].runs[0].style
段落是否下划线
doc.paragraphs[1].runs[1].underline = True


Run对象上设置的text属性
bold 粗体
italic 斜体
underline 下划线
strike 删除线
double_strike 双删除线
all_caps 以大写首字母
small_caps 以大写首字母出现,小写字母小两个点
shadow 带阴影
outline 以轮廓线出现,而不是实心
rtl 从右至左书写
imprint 以刻入页面的方式出现
emboss 以凸出页面的方式出现



创建doc
doc = docx.Document()
标题(0~4 0最大)
doc.add_heading('Header 0', 0)
写入段落
paraObj1=doc.add_paragraph('Hello world!')
向指定段落写入Run
paraObj1.add_run(' This text is being added to the second paragraph.')
加入换页符 (换行:add_break())
doc.paragraphs[0].runs[0].add_break(docx.text.WD_BREAK.PAGE)
添加图片(宽度为 1 英寸,高度为 4 厘米,省略则为图片尺寸)
doc.add_picture('zophie.png', width=docx.shared.Inches(1), height=docx.shared.Cm(4))
保存doc
doc.save('helloworld.docx')

4.8 处理 CSV 简化表格
CSV 纯文本文件
CSV “Comma-Separated Values(逗号分隔的值)”简化的电子表格
CSV 文件中的每行代表电子表格中的一行,逗号分割了该行中的单元格

相比Excel
• 值没有类型,所有东西都是字符串; • 没有字体大小或颜色的设置;
• 没有多个工作表;
• 不能指定单元格的宽度和高度;
• 不能合并单元格;
• 不能嵌入图像或图表。

打开文件
exampleFile = open('example.csv')
创建 读
exampleReader = csv.reader(exampleFile)
得到一个列表
exampleData = list(exampleReader)
获取指定格
exampleData[0][0]
获取行号
exampleReader.line_num


outputFile = open('output.csv', 'w', newline='')
创建 写
outputWriter = csv.writer(outputFile)
创建 写(替换, 和换行符)
csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n')
写入一行
outputWriter.writerow(['spam', 'eggs', 'bacon', 'ham'])
outputFile.close()

4.9 处理 JSON
JSON(JavaScript Object Notation)
纯文本文件
仅能表示python数据类型中的字符串、整型、浮点型、布尔型、列表、字典和 NoneType

import json

json转字典
dic=json.loads('{"name": "Zophie", "isCat": true, "miceCaught": 0, "felineIQ": null}')

字典转json
str=json.dumps({'isCat': True, 'miceCaught': 0, 'name': 'Zophie', 'felineIQ': None})

4.10 时间、计时器、多线程
time模块
Unix纪元是编程中经常参考的时间:1970年1月1日0点(UTC)

import time

UNIX 纪元时间戳(自1970至现在的秒数)浮点型
可用于:函数前后各放置,测试运行时间

time.time()

暂停指定秒数
可用于设置闹钟
time.sleep(1)

注意:IDLE 中按 Ctrl-C 不会中断 time.sleep()调用,但在等待到暂停结束,会抛出KeyboardInterrupt异常。通常使用循环x数个time.sleep(1)来代替time.sleep(x数), 让Ctrl-C立刻触发异常。

四舍五入

保留2位小数点,不填默认整数
round(now, 2)

datetime模块
import datetime

返回一个datetime对象
可以使用== != > <进行比较

当前时刻
datetime.datetime.now()

1970+ 1000000秒的时刻
datetime.datetime.fromtimestamp(1000000)

dt = datetime.datetime(2015, 10, 21, 16, 29, 0)
dt.year, dt.month, dt.day,dt.hour, dt.minute, dt.second

返回时间段
delta = datetime.timedelta(weeks=1, days=11, hours=10, minutes=9, seconds=8, milliseconds=1, microseconds=1)

获取时间段所含周,天,小时,分钟,秒数,,微秒
delta.weeks ,delta.days,delta.hours,delta. minutes,delta.seconds, delta.milliseconds, delta.microseconds

获取所有秒数
delta.total_seconds()

获取可读格式
str(delta)

时间点+-时间段=时间点

 

 

 

date对象转字符串
str=datetime.datetime(2015, 10, 21, 16, 29, 0).strftime('%Y/%m/%d %H:%M:%S')

%Y 带世纪的年份,例如'2014'
%y 不带世纪的年份,'00'至'99'(1970 至 2069)
%m 数字表示的月份, '01'至'12'
%B 完整的月份,例如'November'
%b 简写的月份,例如'Nov'
%d 一月中的第几天,'01'至'31'
%j 一年中的第几天,'001'至'366'
%w 一周中的第几天,'0'(周日)至'6'(周六)
%A 完整的周几,例如'Monday'
%a 简写的周几,例如'Mon'
%H 小时(24 小时时钟),'00'至'23'
%I 小时(12 小时时钟),'01'至'12'
%M 分,'00'至'59'
%S 秒,'00'至'59'
%p 'AM'或'PM'
%% '%'字符


字符串转date对象
datetime.datetime.strptime('October 21, 2015', '%B %d, %Y')

多线程
可以用于并发下载
进程间不能共享变量

import threading

创建线程(target=函数名)
threadObj = threading.Thread(target=takeANap)
创建线程(target=函数名,参数1=值,参数2=值)
threadObj = threading.Thread(target=print, args=['Cats', 'Dogs', 'Frogs'], kwargs={'sep': ' & '})
开启线程(在新线程中执行函数)
threadObj.start()
将阻塞, 直到该线程完成
threadObj.join()

可能导致并发
如多个线程同时修改同一文件

启动其他程序
import subprocess

启动外部程序
calcProc = subprocess.Popen('/usr/bin/gnome-calculator')
启动外部程序(带参)
subprocess.Popen(['C:\\Windows\\notepad.exe', 'C:\\hello.txt'])
subprocess.Popen(['C:\\python34\\python.exe', 'hello.py'])
以默认程序打开
subprocess.Popen(['open', '/Applications/Calculator.app/'])

外部程序正在运行则返回None,否则返回整数退出代码(0:成功执行,非0:失败)
calcProc.poll() == None
将阻塞,直到启动的外部程序进程终止
calcProc.wait()

4.11 处理 邮件
简单邮件传输协议(SMTP) 是用于发送电子邮件的协议
规定电子邮件应该如何格式化、加密、在邮件服务器之间传递,以及在你点击发送后,计算机要处理的所有其他细节.

SMTP服务提供商
Gmail smtp.gmail.com
Outlook.com/Hotmail.com smtp-mail.outlook.com
Yahoo Mail smtp.mail.yahoo.com
AT&T smpt.mail.att.net (port 465)
Comcast smtp.comcast.net
Verizon smtp.verizon.net (port 465)

发送
import smtplib

1. 创建一个 SMTP 对象,不成功(不支持 TLS 端口 )则调2(没网则异常)
smtpObj = smtplib.SMTP('smtp.gmail.com', 587)
smtpObj = smtplib.SMTP_SSL('smtp.gmail.com', 465)

2. 向 SMTP 电子邮件服 务器“打招呼”
smtpObj.ehlo()

3.TLS 加密( tls需要+)
smtpObj.starttls()

4.登陆账号(密码不正确则异常SMTPAuthenticationError)
smtpObj.login('my_email_address@gmail.com', 'MY_SECRET_PASSWORD')

5.发送邮件
smtpObj.sendmail('my_email_address@gmail.com', 'recipient@example.com', 'Subject: So long.\nDear Alice, so long and thanks for all the fish. Sincerely, Bob')
{}

6. 断开服务器
smtpObj.quit()

接收
因特网消息访问协议(IMAP)
规定了如 何与电子邮件服务提供商的服务器通信


搜索关键字(可使用 OR、NOT)
'ALL'
指定当前文件夹中的所有邮件(过大可能会遇到 imaplib 的大小限制)
'BEFORE date','ON date','SINCE date'
指定date之前、当天、之后
日期的 格式必须像 05-Jul-2015
'SUBJECT string', 'BODY string', 'TEXT string'
指定主题、正文、主题或正文中。如果 string 中有空格,就 使用双引号“”
'FROM string', 'TO string','CC string', 'BCC string'
“from”邮件地址,“to”邮件地址,“cc”(抄 送)地址,“bcc”(密件抄送)地址。 多个电子邮件地址用空格分开,并使用双引号
'SEEN','UNSEEN'
分别返回包含和不包含\ Seen 标记的所有信息。如果电子邮件已经被 fetch()方法调用 访问(稍后描述),或者你曾在电子邮件程序或网络浏览器中点击过它,就会有\ Seen 标记。比较常用的说法是电子邮件“已读”,而不是“已看”,但它们的意思一样。
'ANSWERED', 'UNANSWERED'
分别返回包含和不包含\ Answered 标记的所有消息。如果消息已答复,就会有\ Answered 标记
'DELETED', 'UNDELETED'
分别返回包含和不包含\Deleted 标记的所有信息。用 delete_messages()方法删除的邮件就会 有\Deleted 标记,直到调用 expunge()方法才会永久删除(请参阅 16.4.10 节“删除电子邮件”)。 请注意,一些电子邮件提供商,例如 Gmail,会自动清除邮件
'DRAFT', 'UNDRAFT
分别返回包含和不包含\ Draft 标记的所有消息。草稿邮件通常保存在单独的草稿文 件夹中,而不是在收件箱中
'FLAGGED', 'UNFLAGGED'
分别返回包含和不包含\Flagged 标记的所有消息。这个标记通常用来标记电子邮件 为“重要”或“紧急”
'LARGER N', 'SMALLER N'
分别返回大于或小于 N 个字节的所有消息
'NOT search-key'
返回搜索键不会返回的那些消息
'OR search-key1 search-key2'
返回符合第一个或第二个搜索键的消息

import imapclient
import pyzmail
import imaplib


设置大小限制(超过会异常,默认:10000字节)
imaplib._MAXLINE = 10000000

1. 连接到 IMAP 服务器(大多数电子邮件提供商要求 SSL 加密)
imapObj = imapclient.IMAPClient('imap.gmail.com', ssl=True)
2. 登陆(密码错误则异常)
imapObj.login('my_email_address@gmail.com', 'MY_SECRET_PASSWORD')
3.(几乎每个账户默认都有一个 INBOX 文件夹)
打印所有文件夹
pprint.pprint(imapObj.list_folders())
选择文件夹进行搜索(文件夹不存在则异常)
imapObj.select_folder('INBOX', readonly=True)
4.搜索(根据关键字)返回消息ID列表
UIDs = imapObj.search(['SINCE 05-Jul-2014'])
5.获取邮件([UID],)
rawMessages = imapObj.fetch([40041], ['BODY[]', 'FLAGS'])
6.解析邮件
message = pyzmail.PyzMessage.factory(rawMessages[40041]['BODY[]'])
7.获取主题、form、to、cc抄送、bcc密件抄送
message.get_subject()
message.get_addresses('from')
message.get_addresses('to')
message.get_addresses('cc')
message.get_addresses('bcc')

获取纯文本(没有html)
message.text_part != None
message.text_part.get_payload().decode(message.text_part.charset)
获取html
message.html_part != None
message.html_part.get_payload().decode(message.html_part.charset)

删除电子邮件
imapObj.delete_messages(UIDs)
永久删除带有deled的文件
imapObj.expunge()

从 IMAP 服务器断开
imapObj.logout()

4.12 处理 短信
Twilio 一个 SMS 网关服务

注册:http://twilio.com/

from twilio.rest import TwilioRestClient
1.创建Client(SID、Token)
accountSID = 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
authToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
twilioCli = TwilioRestClient(accountSID, authToken)
2.发送短信(Twilio账号,目标手机号)
myTwilioNumber = '+14955551234'
myCellPhone = '+14955558888'
message = twilioCli.messages.create(body='Mr. Watson - Come here - I want to see you.', from_=myTwilioNumber, to=myCellPhone)

获取 to、from、内容、状态、创建时间、
message.to
message.from_
message.body
已发送:datetime对象、已收到:queued
'queued'、'sending'、'sent'、'delivered'、 'undelivered'或'failed'
message.status
message.date_created
message.date_sent == None
最新更新
每个 Twilio 消息都有唯一的字符串 ID(SID)
message.sid
updatedMessage = twilioCli.messages.get(message.sid)
updatedMessage.status
updatedMessage.date_sent

4.13 处理 图片
安装 pillow 模块

计算机程序通常将图像中的颜色表示为 RGBA 值(红、绿、蓝和 alpha)

White (255, 255, 255, 255)
Red (255, 0, 0, 255)
Green (0, 128, 0, 255)
Blue (0, 0, 255, 255)
Gray (128, 128, 128, 255)
Yellow (255, 255, 0, 255)
Black (0, 0, 0, 255)
Purple (128, 0, 128, 255)

from PIL import ImageColor

返回一个 RGBA 元组
ImageColor.getcolor('red', 'RGBA')

from PIL import Image

加载图像(必须是当前文件夹下,或是绝对路径)
catIm = Image.open('zophie.png')

获取大小
catIm.size
获取文件名
catIm.filename
获取文件格式(PNG)
catIm.format
获取文件格式详细(Portable network graphics)
catIm.format_description
以指定文件名保存
catIm.save('zophie.jpg')

旋转(返回新图片,不会修改原文件)(逆时针)
当图像旋转 90 度或 270 度,宽度和高度会变化。其他角度保持不变,使用透明的像素来填补缝隙
catIm.rotate(90)
自动放大尺寸
catIm.rotate(6, expand=True)

镜像翻转(返回新图片,不会修改原文件)
catIm.transpose(Image.FLIP_LEFT_RIGHT)
catIm.transpose(Image.FLIP_TOP_BOTTOM)

调整大小(返回新图片,不会修改原文件)
width, height = catIm.size
quartersizedIm = catIm.resize((int(width / 2), int(height / 2)))
剪裁图片
croppedIm = catIm.crop((335, 345, 565, 560))
复制图片
catCopyIm = catIm.copy()
粘贴图片(左上角)(会修改原文件)
catCopyIm.paste(faceIm, (0, 0))

空白的图像(RGBA模式,大小,背景色-默认黑色)
im2 = Image.new('RGBA', (100, 200), 'purple')
im2.save('purpleImage.png')


获取单个像素
im.getpixel((0, 0))
修改单个像素(返回新图片,不会修改原文件)
im.putpixel((x, y), (210, 210, 210))
im.putpixel((x, y), ImageColor.getcolor('darkgray', 'RGBA'))




在图像上绘画
from PIL import Image, ImageDraw
获取画笔
draw = ImageDraw.Draw(im)
画点
draw.point([(0, 0), (199, 0), (199, 199), (0, 199), (0, 0)], fill='black')
画线(width默认:1)
draw.line([(0, 0), (199, 0), (199, 199), (0, 199), (0, 0)], fill='black')
画矩形(outline:轮廓线颜色)
draw.rectangle((20, 30, 60, 60), fill='blue')
画椭圆(outline:轮廓线颜色)
draw.ellipse((120, 30, 160, 60), fill='red')
画多边形(outline:轮廓线颜色)
draw.polygon(((57, 87), (79, 62), (94, 85), (120, 90), (103, 113)),fill='brown')

绘制文本
from PIL import ImageFont
draw.text((20, 150), 'Hello', fill='purple')

绘制文本(指定字体名‘/Library/Fonts’下)
创建字体
fontsFolder = 'FONT_FOLDER'
字体 /Library/Fonts and /System/Library/Fonts
(字体文件夹,字体,点数每英寸 72 像素,一点是 1/72 英寸)
arialFont = ImageFont.truetype(os.path.join(fontsFolder, 'arial.ttf'), 32)
draw.text((100, 150), 'Howdy', fill='gray', font=arialFont)
获取文本的宽度和高度
textsize('ssss',arialFont)

im.save('drawing.png')

4.14 GUI 自动化(控制键盘和鼠标)
pyautogui 模块
sudo pip3 install pyobjc-framework-Quartz
sudo pip3 install pyobjc-core
sudo pip3 install pyobjc
pip install pyautogui ?


import pyautogui

停止
cmd-Shift-Option-Q(会丢失所有未保存的工作)
调用完函数后暂停(让用户有时间控制窗口)非 PyAutoGUI 指令不会停顿
pyautogui.PAUSE = 1.5
将鼠标移到屏幕的左上角会异常:自动防故障功能,禁止该功能
pyautogui. FAILSAFE = False



坐标(同手机 向左x增大,向下y增大)
分辨率:屏幕的宽和高有多少像素 1920 ×1080左上角(0,0)右下角的坐标是(1919,1079)
获取分辨率宽高
width, height = pyautogui.size()

移动鼠标(相对坐标原点)
pyautogui.moveTo(100, 100, duration=0.25)
移动鼠标(相对当前位置)
pyautogui.moveRel(100, 0, duration=0.25)
获取鼠标位置
pyautogui.position()

点击左键
pyautogui.click(100,150,button='left')
pyautogui.click(10, 5)


鼠标按下
pyautogui. mouseDown()
鼠标弹起
pyautogui.mouseUp()
双击左键
pyautogui.doubleClick()
双击右键
pyautogui.rightClick()
双击中键
pyautogui.middleClick()

拖动:移动鼠标,同时按住一个按键不放
鼠标移动太快 ,拖 动会出错,建议使用duration
相对当前位置
pyautogui.dragRel(distance, 0, duration=0.2)
想对坐标原点
pyautogui.dragTo(distance, 0, duration=0.2)


滚动鼠标(正向上)
pyautogui.scroll(200)

获取中心cente
pyautogui.center((643, 745, 70, 29))


屏幕
安装 pillow 模块
import pyautogui
获取屏幕快照(分析像素,决定执行某步骤)
im = pyautogui.screenshot()
指定坐标的像素是否与指定像素匹配
pyautogui.pixelMatchesColor(50, 200, (130, 135, 144))



图像识别
获取该图片所在位置
pyautogui.locateOnScreen('submit.png')
获取该图片所在位置列表
list(pyautogui.locateAllOnScreen('submit.png'))



键盘

首先获得焦点 输入文本
pyautogui.click(100, 100) ;pyautogui.typewrite('Hello world!')
输入一个单词暂停0.25s
pyautogui.typewrite('Helloworld!', 0.25)
按下,抬起
pyautogui.keyDown('shift'); pyautogui.press('4'); pyautogui.keyUp('shift')

Ctr+C
按下Ctr、c,释放c、ctr
pyautogui.hotkey('ctrl', 'c')
等价
pyautogui.keyDown('ctrl')
pyautogui.keyDown('c')
pyautogui.keyUp('c')
pyautogui.keyUp('ctrl')


hotkey('ctrl', 'alt', 'shift', 's')



单个字符的键
'a', 'b', 'c', 'A', 'B', 'C', '1', '2', '3', '!', '@', '#',等等
回车键
'enter'(or 'return' or '\n')
Esc 键
'esc'
左右 Shift 键
'shiftleft', 'shiftright'
左右 Alt 键
'altleft', 'altright'
左右 Ctrl 键
'ctrlleft', 'ctrlright'
Tab 键
'tab'(or '\t')
Backspace 和 Delete 键
'backspace', 'delete'
Page Up 和 Page Down 键
'pageup', 'pagedown'
Home 和 End 键
'home', 'end'
上下左右箭头键
'up', 'down', 'left', 'right'
F1 至 F12 键
'f1', 'f2', 'f3',等等
静音、减小音量、放大音量键
'volumemute', 'volumedown', 'volumeup'
Pause 键
'pause'
Caps Lock,Num Lock 和 Scroll Lock 键
'capslock', 'numlock', 'scrolllock'
Ins 或 Insert 键
'insert'
Prtsc 或 Print Screen 键
'printscreen'
左右 Win 键(在 Windows 上)
'winleft', 'winright'
Command 键(在 OS X 上)
'command'
Option 键(在 OS X 上)
'option'

 

转载于:https://www.cnblogs.com/nowindxdw/p/9101042.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值