- 编程是一种技能和工具,是理解计算机的有效途径,是一种新的思考方式。
特点
- 语法简洁
- 类库丰富
- 跨平台
- 可拓展
- 开源
历史
- 1990,诞生
- 2000,2.0发布
- 2008,3.0发布
- 2010,2的最后一个版本2.7
数据类型
- 整型:int 8
- 浮点型:float 8.5
- 字符:str "6"
- 布尔型:bool true false
数据类型操作
- type():查看数据类型
- 相同数据类型的数据才可以一起操作,例:"6"必须先转换成整型或浮点型才可以进行计算
序列
定义
它的成员都是有序排列,并且可以通过下标偏移量访问它的成员。
范围
- 字符串 "abc"
- 列表 [4,6,7] 成员可以变更
- 元组 ("234", "hi") 成员不可变更
序列基本操作
- 成员关系操作符:对象(in, not in)序列
- 连接操作符:序列 + 序列
- 重复操作符:序列 * 整数
- 切片操作符:序列[开始下标:结束下标]
# 下标从0开始,包含开头,不包含结尾
# 格式:序列[开始下标:结束下标]
a = [4,6,7]
a[1] # 结果为:6
a[1:2] # 结果为:[6]
列表基本操作
- 添加元素,添加到最后面
list.append("x")
- 删除元素,删除最前面的一个元素
list.remove("x")
字典{}
- 以键值对的形式出现,key会被进行hash运算存起来所以key不能重复,
- 类型int float string tuple都可以进行hash运算可以作为key。
- 查询使用 get,如果查询的值不存在,我们也可以给一个默认值,比如 score.get(‘yase’,99)。
集合{}
- 集合(set)是一个无序的不重复元素序列。
- 可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
s = set(['a', 'b', 'c'])
条件语句if
if 条件:
执行语句
elif 条件:
执行语句
else:
执行语句
循环语句while
while 条件:
执行语句
循环语句for
for 迭代变量 in 可迭代对象:
执行语句
映射类型:字典{}
- 以键值对的形式出现
文件操作
错误≠异常
迭代器
- 迭代是Python最强大的功能之一,是访问集合元素的一种方式。
- 迭代器是一个可以记住遍历的位置的对象。
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
- 迭代器有两个基本的方法:iter() 和 next()。
- 字符串,列表或元组对象都可用于创建迭代器:
生成器
- 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
- 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
a,b=b,a+b 和 a=b b=a+b 的区别
a,b=0,1
a, b = b, a+b
# 这种赋值,先计算等值 右边 就是 b=1 a+b=1
# 再赋值给a和b,那么 a=1, b=1
#然后就是依次这样
a = b
# 此时 b=1, 那么a=1
b = a+b
# 那么 b=2
匿名函数lambda
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
一个语法
- lambda的语法是唯一的
lambda argument_list: expression
三个特性
- lambda函数是匿名的:所谓匿名函数,通俗地说就是没有名字的函数。lambda函数没有名字。
- lambda函数有输入和输出:输入是传入到参数列表argument_list的值,输出是根据表达式expression计算得到的值。
- lambda函数一般功能简单:单行expression决定了lambda函数不可能完成复杂的逻辑,只能完成非常简单的功能。由于其实现的功能一目了然,甚至不需要专门的名字来说明。
四个用法
- 将lambda函数赋值给一个变量,通过这个变量间接调用该lambda函数。
- 将lambda函数赋值给其他函数,从而将其他函数用该lambda函数替换。
- 将lambda函数作为其他函数的返回值,返回给调用者。
- 将lambda函数作为参数传递给其他函数。
一个争议
- 关于lambda在Python社区是存在争议的
- 支持方认为使用lambda编写的代码更紧凑,更“pythonic”。
- 反对方认为,lambda函数能够支持的功能十分有限,其不支持多分支程序if...elif...else...和异常处理程序try ...except...。并且,lambda函数的功能被隐藏,对于编写代码之外的人员来说,理解lambda代码需要耗费一定的理解成本。他们认为,使用for循环等来替代lambda是一种更加直白的编码风格。
内建函数
filter()
- filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。
- 该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
filter(function, iterable)
# function -- 判断函数。
# iterable -- 可迭代对象。
# 返回一个迭代器对象
def is_odd(n):
return n % 2 == 1
tmplist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
newlist = list(tmplist)
print(newlist)
# 结果为:[1, 3, 5, 7, 9]
map()
- map() 会根据提供的函数对指定序列做映射。
- 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
map(function, iterable, ...)
# function -- 函数
# iterable -- 一个或多个序列
# Python 2.x 返回列表。
# Python 3.x 返回迭代器。
# 使用 lambda 匿名函数
map(lambda x: x ** 2, [1, 2, 3, 4, 5])
# [1, 4, 9, 16, 25]
# 提供了两个列表,对相同位置的列表数据进行相加
map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
# [3, 7, 11, 15, 19]
reduce()
- reduce() 函数会对参数序列中元素进行累积。
- 函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
- 在 Python3 中,reduce() 函数已经被从全局名字空间里移除了,它现在被放置在 functools 模块里,如果想要使用它,则需要通过引入 functools 模块来调用 reduce() 函数:
reduce(function, iterable[, initializer])
# function -- 函数,有两个参数
# iterable -- 可迭代对象
# initializer -- 可选,初始参数
from functools import reduce
def add(x,y):
return x + y
print (reduce(add, range(1, 3)), 4)
# 10
zip()
- zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
- 我们可以使用 list() 转换来输出列表。
- 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
zip([iterable, ...])
# iterabl -- 一个或多个迭代器;
# python3返回的是对象,python2返回的是列表
z = zip([1,2,3],[4,5,6])
print(list(z))
# [(1, 4), (2, 5), (3, 6)]
闭包
- 形成闭包的条件
- 必须要有一个内嵌函数
- 内嵌函数中要对自由变量的引用
- 外部函数必须返回内嵌函数
# a * x + b = y
def line(a,b):
def arg_x(x):
return a * x + b
return arg_x
a_line = line(2,5)
print(a_line(1))
# 7
装饰器
- 从字面上理解,就是装饰对象的器件。可以在不修改原有代码的情况下,为被装饰的对象增加新的功能或者附加限制条件或者帮助输出。装饰器有很多种,有函数的装饰器,也有类的装饰器。装饰器在很多语言中的名字也不尽相同,它体现的是设计模式中的装饰模式,强调的是开放封闭原则。装饰器的语法是将@装饰器名,放在被装饰对象上面。
import time
def timer(func):
def wrapper():
start_time = time.time()
func()
stop_time = time.time()
print(stop_time-start_time)
return wrapper
# 装饰器
@timer
def i_can_sleep():
time.sleep(2)
i_can_sleep()
函数的基本概念
- 函数名:foo、outer、inner
- 函数体:函数的整个代码结构
- 返回值:return后面的表达式
- 函数的内存地址:id(foo)、id(outer)等
- 函数名加括号:对函数进行调用,如foo()、outer(foo)
- 函数名作为参数:outer(foo)中foo本身是一个函数,但作为参数传递给了outer函数
- 函数名加括号作为参数:先调用函数,再将它的返回值当做别的函数的参数,例如outer(foo())
- 返回函数名:return inner
- 返回函数名加括号:return inner(),其实就是先执行inner()函数,再将其返回值作为别的函数的返回值。
上下文管理器
- 用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。它的语法形式是with...as...
- 上下文管理器协议:是指类需要实现 __ enter __ 和 __ exit __ 方法。
- 就跟迭代器有迭代器协议一样,迭代器协议需要实现 __ iter __ 和 __ next __ 方法。
- 上下文管理器,也就是支持上下文管理协议的对象,简单点讲就是,实现了 __ enter __ 和 __ exit __两个方法的类。这个类也叫做,上下文管理器的类。
class Resource():
def __enter__(self):
print('===connect to resource===')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('===close resource connection===')
def operate(self):
print('===in operation===')
with Resource() as res:
res.operate()
输出:
===connect to resource===
===in operation===
===close resource connection===
面向对象
-
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
-
方法:类中定义的函数。
-
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
-
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
-
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
-
局部变量:定义在方法中的变量,只作用于当前实例的类。
-
实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
-
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
-
实例化:创建一个类的实例,类的具体对象。
-
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
-
两个下划线“__”开头的属性和方法是私有的
-
__init__ 是 构造方法
继承
- 子类继承父类的属性和方法,可以继承多个,当多个父类有相同方法时,默认从左向右取第一个父类的方法
class Test:
def prt(self):
print(1)
class Test2:
def prt(self):
print(2)
class Test3(Test, Test2):
def __init__(self):
print(3)
t = Test3()
t.prt()
# 3 1
多线程
- 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
- 每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
- 指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
import threading
import time
from threading import current_thread
def my_thread(arg1, arg2):
print(current_thread().getName(), "start")
print("%s %s" % (arg1, arg2))
time.sleep(2)
print(current_thread().getName(), "stop")
for i in range(1,6,1):
t1 = threading.Thread(target=my_thread, args=(i, i+1))
t1.start()
print(current_thread().getName(), "end")
Thread-1 start
# 1 2
# Thread-2 start
# 2 3
# Thread-3 start
# 3 4
# Thread-4 start
# 4 5
# Thread-5 start
# MainThread end
# 5 6
# Thread-4 stop
# Thread-3 stop
# Thread-1 stop
# Thread-2 stop
# Thread-5 stop
正则表达式
- 正则前面加上 r 表示规则不被转译
- re.compile() 设置匹配规则
- re.match()是从开头开始匹配,开头不符合直接返回None
- re.search()是匹配整个字符串,有一个符合的就返回,没有一个符合的返回None
- re.findall()是匹配整个字符串,返回所有符合的字符串组成的列表
- re.sub()是替换字符串
Python是如何进行内存管理的
- 对象的引用计数机制
- Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
引用计数增加的情况: - 一个对象分配一个新名称
- 将其放入一个容器中(如列表、元组或字典)
引用计数减少的情况: - 使用del语句对对象别名显示的销毁
- 引用超出作用域或被重新赋值
-
垃圾回收
当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。 -
内存池机制
- Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统:
- Pymalloc机制:为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
- 对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
Numpy
- NumPy 数组存储在一个均匀连续的内存块中,不需要对内存地址进行查找;而列表 list 的元素在系统内存中是分散存储的,需要对内存地址进行查找。
- 在内存访问模式中,缓存会直接把字节块从 RAM 加载到 CPU 寄存器中。因为数据连续的存储在内存中,NumPy 直接利用现代 CPU 的矢量化指令计算,加载寄存器中的多个连续浮点数。
- NumPy 中的矩阵计算可以采用多线程的方式,充分利用多核 CPU 计算资源,大大提升了计算效率。
- 提升内存和提高计算资源的利用率:避免采用隐式拷贝,而是采用就地操作的方式。
网友评论