ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python基础知识

2022-05-25 18:01:18  阅读:150  来源: 互联网

标签:__ 函数 迭代 Python list 基础知识 func print


函数式编程

定义

所谓函数式编程,是指代码中每一块都是不可变的(immutable),都由纯函数(pure function)的形式组成。这里的纯函数,是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出,没有任何副作用。

def multiply_2(l):
    for index in range(0, len(l)):
        l[index] *= 2
    return l

这段代码就不是一个纯函数的形式,因为列表中元素的值被改变了,如果多次调用 multiply_2() 这个函数,那么每次得到的结果都不一样。

要想让它成为一个纯函数的形式,就得写成下面这种形式,重新创建一个新的列表并返回。

def multiply_2_pure(l):
    new_list = []
    for item in l:
        new_list.append(item * 2)
    return new_list

优点:其纯函数和不可变的特性使程序更加健壮,易于调试(debug)和测试;
缺点:限制多,难写。

Python 主要提供三个函数:map()、filter() 和 reduce(),通常结合匿名函数 lambda 一起使用。

map()

函数 map(function, iterable) 的第一个参数是函数对象,第二个参数是一个可以遍历的集合

作用:对 iterable 的每一个元素,都运用 function 这个函数。

l = [1, 2, 3, 4, 5]
new_list = map(lambda x: x * 2, l) # [2, 4, 6, 8, 10]
print(type(new_list))
print(list(new_list))
 
# 输出
<class 'map'>
[2, 4, 6, 8, 10]

filter()

filter(function, iterable) 函数,和 map 函数类似,function 同样表示一个函数对象。

作用:对 iterable 中的每个元素,都使用 function 判断,并返回 True 或者 False,最后将返回 True 的元素组成一个新的可遍历的集合。

l = [1, 2, 3, 4, 5]
new_list = filter(lambda x: x % 2 == 0, l) # [2, 4]
print(type(new_list))
print(list(new_list))

# 输出
<class 'filter'>
[2, 4]

reduce()

reduce(function, iterable) 函数,它通常用来对一个集合做一些累积操作。

作用:function 有两个参数,表示对 iterable 中的每个元素以及上一次调用后的结果,运用 function 进行计算,所以最后返回的是一个单独的数值

from functools import reduce
l = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, l) # 1*2*3*4*5 = 120
print(type(product))
print(product)

# 输出
<class 'int'>
120

迭代器、生成器、装饰器

迭代器

从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值)

可迭代对象(iterable):是指该对象可以被用于for…in…循环,例如:集合,列表,元祖,字典,字符串,迭代器等。

  • 在python中如果一个对象实现了 __iter__方法,我们就称之为可迭代对象,可以查看set\list\tuple…等源码内部均实现了__iter__方法
  • 如果一个对象未实现__iter__方法,但是对其使用for…in则会抛出TypeError: ‘xxx’ object is not iterable
  • 可以通过isinstance(obj,Iterable)来判断对象是否为可迭代对象。如:
from collections.abc import Iterable
a: int = 1
print(isinstance(a, Iterable))  # False
b: str = "lalalalala" 
print(isinstance(b, Iterable))  # True
c: set = set([1, 2])
print(isinstance(c, Iterable))  # True

迭代器:对可迭代对象进行迭代的方式或容器,并且需要记录当前迭代进行到的位置。

  • 在python中如果一个对象同时实现了__iter__和__next__(获取下一个值)方法,那么它就是一个迭代器对象。
  • 可以通过内置函数next(iterator)或实例对象的__next__()方法,来获取当前迭代的值
  • 迭代器一定是可迭代对象,可迭代对象不一定是迭代器。
  • 如果可迭代对象遍历完后继续调用next(),则会抛出:StopIteration异常。

自己实现一个迭代器对象:

from collections.abc import Iterator, Iterable

class MyIterator:
	def __init__(self, array_list):
		self.array_list = array_list
		self.index = 0

	def __iter__(self):
		return self

	def __next__(self):
		if self.index < len(self.array_list):
			val = self.array_list[self.index]
			self.index += 1
			return val
		else:
			raise StopIteration

# 父类如果是迭代器,子类也将是迭代器
class MySubIterator(MyIterator):
	def __init__(self):
		pass


myIterator = MyIterator([1, 2, 3, 4])
# 判断是否为可迭代对象
print(isinstance(myIterator, Iterable))  # True
# 判断是否为迭代器
print(isinstance(myIterator, Iterator))  # True
# 子类实例化
mySubIterator = MySubIterator()
print(isinstance(mySubIterator, Iterator))  # True
# 进行迭代
print(next(myIterator))  # 1
print(myIterator.__next__())  # 2
print(next(myIterator))  # 3
print(next(myIterator))  # 4
print(next(myIterator))  # raise StopIteration
  • 优点:迭代器对象表示的是一个数据流,可以在需要时才去调用next来获取一个值;因而本身在内存中始终只保留一个值,对于内存占用小可以存放无限数据流。优于其他容器需要一次将所有元素都存放进内存,如:列表、集合、字典...等
  • 缺点:1.无法获取存放的元素长度,除非取完计数。2.取值不灵活,只能向后取值,next()永远返回的是下一个值;无法取出指定值(无法像字典的key,或列表的下标),而且迭代器对象的生命周期是一次性的,元素被迭代完则生命周期结束。

生成器

一边循环一边计算的机制,称为生成器:generator;同时生成器对象也是迭代器对象,所以他有迭代器的特性;例如支持for循环、next()方法…等
作用:对象中的元素是按照某种算法推算出来的,在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。

简单生成器:通过将列表生成式[]改成()即可得到一个生成器对象

# 列表生成式
_list = [i for i in range(10)]
print(type(_list))  # <class 'list'>
print(_list)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 生成器
_generator = (i for i in range(10))
print(type(_generator))  # <class 'generator'>
print(_generator)  # <generator object <genexpr> at 0x7fbcd92c9ba0>
# 生成器对象取值
print(_generator.__next__())  # 0
print(next(_generator)) # 1
# 注意从第三个元素开始了!
for x in _generator:
	print(x)  # 2,3,4,5,6,7,8,9

含有yield指令的函数可以称为生成器,它可以将函数执行对象转化为可迭代的对象。这样就可以像debug一样一步一步推进函数。可以实现让函数内部暂停,实现了程序的异步功能,这样可以及进行该函数与外部构件的信息交互,实现了系统的解耦。

装饰器

对象引用 :对象名仅仅只是个绑定内存地址的变量

def func():   # 函数名仅仅只是个绑定内存地址的变量       
	print("i`m running") 
                     
# 这是调用                       
func()  # i`m running
# 这是对象引用,引用的是内存地址        
func2 = func  
print(func2 is func)  # True
# 通过引用进行调用  
func2()  # i`m running

闭包:定义一个函数A,然后在该函数内部再定义一个函数B,并且B函数用到了外边A函数的变量

def out_func():
	out_a = 10

	def inner_func(inner_x):
		return out_a + inner_x

	return inner_func


out = out_func()
print(out)  # <function out_func.<locals>.inner_func at 0x7ff378af5c10> out_func返回的是inner_func的内存地址
print(out(inner_x=2))  # 12

装饰器和闭包不同点在于:装饰器的入参是函数对象,闭包入参是普通数据对象

def decorator_get_function_name(func):
	"""
	获取正在运行函数名
	:return:
	"""

	def wrapper(*arg):
		"""
		wrapper
		:param arg:
		:return:
		"""
		print(f"当前运行方法名:{func.__name__}  with  params: {arg}")
		return func(*arg)

	return wrapper

# @func_name是python的语法糖
@decorator_get_function_name 
def test_func_add(x, y):
	print(x + y)


def test_func_sub(x, y):
	print(x - y)


test_func_add(1, 2)
# 输出:
# 当前运行方法名:test_func_add  with  params: (1, 2)
# 3
# 不使用语法糖的话也可以用以下方法,效果是一样的
decorator_get_function_name(test_func_sub)(3, 5)
# 还记得前文讲的引用吗?我们还可以换种写法达到跟

标签:__,函数,迭代,Python,list,基础知识,func,print
来源: https://www.cnblogs.com/ttyangY77/p/16310185.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有