- 作者:
- 分类:知识&开发->语言->Python
- 阅读:2511
- 点赞:50
- 版权:CC BY-SA 4.0
- 创建:2019-10-13
- 更新:2020-10-10
原文链接(持续更新):https://neucrack.com/p/59
本文主要是简单介绍,具体大量的函数库的使用不会具体说明, 比如对于list
类型会简单介绍概念,具体它相关的方法需要看文档或者其它更详细的教程
简介
Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言
python, 英文翻译为蟒蛇, 也可以看到它的 logo 也是两条不同颜色的蛇
1991年发行, 创始人为荷兰人吉多·范罗苏姆(Guido van Rossum)
python的实现也有很多版本, 主要使用的是python.org的版本(也就是CPython), 到现在实现分别有python2
和python3
两个大版本
特征
- 跨平台脚本语言
- 不需要编译, 解释型语言,语法检查也是在运行时
- 使用缩进符号来作为域分隔,作用类似
C
中的大括号(所以你的编辑器一定要注意缩进符号设置,建议设置成4个空格) - 面向对象语言
开源, 也免费,开源协议看这里
优点:
- 语法简单易学,好入门
- 可读性高
- 内置库和语法好用, 代码好读懂,编写代码快
- 各种现成的库,数量庞大,安装和引入非常简单
- 综上两点,节省头发和生命
- 可扩展性, 可方便地引入其它模块,以及其它语言编写的模块
- 缺点:
- 解释型语言, bug需要在运行后才能知道,那怕是语法错误(因为没有编译这一步), 所以测试要覆盖率高才行
- 解释型语言, 相比于编译型语言,运行效率低(注意这还跟程序的写法有很大关系), 所以一些关键的耗费性能的部分还是需要调用其它语言写的库
- 入门太容易
应用场景
- 脚本, 类似 shell 脚本的用法, 用来方便日常各种任务的自动化, 包括朋友圈天天发的办公自动化广告= =
- 自动化测试, 比如web自动化测试可以使用
selenium
库 - 爬虫, 有大量好用的库,以及很多参考项目
web
服务器,有很多现成的框架比如 Flask, Django, FastAPI 等- 科学计算, 有大量科学计算的库如 numpy matplotlib SciPy等
- 图形处理,如opencv VTK ITK
- 机器学习, 已有的库比如 TensorFlow 等
- 桌面软件开发, 对于桌面软件也有很多GUI框架, 比如 pyqt5, Kivy, wxPython, Tkinter 等
- 嵌入式开发, 没错,有嵌入式实现
Micropython
, 包括我们做的MaixPy
也是基于Micropython
- 游戏开发, 有很多游戏开发库如pygame,cocos2d,panda3d等
第一次遇见的很多问号
- 能取代 C/C++ 么?
回答: 不能 - 除了CPython还有哪些实现
回答: 比如 Jython(基于java编写), IronPython(基于.net框架), PyPy(基于RPython的实现,利用JIT(Just In Time 编译)来加快执行速度)
安装
下载 python3 (如果新学就不要学
python2
了)。 windows需要去官网下载, 然后命令执行pip3 install pyreadline
(tab补全); 在linux mac中默认已经安装了, 命令是python3
(python
命令默认可能是python2
), 以下均用python
表示python3
, 除非特殊说明运行程序, 比如取名
soft.py
print("hello python")
直接使用
python soft.py
即可运行软件soft.py。如果不支持中文, 可以设置一下系统语言(unix)
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
加入到~/.bashrc
或者~/.zshrc
安装其它程序
Python提供了包管理器pip
(英语发音[pɪp]
,中国很多也读成pipe
一样的读音,看你喜欢),使用pip安装软件pip install soft_name
,更多方法看官方文档
另外, 如果从默认的国外的源下载太慢,可以设置国内的源,比如以下几个:IDE
pycharm
,或者vscode
装python
插件或者更多其它的可以自己发掘
寻找库
发布
源码直接发布, 比如我写的这个串口助手
二进制发布,打包成平台对应的可执行文件, 比如 windows 的 exe, macOS 的 dmg
使用py2exe、cx-freeze、pyInstaller(推荐)等工具来进行打包,这种打包方式会将环境和依赖一同打包进软件,用户使用时下载软件包后可以直接运行,不需要用户自己安装Python。
比如cx-free打包:参考:http://www.cnblogs.com/zhongtang/p/5699322.html
建议使用pyinstaller
, 比如pyinstaller --add-data="kflash_gui_data:kflash_gui_data" --add-binary="kflash_py:kflash_py" -i="kflash_gui_data/assets/logo.ico" -w kflash_gui.py
作为一个模块或者软件在pypi.org发布, 用户使用包管理工具
pip
安装,将工程设置为pip可以安装的方法参见官方说明,这样用户使用的时候只需使用pip install softName
就可以安装软件啦
虚拟环境
- 如果需要对某个工程使用特定的环境,使用
virtualenv
pip3 install virtualenv
virtualenv --no-site-packages venv # venv是虚拟环境的名称
source venv/bin/activate #激活虚拟环境
deactivate # 退出虚拟环境
- 如果需要在一台电脑上安装多个环境(不同python版本,同时还可以不同包),可以用
conda
(miniconda(推荐), Anaconda都可以)conda create --name test python=3.7
conda activate test #激活环境
conda list # 展示已经安装了的包
conda deactivate # 退出环境
基本语法
查看模块帮助信息
import json
print(dir(json))
help(json)
打印
print("hello")
print("hello", "no return" , end="")
print("hello")
注释
- 行注释:
#
开头 - 段注释: 三引号
#############
# 这是注释
#############
'''
这也是注释
'''
"""
这也是注释
"""
另外,在文件头声明
#! /usr/bin/env python3
可以使用./文件名.py
直接执行
缩进
这是python 和其它语言非常不同的一点, 其它语言很多都用大括号来分隔函数条件循环等, python使用缩进, 可以使用tab
或者空格
, 所以这里也需要十分注意,tab
和空格是不一样的,在写程序时需要使用一样的,最好编辑器设置好tab
自动转换为4个空格
def func():
print("hello") # 这里使用了tab按键
def func2():
print("hello") # 这里使用了空格
注意如果在一个文件内即用空格又用tab就会报格式错误
多行
和其它语言一样使用\
符号来换行, 如果是list, dict等对象,不需要,比如:
a = [1,2,
3,4]
b = {
"aaa": 123
}
等待用户输入
a = input("请输入内容")
print(a)
同一行多个语句
print("aaa"); print("bbb")
变量
直接赋值,不需要声明类型
a = 10
print(type(a))
print(a)
注意 全局变量使用
- 全局变量在函数中使用需要注意:获取值可以直接使用,但是如果要赋值一定要 global 声明, 不然是定义一个新的局部变量
g = 10
def test():
print(g)
def test2():
g = 20
def test3():
global g
g = 30
print(test())
print(test2())
print(g)
print(test3())
print(g)
- nonlocal 使用
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
outer()
类型
可以用type(变量)
来获取变量类型
str
: 字符串, bytes
:字节
字符串可以用单引号或者双引号或者三引号, 可以嵌套, 比如'string:"hello"'
, 不需要转义符,很方便。
三引号是可以扩一整段,包括多行,注意不赋值给变量可以当成注释功能
python 里面字符串分为两种, 一个是
ascii
字节码, 另一个unicode
字符串str_bytes = b'12\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88'
str_unicode = '12哈哈哈哈'
print(str_unicode.encode('utf-8') == str_bytes)
print(str_unicode == str_bytes.decode())
字串: 下标取,
字符串的常见函数,直接在终端中输入变量按tab补全就有了, 或者看文档
这里说一下格式化字符串:
第一种,类似c
的printf
:my_str = 'hello %.2f %04d %s' %(1.23456, 12, "good")
print(my_str)
或者
format
:my_str = 'hello {:.2f} {:04d} {}'.format(1.23456, 12, "good")
print(my_str)
转义符号:
\
,如果不想字符串被转义,在字符串前面添加r
,比如`r’hello\n’’去掉行末空格 行首空格
s = ' 123 '
print(s.strip())
print(s.lstrip())
print(s.rstrip())
list
: 列表, 类似 C 中的数组
a = [1,2,3,4, "hello"]
- 取子list
a = [1,2,3,4,5]
print(a[0:3]) # [1,2,3]
冒号 :
, [i:j]
, i
是开始(默认0
),j
是结束(默认len
), 也可以负数,表示从后往前数,比如[-2:-1]
就是去倒数第2个数据
两个冒号 ::
, 实际上是[i:j:s]
,
- 当
s>0
:i
默认0
,j
默认len
,s
默认值1
代表步进. 步进为1
的情况就和使用一个冒号一样了 - 当
s<0
:i
默认-1
,j
默认-len-1
,代表步进, 比如-1
就代表反向步进1
iter
迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print (x, end=" ")
tuple
:元组, 不可更改
a = (1,2,3,4, "hello")
set, frozenset
: 与数学中集合的概念类似。无序的、每个元素唯一。
{4.0, 'string', True}
frozenset([4.0, 'string', True])
dict
: 字典, 键值对
d = {
'key1': 1.0,
3: False
}
print(d)
int
, float
, bool
:证书浮点数布尔
a = 10
b = 1.234
print(a, b, int(b))
a = True
b = False
注意 True``False
大写开头
complex
: 复数
3+2.7j
range
: 按顺序排列的数
a = range(10)
a = range(0, 10)
print(list(a))
运算符
几乎和其它语言一样, +-*/
, <<
, >>
|
&
, 或是or
, 与是and
, 非是not
a = 10
if not 0 and a==10:
print("hello")
常用转换函数
str(x)
: 将对象 x 转换为字符串int(x [,base])
: 将x转换为一个整数float(x)
: 将x转换到一个浮点数complex(real [,imag])
; 创建一个复repr(x)
: 将对象 x 转换为表达式字符串eval(str)
: 用来计算在字符串中的有效Python表达式,并返回一个对象tuple(s)
: 将序列 s 转换为一个元组list(s)
: 将序列 s 转换为一个列表set(s)
: 转换为可变集合dict(d)
: 创建一个字典。d 必须是一个 (key, value)元组序列。frozenset(s)
: 转换为不可变集合chr(x)
: 将一个整数转换为一个字符ord(x)
: 将一个字符转换为它的整数值hex(x)
: 将一个整数转换为一个十六进制字符串oct(x)
: 将一个整数转换为一个八进制字符串
函数
def test(arg, optional=10):
print(arg, optional)
test()
类
class Base:
a = 10
b = 20
__private_v = 10
class AAA(Base):
def __init__(self, arg):
print(arg)
print(a)
def __del__(self):
pass
varA = AAA(123)
print(varA.a, varB.b, AAA.a, AAA.b)
varA.a = 100
AAA.a = 999
AAA.b = 888
print(varA.a, varB.b, AAA.a, AAA.b)
需要注意的类的变量的对象的变量, 对象的变量要在构造函数
__init__
中使用self.a
这样定义,
类变量要直接在类中定义,就像上面Base
类的a
变量。
每个对象都会有这个类变量,但是对象一旦修改了这个类变量,这个类变量就变成了这个对象专有的对象变量了,通过类名修改这个变量也不会影响到这个对象变量注意,这里每个成员函数的
self
参数就是对象, 不是类, 类成员用类名调用__
两个下划线开头表示是私有变量调用父类方法:
super(Class, obj).func()
返回多个参数: 返回一个元组或者列表类型即可
匿名函数
lambda
:add = lambda x,y:x+y
print(add(3,4))
闭包函数(返回函数)
#闭包函数,其中 exponent 称为自由变量
def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of # 返回值是 exponent_of 函数
square = nth_power(2) # 计算一个数的平方
cube = nth_power(3) # 计算一个数的立方
print(square(2)) # 计算 2 的平方
print(cube(2)) # 计算 2 的立方
函数注解(
decorator
)
本质上,decorator
就是一个返回函数的高阶函数.def log(func):
def wrapper(*args, **kw):
print('call %s()' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2015-3-25')
#call now()
#2015-3-25
偏函数
from functools import partial
def mod( n, m ):
return n % m
mod_by_100 = partial( mod, 100 )
print mod( 100, 7 ) # 2
print mod_by_100( 7 ) # 2
bin2dec = partial( int, base=2 )
print bin2dec( '0b10001' ) # 17
print bin2dec( '10001' ) # 17
- 参数,返回值类型指定:
输出为:def add(num1: int, num2: int=100) -> int:
sum = num1 + num2
return sum
#
if __name__ == "__main__":
print(add.__annotations__)
print(add(1,2))
print(add(1))
print(add('test1', 'test2'))
{'num1': <class 'int'>, 'num2': <class 'int'>, 'return': <class 'int'>}
3
101
test1test2
控制语句
if
:a = 1
if a == 1:
print("hello")
elif a == 2:
print("hello 2")
else:
print("hello 3")
for
:循环迭代器for i in range(0, 10):
print(i)
`
while
:循环count = 0
while 1:
print("hello")
count += 1
if count < 2:
continue
break
try
:捕获import traceback
import sys
try:
raise Exception("error lalala")
except Exception as e:
print("error:", e)
traceback.print_exc()
err_info2 = sys.exc_info()
traceback.print_tb(err_info2[2])
else:
print("no error")
finally:
print("finally")
这里用了
traceback.print_exc()
或者sys.exc_info()
来打印出错的行数等信息traceback.print_exc()
原型是print_exception(etype, value, tb[,limit[, file]])
pass
: 表示此行为空,不运行任何操作。assert: 用于程序调试阶段时测试运行条件是否满足。
with
:with open("file.txt") as f:
print(f.read())
yield: 在迭代器函数内使用,用于返回一个元素。自从Python 2.5版本以后。这个语句变成一个运算符。
in
: 判断一个对象是否在一个字符串/列表/元组里。for i in range(0, 10):
print(i)
l = [1,2,3]
print(2 in l)
import
: 导入一个模块或包。from … import
: 语句,从包导入模块或从模块导入某个对象。import … as
: 语句,将导入的对象赋值给一个变量(别名)。
常用全局变量
__name__
: 当文件或模块被python直接执行比如python test.py
则这个文件这个变量的值为__main__
,否则为包名, 所以可以利用这个来区分是被当成模块调用还是直接执行, 一般在文件中写:def test():
print("test")
if __name__ == "__main__":
test()
__file__
: 当前文件的路径, 注意以相对路径运行文件可能是相对路径, 可以用os.path.abspath(__file__)
获取绝对路径__all__
: 指定模块内哪些变量能被import
使用
def test():
print("hello")
def test2():
print("test2")
__all__ = ['test'] # 如果使用 from var import test2 会报错
# 但是使用import var; var.test2()可以使用
# 直接执行文件也是都可以访问的
模块
一个模块是一个文件夹, 下面有一个__init__.py
, 这里面的内容就是模块的内容, 也可以在文件夹下建其它文件
test
├─ __init__.py
├─ aaa.py
└─ bbb.py
使用:
import test
from test import aaa, bbb
from test.aaa import *
常见模块及使用方法
后台运行及时打印日志到文件
执行命令时加 -u
参数,
(python -u test.py > teset.log 2>&1 &)
文件操作
with open("文件名", 'r') as f:
print(f.read())
f = open("文件名", 'r')
print(f.read())
f.close()
更多可以看其它教程
文件、文件夹、路径操作
import sys
import os
import shutil
import glob
os.getcwd()
shutil.copyfile('data.db', 'archive.db')
shutil.move('/build/executables', 'installdir')
shutil.rmtree("./test_dir")
print(glob.glob('*.py')) # ['primes.py', 'random.py', 'quote.py']
执行语句
eval(source, globals=None, locals=None, /)
或者
exec(source, globals=None, locals=None, /)
globals
和locals
传字典类型, globals
不传会使用默认全局命名空间eval
会返回执行结果, exec
不会
执行shell命令
sys.call()
subprocess.Popen()
正则表达式
参考菜鸟教程
数据库
内置了
sqlite3
使用
mysql
, 用pymysql
或者mysql-connector
库
网络
- socket: 直接
import socket
使用即可,包含服务端和客户端 - http客户端: requests(入门推荐), urllib, httplib, xmlrpclib, 解析用
xpath
或BeautifulSoup
多线程
- 简单的用
_thread
模块
_thread.start_new_thread ( function, args[, kwargs] )
参数
- function - 线程函数。
- args - 传递给线程函数的参数,他必须是个tuple类型。
- kwargs - 可选参数。
推荐用
threading
模块同步锁用
threading.Lock()
和threading.RLock()
(同一个线程可重入可嵌套)多线程使用队列, 可以直接使用
queue
模块
多进程
- unix 下可以用
os.fork
- 跨平台使用
multiprocessing
模块 - 调用执行其它程序用
subprocess
- 还可以使用
multiprocessing.managers
模块来分布式进程
参考这里
协程
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
asyncio 实现异步IO
import threading
import asyncio
@asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
yield from asyncio.sleep(1)
print('Hello again! (%s)' % threading.currentThread())
async def hello2():
print("Hello world!")
r = await asyncio.sleep(1)
print("Hello again!")
loop = asyncio.get_event_loop()
tasks = [hello(), hello2()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
json
json.loads
,json.dumps
用来处理json字符串
和dict
互相转换json.load
,json.dump
用来处理文件中的json字符串
和dict
互相转换,参数需要传文件操作对象
常见问题以及遇到的问题
bytes 和 str 不同
dataToSend = 'AT\r\n'
self.com.write(dataToSend)
raise TypeError('unicode strings are not supported, please encode to bytes: {!r}'.format(seq))
解决:
dataToSend = 'AT\r\n'.encode()
print(dataToSend)
self.com.write(dataToSend)
打包 cx-freeze
bash: /c/Users/neucrack/AppData/Local/Programs/Python/Python36-32/Scripts/cxfreeze: C:\program: bad interpreter: No such file or directory
解决:C:\Users\neucrack\AppData\Local\Programs\Python\Python36-32\Scripts
下的cxfreeze和cxfreeze-postinstall和cxfreeze-quickstart文件修改一下:
#!python.exe
cx-freeze打包去掉控制台黑框
如果是windows,加一个参数
--base-name=win32gui
或者使用cxsetup.py配置文件,base = "Win32GUI"
pyqt使用styleSheet
# 对整个app生效:
app = QApplication(sys.argv)
file = open('style.qss',"r")
app.setStyleSheet(file.read())
# 对单个组件生效:
button = ...
button.setStyleSheet(file.read())
例子见官方文档