Python进阶(迭代,函数式编程,Collections类)

PYTHON进阶

PYTHON迭代

@生成器(Generator)

列表生成器产生的列表很占用内存空间,我们每次在计算使用的时候都是对单个元素进行操作,这样其它元素占用的空间就白白浪费了。所以如果列表内的元素可以按照某种算法推算出来,这样我们就可以在循环过程中不断的推算下一个元素(一次只推算一个),从而避免创建完整的列表而占用大量内存。
在Python中我们把一边循环一边计算的机制称为生成器:generator.

生成器创建的语法

列表生成器中括号[]包裹改为小括号()包裹

# 列表生成器
data = [x + 1 for x in range(0, 10)]
print(data)             # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 生成器
g = (x * x for x in range(10))
print(g)                # <generator object <genexpr> at 0x10a4d6318>

生成器的遍历

使用生成器的元素也很简单,直接循环打印出即可

注意:生成器创建完了,只能消费一次。也就是说当遍历过一次后,第二次再遍历时,列表已经为空了

# 使用for循环
for i in g:
    print(i)

# 直接使用list打印输出
g = (x for x in range(10))
list(g)                         # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

也可以调用Next函数直到计算出最后一个元素位置,但是这种方法很明显不适用,并且最后会抛出StopIteration的错误

g = (x * x for x in range(10))
next(g)                         # 逐个输出元素,遍历完后会抛出StopIteration异常

所以我们创建一个generator后,基本上永远不会调用next(),而是通过for循环来迭代,并且不需要关心StopIteration的错误,generator非常强大,如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

@迭代器

什么是可迭代对象(Iterable)?

可用于for循环的对象统称为可迭代对象:Iterable。比如之前学习的集合数据类型,list,tuple,dict, set, str等;还有上面介绍的生成器也是可迭代对象。

什么是迭代器(Iterator)?

可以被next()函数调用并不断返回下一个值的对象称为迭代器。比如生成器就是迭代器的一种,但list、dict、str,却不是Iterator。什么机制咧?迭代器属于未知长度的数据流,惰性序列(只管下一个),

from collections.abc import Iterable,Iterator
a = [1,2,3,4]
g = (i for i in range(10))
isinstance(a, Iterable)             # True
isinstance(a, Iterator)             # False
isinstance(g, Iterator)             # True

# iter方法可以将生成器转化为迭代器
next(iter(a))                           # 1

函数式编程

@高阶函数

变量可以指向函数,函数名也是变量,函数名就是指向函数的变量,比如对于len()这个函数来说,我们可以把len看做是变量

传入函数,既然变量可以指向函数,函数可以接受变量,那么一个函数就可以接受另一个函数作为传入参数

x = len
x([i for i in range(5)])                # 5

def add(x, y, z):
    return z(x) + z(y)
add([1,2,3,4], [4,3,1,5,6], max)        # 10

@map/reduce

map接收两个参数,一个是函数,一个是可迭代对象(Iterable),函数作用在序列的每一个元素上。

map函数返回的依然是可迭代对象(Iterable)。

# 将下面的序列元素与自身相乘
map(lambda x: x * x, [1, 2, 3])
# 别忘记之前通过list包裹可迭代对象的例子
list(map(lambda x: x * x, [1, 2, 3]))   # [1, 4, 9]

reduce同样也是接收两个参数,一个是函数,一个是可迭代对象(Iterable),不过这个函数必须接受两个参数,reduce把计算结果继续与下一个元素累积计算

reduce函数返回的是最终的计算结果。

from functools import reduce
reduce(lambda a,b: a+b, [1,2,3,4,5])        # 15

@filter函数

filter同样也是接收两个参数,一个是函数,一个是可迭代对象(Iterable),不过该函数返回的结果必须是布尔型,filter根据true或者false进行元素的保留和删除

filter函数返回的依然是可迭代对象(Iterable)。

# 对下列数据只保留能被2整除的数
list(filter(lambda x: x % 2 == 0, [1,2,3,4,5]))    # [2, 4]

@匿名函数 Lambda

我们可以不用显示的定义函数名,因此可以使用匿名函数。

匿名函数可以被一个变量保存,也可以不保存直接使用。

# 用变量保存
f = lambda x : x * 2
list(map(f, [1,2,3]))                     # [2, 4, 6]

# 直接使用
list(map(lambda x: x * 2, [1, 2, 3]))     # [2, 4, 6]

@三元运算

  • [true] if [expression] else [false]
print("成年人") if 24 > 18 else print("未成年人")
list(map(lambda x: x ** 2 if x % 2 == 0 else x, [1,2,3,4,5]))

Collections类

@deque

deque和list的用法比较类似,它是队列(先进先出)与栈(先进后出)的实现,可以对有序序列数据进行两端的操作。

deque支持在O(1)的时间复杂度上对序列进行两端的append或者pop。list也可以实现同样的操作,但是它的复杂度是O(N).

from collections import deque

# 创建
d = deque([1,2,3])

# 添加
d.append(4)                 # deque([1, 2, 3, 4])
d.appendleft(0)             # deque([0, 1, 2, 3, 4])

# 删除
d.pop()                     # deque([0, 1, 2, 3])
d.popleft()                 # deque([1, 2, 3])

# 旋转
d.rotate(2)                 # deque([2, 3, 1])

通过魔法函数timeit计算时间,比较list和deque在左侧插入数据的效率

list_a = [x for x in range(1,1000000)]
deque_a = deque(list_a)
%timeit list_a.insert(0, 'a')
%timeit deque_a.appendleft('a')

执行

1.72 ms ± 196 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
234 ns ± 16.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

@Counter与OrderedDict

Counter

A Counter is a dict subclass for counting hashable objects. It is an unordered collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts.

from collections import Counter

# 创建
a = list('Jeff')
c = Counter(a)                      # Counter({'J': 1, 'e': 1, 'f': 2})

# 遍历,子类具有父类的全部属性和方法
for k, v in c.items():
    print(k, v)

# 查看Top1的元素
c.most_common(1)                    # [('f', 2)]

OrderedDict

与Counter类似,只不过OrderedDict是有序的,而Counter是无序的

from collections import OrderedDict

# unsorted dictionary
d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

# sorted by key
OrderedDict(sorted(d.items(), key=lambda t: t[0]))

# sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))

# sorted by length of the key string
OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))

r.popitem(last=False)           # ('pear', 1)

字符串处理

@常见处理方法

s = " Hello, World "
len(s)
s.split(' ')
s.lstrip()

# 查找和替换
s.endswith(" ")
s.startswith(" ")
s.find("ll")
s.replace("World", 'Tomorrow')

# 去空格转成大写并按逗号分隔
list(map(lambda t: t.strip(), s.strip().upper().split(",")))    # ['HELLO', 'WORLD']

@格式化

t = '五'
a = 3.1415
print("星期%s" %t)                            # 星期五
# 保留2位小数
print("pi是%.2f" %a)                         # pi是3.14

# format写法(推荐这样写)
a = '2019-12-12'
b = '10'
print("{0}的温度是{1}度".format(a, b))        # 2019-12-12的温度是10度

时间类:datetime

datime模块是专门用于处理时间的类,它是PYTHON的标准库之一,内容复杂且强大,这里只涉及一些常用的函数:

  • 获取时间
  • 字符串与时间的转换
  • 时间的提取
  • 日期之间的计算
# 获取时间
from datetime import datetime
print(datetime.now())                       # 2019-12-13 21:32:25.754216
# 创建指定的时间
dt = datetime(2019, 12, 13, 20, 11)         # 2019-12-13 20:11:00
print(dt)

# 字符串与时间的转换
s1 = '20170901'
s1 = datetime.strptime(s1, '%Y%m%d')
s2 = "2019/05/03"
s2 = datetime.strptime(s2, '%Y/%m/%d')
s3 = "2019-09-17 20"
s3 = datetime.strptime(s3, '%Y-%m-%d %H')

# 时间的提取
dt.date()
datetime.now().date()                       # datetime.date(2019, 12, 13)
# 属性year,month,day,hour,minute,second
dt.year                                     # 2019

# 日期间的计算
from datetime import datetime, timedelta
print(s3 - s1)                                               # 746 days, 20:00:00
s3 - timedelta(days=1, seconds=86400, hours=12, minutes=60)  # datetime.datetime(2019, 9, 15, 7, 0)

I/O

@读文件

我们的数据一般都是存在文件里的,需要通过程序将文件加载到Python环境中,这样才可以使用python对其进行分析。
PYTHON标准库提供了一些标准的实现,我们一起来看一下。

读文件需要使用 open()函数,其参数为文件名与标识符:

f = open("test2.txt", 'r', encoding="gbk")  # 指定文件编码和模式
data = f.readline()
f.close()
print(data)

‘r‘表示读文件的意思,在获取文件之后,使用read函数读取数据,最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源。但是每次这样写很麻烦,我们可以使用with关键词进行整合:

with open("test2.txt", 'r', encoding="gbk") as handle:
    data = handle.readlines()
print(data)                             # ['hello world\n', '\n', 'Today is 星期二']

list(map(lambda s : s.strip(),data))    # ['hello world', '', 'Today is 星期二']

@写文件

写文件和读文件几乎一致,唯一的区别是标识符需要改为"w"。

第一个实参也是要打开的文件的名称;
第二个实参(‘w‘)告诉Python,我们要以写入模式打开这个文件。打开文件时,可指定读取模式(‘r‘)、 写入模式(‘w‘)、 附加模式(‘a‘)或是让你能够读取和写入文件的模式(‘r+‘)。如果
你省略了模式实参, Python将以默认的只读模式打开文件

with open("test2.txt",'w') as handle:
    handle.write("hello world\n")           # 注意,这里手动添加了换行符
    handle.write(" And fate")

如果你要写入的文件不存在,函数open()将自动创建它。然而,以写入(‘w‘)模式打开文件时千万要小心,因为如果指定的文件已经存在, Python将在返回文件对象前清空该文件。

附加到文件

如果你要给文件添加内容,而不是覆盖原有的内容,可以以附加模式打开文件。你以附加模式打开文件时, Python不会在返回文件对象前清空文件,你写入到文件的行都将添加到文件末尾。如果指定的文件不存在,Python将为你创建一个空文件。

with open("test.txt",'a') as handle:
    handle.write("Today is Nice!\n")
    handle.write("We are happy!!\n")

异常处理

Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码(即捕获),程序将继续运行;如果你未对异常进行处理(未捕获),程序将停止,并显示一个traceback,其中包含有关异常的报告。

异常是使用try-except代码块处理的。try-except代码块让Python在执行指定的操作时,一旦发生了异常知道该怎么办。使用了try-except代码块时,即便出现异常,程序也将继续运行: 显示你编写的友好的错误消息,而不是令用户迷惑的traceback。

while True:
    first_number = input("First Number: ")
    if first_number == 'q':
        break
    second_number = input("Second Number: ")
    if second_number == 'q':
        break
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError as e:
        print(" 除数不可以为0!!")
    print(answer)

执行

First Number: 10
Second Number: 2
5.0
First Number: 3
Second Number: 5
0.6
First Number: 10
Second Number: 0
 除数不可以为0!!

多个异常

some_list = [1, 2, 3]
try:
    print(some_list[5])
    some_list.remove(4)
# except Exception as e:    # 也可以用Exception替代,不过不建议这样做
except (IndexError, ValueError) as e:   # 使用tuple封装多个异常类型
    print("Caught again!")
    print(e)

原文地址:https://www.cnblogs.com/wjf0/p/12040590.html

时间: 2024-11-01 13:34:05

Python进阶(迭代,函数式编程,Collections类)的相关文章

一、Python 进阶 之 函数式编程

Python 进阶 之 函数式编程 写在前面 入门阶段的系列笔记传送门 → 进这里 已经掌握了基础的内容如下: 变量和数据类型:Python 内置的基本类型 List 和 Tuple:顺序的集合类型 条件判断和循环:控制程序流程 Dict 和 Set:根据Key访问的集合类型 函数:定义和调用函数 切片:如何对 list 进行切片 迭代:如何用 for 循环迭代集合类型 列表生成式:如何快速生成列表 接下来我要学会: 函数式编程 如何使用 Python 的模块(内置模块和第三方模块) 面向对象编

Python进阶之函数式编程(把函数作为参数)

什么是函数式编程? 什么是函数式编程? 函数:function 函数式:functional,一种编程范式 函数式编程是一种抽象计算的编程模式 函数≠函数式,比如:计算≠计算机 在计算机当中,计算机硬件是最底层的,而越往上语言越高级 低--------------------------------->高计算机硬件-->汇编语言-->c语言-->Python语言 ↓ ↓ ↓ 指令 函数 函数式计算机------------------------>计算(数学) ○ 函数式编程

Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)...啊啊啊

函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. 而函数式编程(请注意多了一个"式"字)--Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算. 我们首先要搞明白计算机(Computer)和计算(Compute)的概念. 在计算机的层次上,CPU执行的是加减乘除的指令代码

【python进阶】详解元类及其应用2

前言 在上一篇文章[python进阶]详解元类及其应用1中,我们提到了关于元类的一些前置知识,介绍了类对象,动态创建类,使用type创建类,这一节我们将继续接着上文来讲~~~ 5.使?type创建带有?法的类 最终你会希望为你的类增加?法.只需要定义?个有着恰当签名的函数并将 其作为属性赋值就可以了.添加实例?法 In [14]: def echo_bar(self):#定义了一个普通的函数 ...: print(self.bar) ...: In [15]: FooChild = type('

Python函数以及函数式编程

本文和大家分享的主要是python 函数及函数式编程相关内容,一起来看看吧,希望对大家 学习python有所帮助. 函数基本语法及特性 定义 数学函数定义: 一般的,在一个变化过程中,如果有两个变量 x 和 y ,并且对于 x 的每一 个确定的值, y都有唯一确定的值与其对应,那么我们就把 x 称为自变量,把 y 称为因变 量, y 是 x 的函数.自变量 x 的取值范围叫做这个函数的定义域. 但编程中的「函数」概念,与数学中的函数是有很  同的  函数是逻辑结构化和过程化的一种编程方法 函数的

python 函数和函数式编程

什么是函数 调用函数 创建函数 传入函数 形参 变长参数 函数式编程 变量的作用域 递归 生成器 1 什么是函数 函数是对程序逻辑进行结构化或过程化的一种编程方法.能将整块代码巧妙地隔离成易于管理 的小块,把重复代码放到函数中而不是进行大量的拷贝--这样既能节省空间,也有助于保持一致性,因为你只需改变单个的拷贝而无须去寻找再修改大量复制代码的拷贝. 1.1 过程 vs 函数 在C++里我不记得有过程这种东西,但是在一些其它的语言比如PL/SQL里面会有过程.过程和函数一样是可以调用的代码块,但是

Python学习之函数式编程

本文和大家分享的主要是 python开发中函数式编程相关内容,一起来看看吧,希望对大家学习和使用这部分内容有所帮助. 1. python把函数作为参数 import math def  add(x, y, f): return f(x) + f(y) print add(-5, 9, abs) print abs(-5) + abs(9) print add(25, 9, math.sqrt) 2. python中map()函数 map() 是  Python  内置的高阶函数,它接收一个函数 

python中的函数式编程与装饰器

2.1 python中的函数式编程 函数式编码的特点 把计算视为函数而非指令 纯函数式编程,不需要变量,没有副作用,测试简单 支持高阶函数,代码简洁 python支持的函数式编程 不是纯函数式编码:允许有变量 支持高阶函数:函数也可以作为变量传入 支持闭包:有了闭包就能返回函数 有限度地支持匿名函数 2.2 python中高阶函数 函数名可以作为变量,如 高阶函数:只能接收函数作为参数的函数 变量可以是指向函数 函数的参数可以接收变量 一个函数可以接收另一个函数作为参数 能接收函数作为参数的函数

Python 进阶(五)定制类

__str__和__repr__ 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __str__(self): return '(Person: %s, %s)' % (self.name, self.gender) 现在,在交互式命令行下用 print 试试: >>>