python3基础

  • 编程是一种技能和工具,是理解计算机的有效途径,是一种新的思考方式。

特点

  • 语法简洁
  • 类库丰富
  • 跨平台
  • 可拓展
  • 开源

历史

  • 1990,诞生
  • 2000,2.0发布
  • 2008,3.0发布
  • 2010,2的最后一个版本2.7

数据类型

  1. 整型:int 8
  2. 浮点型:float 8.5
  3. 字符:str “6”
  4. 布尔型:bool true false
数据类型操作
  • type():查看数据类型
  • 相同数据类型的数据才可以一起操作,例:"6"必须先转换成整型或浮点型才可以进行计算

序列

定义

它的成员都是有序排列,并且可以通过下标偏移量访问它的成员。

范围
  1. 字符串 “abc”
  2. 列表 [4,6,7] 成员可以变更
  3. 元组 (“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
三个特性
  1. lambda函数是匿名的:所谓匿名函数,通俗地说就是没有名字的函数。lambda函数没有名字。
  2. lambda函数有输入和输出:输入是传入到参数列表argument_list的值,输出是根据表达式expression计算得到的值。
  3. lambda函数一般功能简单:单行expression决定了lambda函数不可能完成复杂的逻辑,只能完成非常简单的功能。由于其实现的功能一目了然,甚至不需要专门的名字来说明。
四个用法
  1. 将lambda函数赋值给一个变量,通过这个变量间接调用该lambda函数。
  2. 将lambda函数赋值给其他函数,从而将其他函数用该lambda函数替换。
  3. 将lambda函数作为其他函数的返回值,返回给调用者。
  4. 将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)]

闭包

  • 形成闭包的条件
  1. 必须要有一个内嵌函数
  2. 内嵌函数中要对自由变量的引用
  3. 外部函数必须返回内嵌函数
# 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是如何进行内存管理的

  1. 对象的引用计数机制
  • Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
    引用计数增加的情况:
  • 一个对象分配一个新名称
  • 将其放入一个容器中(如列表、元组或字典)
    引用计数减少的情况:
  • 使用del语句对对象别名显示的销毁
  • 引用超出作用域或被重新赋值
  1. 垃圾回收
    当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。

  2. 内存池机制

  • Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统:
  • Pymalloc机制:为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
  • 对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

Numpy

  • NumPy 数组存储在一个均匀连续的内存块中,不需要对内存地址进行查找;而列表 list 的元素在系统内存中是分散存储的,需要对内存地址进行查找。
  • 在内存访问模式中,缓存会直接把字节块从 RAM 加载到 CPU 寄存器中。因为数据连续的存储在内存中,NumPy 直接利用现代 CPU 的矢量化指令计算,加载寄存器中的多个连续浮点数。
  • NumPy 中的矩阵计算可以采用多线程的方式,充分利用多核 CPU 计算资源,大大提升了计算效率。
  • 提升内存和提高计算资源的利用率:避免采用隐式拷贝,而是采用就地操作的方式。
评论