1.认识python
python的官方介绍:
“Python是一种简单易学,功能强大的编程语言,它有高效率的高层数据结构,简单而有效地实现面向对象编程。Python简洁的语法和对动态输入的支持,再加上解释性语言的本质,使得它在大多数平台上的许多领域都是一个理想的脚本语言,特别适用于快速的应用程序开发。 ”
由 Guido van Rossum创造的广泛使用的解释型的高级通用型语言。设计哲学强调代码的可读性和简洁的语法,试图让程序的结构清晰明了。
关于编译型和解释型:
编译型语言比如C或C++写的程序可以从源文件(即C或C++语言),通过编译器和不同的标记、选项,转换到一个你的计算机使用的语言(二进制代码,即0和1)。运行程序的时候,连接/转载器软件把程序从硬盘复制到内存中并且运行。
而Python语言写的程序不需要编译成二进制代码。你可以直接从源代码运行程序。在计算机内部,Python解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成二进制语言并运行。
与Scheme、Ruby、Perl、Tcl等动态类型编程语言一样,python拥有动态类型系统和垃圾回收功能,能自动管理内存使用,支持面向对象、面向过程、函数式、命令式等多种编程范式。
本身拥有庞大的标准库,包括正则表达式、文档生成、单元测试、线程、数据库、网页浏览器、CGI(公共网关接口:是web服务器运行时外部程序的规范)、FTP、电子邮件、HTML、XML、XML-RPC(远程过程调用的分布式计算协议)、WAV文件、GUI、密码系统、Tk和其他与系统有关的操作。
术语表
argument | attribute | base class | block | comment | derived class |
---|---|---|---|---|---|
实参 | 属性 | 基本类 | 块 | 注释 | 导出类 |
parameter | indentation | identifier | subclass | superclass |
---|---|---|---|---|
形参 | 缩进 | 标识符 | 子类 | 超类 |
2.python相关开发工具
IDLE(python安装后自带的,新手熟悉python编码风格必备);
Pycharm(专门面向python的全功能IDE);
Sbulime3(相对轻量级);
Visual Studio;
……
工具很多,使用起来大同小异,找到最适合的就OK。
3.基本概念
3.1 标识符
命名规则:第一个字符必须是字母或下划线;其他部分可以是字母、下划线、数字;对大小写敏感;不能是python的关键字。
以下划线开头的标识符是有特殊意义的。_foo
代表不能直接访问的类属性,需通过类提供的接口进行访问。__foo
代表类的私有成员,__foo__
代表python里特殊方法专用的标识,如__init__()
代表类的构造函数、__doc__
用于获取文档注释。
无效标识符示例:2th、this is a、my-name
3.2 数据类型和数据结构
数据类型关心数据的种类,是一组性质相同的值的集合与定义在此集合上的一组操作的总称;
而数据结构关心数据的构造,是一个数据元素与数据元素间关系的集合
数据类型 | 是否可变 | 示例 |
---|---|---|
数字(number) | N | 10、10.0、3 + 2j 或 complex(3,2) |
字符串(string) | N | ‘’、abc |
元组(tuple) | N | ()、(2,) |
列表(list) | Y | []、[2, 3] |
字典(dictionary) | Y | {}、{a : 1, b : 2} |
集合(sets) | Y | set = set() |
除了这6种基本的标准数据类型,还可以有用class自定义的类型。
数据结构 | 包含 | 特性 |
---|---|---|
序列 | 字符串、元组、列表 | 支持索引和切片 |
散列 | 字典 | |
集合 | 集合 |
数字
支持int、long、float、complex。
print(2 / 4) # 除法,取浮点数,输出0.5
print(2 // 4) # 除法,取整,输出0
print(17 % 3) # 取余,输出2
print(2 ** 5) # 乘方,输出32
eval(str) # 计算str中的有效python表达式,并返回一个对象
>>> eval('2*3')
6
# exec语句用来执行储存在字符串或文件中的python语句
>>> exec 'print"hello world"'
hello world
# 数学运算常用的函数多在math模块(多对浮点数)、cmath模块(多对复数)中
abs(x) # 返回数字的绝对值
ceil(x) # 返回上入整数,如math.ceil(4.1)返回5
floor(x) # 返回下舍整数,如math.floor(4.9)返回4
pow(x, y) # x**y的值
sqrt(x) # x的平方根
random() # 随机生成一个实数,[0,1)
uniform(x,y) # 随机生成一个实数,[x,y]
shuffle(lst) # 将序列的所有元素随机排序
字符串
可用单(双/三单/三双)引号来创建。
运算符操作
“在序列的其他数据类型中操作以此类推”
str * 3 # 重复输出3遍
str[start: stop: stride] # 切片,反转字符串s[::-1]
eg.利用切片操作,实现一个trim()函数,去除字符串首尾的空格
# -*- coding: utf-8 -*-
def trim(s):
while s[:1] == '':
s = s[1:]
while s[-1:] == '':
s = s[:-1]
return s
not in # 判断字符不在字符串中
% # 格式化输出,print ("My name is %s and height is %d cm" % ('xiaoming', 175))
内建函数
str.capitalize() # 首字符大写
str.center(width) # 返回新字符串:长度为width,原str居中,其余是空格
str.count(s, beg=0, end=len(str)) # 指定范围内s出现的次数
str.find(s, beg=0, end=len(str))与str.rfind() # 查找s在指定范围内的开始处的索引值,没有就返回-1;最后一次的位置
str.replace(s1, s2, num=str.count(s1)) # s1换成s2,num是最大次数
str.partition(s)与str.rpartition(s) # 分隔,组成三个元素的元组
str.format() # 格式化输出
str.startswith(obj, beg=0, end=len(str)) 与endswith() # 判断以obj开始(结束)
str.isalnum() # 判断所有字符都是字母、数字
str.isalpha() # 判断都是字母
str.isdigit() # 判断都是数字字符,不包括汉字数字、罗马数字等
str.isnumeric() # 判断都是数值字符,包括汉字数字、罗马数字
str.lower()与str.upper() # 大写字符转小写与小转大
str.swapcase() # 翻转大小写
str.lstrip()与str.rstrip() # 截掉str左(右)边的空格
元组
元组与列表类似,只是元素不可变,但元组本身可以通过运算符修改来创建新的元组,或者del语句整个删除。
元组的内置函数也类似于列表。
列表
函数与方法
"""函数"""
len(list) # 元素个数
max(list)与min(list) # 最大最小值
list(seq) # 序列变成列表
"""方法"""
list.count(obj) # 统计次数
list.append(obj) # 末尾添加新元素
list.extend(seq) # 末尾追加多个值
list.index(obj) # 找第一个obj的索引位置
list.insert(index, obj) # 插入值
list.pop(index=-1) # 移除(默认最后一个)元素,且返回值
list.remove(obj) # 移除第一个obj
list.reverse() # 反向排列元素
字典
- dict作为Python的关键字和内置函数,变量名不建议命名为dict;
- 由于键不可变,所以可选择数字、字符串、元组,不能选列表;
内置方法
dict.clear() # 删除所有元素
dict.get(key, default=None) # 返回指定key的值,如果不存在则返回default值
dict.has_key(key) # 判断键key在字典中
dict.keys()与dict.values()与dict.items() # 返回所有的键的迭代器/值的迭代器/键值对元组数组
dict.pop(key[,default]) # 删除并返回key对应的值,没有key时返回default
dict.popitem() # 删除并返回最后一对键值对
集合
由不重复元素组成的无序(不能用索引和切片)的集。
- 可以通过集合去判断数据的从属关系,也可以通过集合把数据结构中重复的元素减掉;
- 集合内的数据:str,int,float,tuple,冰冻集合等;
- 集合对象支持联合、交集、差集、对称差分等数学运算。
比如想要检查列表中是否包含重复的元素,用集合就会比直接for循环更简单优雅:
some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']
duplicates = []
for value in some_list:
if some_list.count(value) > 1:
if value not in duplicates:
duplicates.append(value)
print(duplicates)
# 输出: ['b', 'n']
some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']
duplicates = set([x for x in some_list if some_list.count(x) > 1])
print(duplicates)
# 输出: set(['b', 'n'])
# 创建集合可用大括号或set()
par = {val1, val2, ...}
set(val) # 空集合是set()
# 向集合s中添加元素x,如果已存在,则不进行任何操作
s.add(x)
s.update(x, y, z, ...)
# 移除元素,不存在则报错/不报错
s.remove(x) / s.discard(x)
s.pop() # 随机删除一个元素
s.clear() # 清空
# 集合运算
- (减号)前集合有,后集合没有的元素
| 前+后,然后去重
& 前后集合中都有的元素
^ 不同时存在于前后集合中的元素
"""内置方法"""
# 1.计算差集
difference()与difference_update() "-"
# x.difference(y)会返回一个新集合
# x.difference_update(y)没有返回值
# 2.返回并集,重复元素会自动去掉。"|"
union()
s.union(x, y...)
# 3.返回x,y中不重复的元素的集合。"^"
symmetric_difference() # symmetric:对称的
# 4.移除x里与y重复的元素,把y里不重复的元素插入到x中
x.symmetric_difference_update(y)
# 5.判断
isdisjoint() # x.isdisjoint(y),判断x与y没有相同元素,否则返回False
issubset() # x.issubset(y),判断x全部包含在y中(sub有子过程的意思,“是子集合”的作用对象是x...)
issuperset() # x.issuperset(),判断y全部包含在x中(subset:超集),与issubset()效果相反
3.3 流程控制
if语句
if … elif … else … 序列用于替代其它语言中的 switch 或 case 语句。
if True:
print('Yes, it is true')
while循环
for循环
# 格式
for iterating_var in sequence:
statements(s)
break语句和continue语句
break用于跳出循环体,结束对应的整个循环过程;
continue跳过当前循环,继续下一轮循环
3.4 函数
根据有无参数(默认值参数、关键字参数、可变参数等)、返回值可分为四类。
# 递归函数:直接或间接调用函数本身的函数
# 阶乘的递归实现
def fact(n):
if n == 1:
return 1
return n * fact(n - 1)
3.5 模块和包
模块(module)即py文件,用于在别的程序中重用它提供的服务和功能。
import module1[, module2, ...moduleN]
from module1 import func1
from module1 import *
- 用
__name__
属性限制程序只在程序本身被使用时运行模块; - 可用dir()函数来列出模块定义的标识符;
包(package)是python中对模块更高一级的抽象。
import 包名.包名.模块名
- 包的路径下必须存在
__init__.py
文件
3.6 类与对象
- 类中的自定义方法:类方法、静态方法、实例方法
- 类中应包含数据(属性)和操作数据的方法(函数,即调用方法)
- 面向对象编程的三大特性:封装、继承、多态;
"""创建类时的一些内置方法"""
__init__ # 构造函数,生成对象时调用
__del__ # 析构函数,释放对象时使用
__str__ # 对对象使用print语句或str()时调用
__len__ # 获得长度
# self:python类中的函数必有的额外参数,永远在第一位指向实例对象本身,约定俗成叫self,调用时不需要传递。
class Apple(object): # 定义类
def __init__(self, x, y): # 初始化
self.x = x
self.y = y
def add(self):
sum = self.x + self.y
return sum
red = Apple(1, 2) # 类的实例化->red对象
print(red.add())
类方法(可调类变量,可被类、实例调用)
1.通过@classmethod装饰器实现;
2.通过cls参数传递当前类对象,不需要实例化。
class Car(object):
name = 'BMW'
def __init__(self, name):
self.name = name
@classmethod
def run(cls, speed):
print(cls.name, speed, '行驶')
# 访问方式1
c = Car("宝马")
c.run("100迈")
# 访问方式2
Car.run("100迈")
静态方法(可调类变量,可被类、实例调用)
1.通过@staticmethod装饰的不带self参数的方法;
2.实际在静态方法中无法访问类和实例中的任何属性;
3.调用时不需要传递类或实例。
class Car(object):
name = 'BMW'
def __init__(self, name):
self.name = name
@staticmethod
def run(speed):
print(Car.name, speed, '行驶')
# 访问方式1
c = Car("宝马")
c.run("100迈")
# 访问方式2
Car.run("100迈")
实例方法(可调用变量、实例变量,可被实例调用)
第一个参数强制为实例对象self。
class Car(object):
name = 'BMW'
def __init__(self, name):
self.name = name
def run(self, speed):
print(self.name, speed, '行驶')
# 访问
c = Car("宝马")
c.run("100迈")
3.7 输入输出
很多时候需要让程序与用户进行交互。从用户处得到输入,然后打印一些结果,可以用input、print语句完成;使用多种类的str可以完成输出。
此外,处理文件(创建、读写等)也是种常见的I/O类型。
格式化输出之format()方法
1.{}及其里面的字符(格式化字段)会被format()中的参数替换
>>> print('{} world: "{}!"'. format('hello', '你好世界'))
hello world: "你好世界!"
2.在括号里的数字用于指向传入对象在format()中的位置
>>> print('{1} {0}'.format('hello', 'world'))
world hello
3.使用关键字参数以及与位置参数组合
>>> print('{name}网址:{site}'.format(name='百度', site='www.baidu.com'))
百度网址:www.baidu.com
>>> print('电商网站:{1}、{0}、{other}。'.format('淘宝', '京东', other='拼多多'))
电商网站:京东、淘宝、拼多多。
4.数字格式化
>>> print('{:.2f}'.format(3.1415926))
3.14
……
文件操作
read(size) # size可选
readline() # 读一行
readlines(size) # 读全部(或size)行
write(str) # 写入内容,需要为str
close()或使用with处理文件对象实现自动关闭
3.8 错误与异常
错误:语法上的错误;
异常:运行时检测到的错误
try:
raise BException() # 抛出异常
except (BException, DException) as e:
print("D")
except:
print("处理全部其它异常") # 处理全部其它异常
else:
print("没有异常发生") # 只在try语句里没有触发异常时执行
finally:
print("你们绕不过我,必须执行") # 有无异常都要执行,可用于清理工作
4.python标准库
python标准库包含内置模块(用C编写)以及用python编写的模块。熟悉后,大多数问题都可以简单快捷地使用它们来解决。
OS模块
包含很多与操作系统、文件目录等相关的函数
os.system() # 用来运行shell命令
os.system(cmd) # 利用系统调用运行cmd命令
os.getcwd() # 获取当前目录
os.listdir() # 获取某个目录下的所有文件名
os.remove() # 删除某文件
os.path.isfile() 或 os.path.isdir() # 判断是文件/文件夹
……
shutil模块:高级的文件、文件夹、压缩包处理模块。
sys模块:最常用的和python解释器交互的模块,提供了许多函数和变量来处理Python运行时环境的不同部分。
re模块:为高级字符串处理提供了正则表达式工具。
数学
math模块:与数学的计算、应用相关,提供了对浮点数学的底层函数访问;
random模块:提供了进行随机选择的工具;
statistics模块:计算数值数据的基本统计属性(均值、中位数、方差等)。
互联网访问
如urlib.request用于从URL检索数据;
smtplib用于发送邮件
datetime模块:提供了操作日期和时间的类。
数据压缩:由模块直接支持,包括zlib,gzip,bz2,lzma,zipfile和tarfile。
质量控制
doctest模块:提供了一个工具,用于扫描模块并验证程序文档字符串中嵌入的测试;
unittest:单元测试框架,支持自动化、配置共享和关机代码测试。
高级编程常用模块
reprlib模块:提供了一个定制化版本的repr()函数,用于缩略显示大型或深层嵌套的容器对象,将容器中的对象按照一定的规律输出;
textwrap模块:格式化文本段落,以适应给定的屏幕宽度;
logging模块:提供功能齐全且灵活的日志记录系统;
array模块:提供了类似列表的array()对象,但只能存储类型一致的数据且存储密集更高;
……
5.python底层原理
5.1 python垃圾回收机制
python程序运行过程中创建的各种变量存在于内存中,需要被进行有效合理的管理,这涉及到Python的垃圾回收机制。目前较通用的解决办法有三种:引用计数、标记清除、分代回收。
引用计数
在python中的大多数对象的生命周期都是通过对象的引用计数来管理的。python为每个对象维护一个ref
字段来记录对象被引用的次数,当对象被创建或引用时将该对象的引用次数+1,当对象的引用被销毁时将引用次数-1,减到0时说明程序中没有任何对象持有该对象的引用了,其所占用的空间就可以被释放了。
引用次数+1 | 引用次数-1 |
---|---|
对象被创建 | 对象的别名被显示销毁 |
对象被引用 | 对象的别名被赋予新的对象 |
对象作为参数传递到函数内部 | 对象离开它的作用域 |
对象作为一个元素添加到容器中 | 从容器中删除对象,或容器被销毁 |
为解决对象交叉引用的问题,python引入了标记清除算法和分代回收算法。
标记清除
标记清除算法是一种基于对象可达性分析的回收算法,分为两个步骤:
标记(将所有活动对象即可达对象进行标记)和清除(将未标记的对象清除)。主要用来处理一些容器对象,由于需要扫描整个堆的所有对象,因此性能损耗较大。
分代回收
将系统中存活时间不同的对象划分到不同的内存区域,共0、1、2这三代。新生成的对象是0代,经过一次垃圾回收后,仍然存活的对象会升级到1代,以此类推。
由于交叉引用的存在,以及程序中使用了长时间存活的对象,这就造成了新生成的对象的数量会大于被回收的对象数量,一旦二者之间的差值达到某个阈值就会启动垃圾回收机制,使用标记清除算法将死亡对象进行清除,同时将存活对象移动到 1 代。以此类推,当二者的差值再次达到阈值时又触发垃圾回收机制,将存活对象移动到 2 代。
5.2 值传递与引用传递
**值传递:**在参数传递过程中将实际参数的值复制一份传递给形式参数;
**引用传递:**值将实际参数的引用传递给形式参数,这样实参与形参就会指向同一块内存地址,如果对形参进行修改,那么实参也会一并改变。
a = 10 # 声明变量a
b = a # b也指向a,于是与a指向同一个对象10
a = a + 10 # a指向生成的新对象20,而b还是指向10
5.3 对象的比较与拷贝
比较:==
与is
python中一切皆对象,而对象包括id(唯一身份标识)、type(类型)、value(值)三个要素。is是判断两个对象是否是同一个对象(id),是判断两个对象的值是否相等(value),is的效率优于。
拷贝:浅拷贝与深拷贝
对象的拷贝其实就是创建新的对象,当顶层对象和它的子元素对象全都是不可变对象时,不存在被拷贝,因为没有产生新对象。
浅拷贝只拷贝顶层对象,而不会去拷贝内部的子元素对象;深拷贝则会递归地拷贝顶层对象内部的子元素对象。