1.列表推导式
列表推导式comprehensions(又称解析式),是Python的一种独有特性。列表解析式是将一个列表(实际上适用于任何可迭代对象)转换成另一个列表的工具。
可迭代对象:
- 集合数据类型,如 list、 tuple、 dict、 set、 str 等
- generator,包括生成器和带 yield 的 generator function
列表推导式
# 求列表的平方
li = [1,2,3,4,5,6,7,8]
square = [i**2 for i in li]
>>> print(square)
[1, 4, 9, 16, 25, 36, 49, 64]
# 如果想求大于4平方
square = [i**2 for i in li if i > 4]
>>> print(square)
[25, 36, 49, 64]
set推导式
列表推导式不只对列表,凡是能够迭代的对象都能使用列表推导式
li = [1,2,3,4,5,6,7,8]
s = {i**2 for i in li}
>>> print(s)
{1, 4, 9, 16, 25, 36, 49, 64}
示例
将下面的数据格式
[{'city': '北京北京', 'max_temp': '35', 'min_temp': '23'}, {'city': '北京海淀', 'max_temp': '36', 'min_temp': '23'}]
转换成:
[('北京北京', '35'), ('北京海淀', '36')]
这里就用列表推导式进行演示
li = [{'city': '北京北京', 'max_temp': '35', 'min_temp': '23'}, {'city': '北京海淀', 'max_temp': '36', 'min_temp': '23'}]
s = [(item['city'],item['max_temp']) for item in li]
>>> print(s)
[('北京北京', '35'), ('北京海淀', '36')]
2.iterator、generator
iterable
(可迭代对象):凡是能够被for in
来循环遍历的对象都是可迭代对象,如:列表、元组、集合
iterator
(迭代器):iterator对象在迭代过程中提供返回的值。它的next()或者__next__()方法用来产生这个值。迭代结尾它会产生StopIteration异常。iter函数为一个可迭代对象返回一个迭代器。如果给iter函数传入一个迭代器,它就直接返回那个迭代器。
自定义一个迭代器
class BookCollection:
def __init__(self):
self.data = ['《往事》','《只能》','《回味》']
self.curr = 0
def __iter__(self):
return self
def __next__(self):
if self.curr >= len(self.data):
#抛出一个异常
raise StopIteration()
r = self.data[self.curr]
self.curr += 1
return r
books = BookCollection()
for book in books
print(book)
#也可以通过next调用
print(next(books))
print(next(books))
迭代器有一个重要的特性,就是当第一次遍历完之后,第二次就不能在遍历
class BookCollection:
def __init__(self):
self.data = ['《往事》','《只能》','《回味》']
self.curr = 0
def __iter__(self):
return self
def __next__(self):
if self.curr >= len(self.data):
#抛出一个异常
raise StopIteration()
r = self.data[self.curr]
self.curr += 1
return r
books = BookCollection()
for book in books
print(book)
for book in books
print(book)
要想进行多次遍历,需要重新实例化一个新的对象 或者在遍历之前将原来的对象copy
books = BookCollection()
book1s = BookCollection()
for book in books
print(book)
for book in book1s
print(book)
#copy
import copy
books = BookCollection()
b = copy.copy(books)
for book in book1s
print(book)
for book in b
print(book)
generator
生成器函数允许您声明一个行为类似于迭代器的函数,即它可以在for循环中使用。
我们还是从一个简单的示例来了解什么是生成器?现在有个需求,想要一个0-10000的列表
n = [i for i in range(0,100001)]
上面代码虽然实现要求,但是有个问题,就是非常消耗内存,因为我们用一个列表将0-10000的数据存储起来。可以用生成器来解决这个问题:
def gen(max):
n = 0
while n <= max:
n += 1
yield n
g = gen(10000)
>>> type(g)
<class 'generator'>
#for in 变量
for i in g:
print(i)
用生成器的好处就是节省了内存空间,在gen
函数中只保存一段生成0-10000的算法而不是像n
列表保存的是数据。
3.None
python中None
就None,它不等同于空字符串、空列表、False、0。这里说的不等于是从类型
和值
上面来说的。
type(None)
<class 'NoneType'>
>>> '' == None
False
>>> [] == None
False
>>> False == None
False
判空
def func():
return None
def isNone(a):
if not a:
print('T')
else:
print('F')
if a is None:
print('T')
else:
print('F')
a = func()
isNone(a)
'T'
'T'
a = []
isNone(a)
'T'
'F'
建议大家用 if not a
来判断是不是空
4.对象存在不一定是True
在编写代码时候,初学者会认为一个对象存在,在if判断中就是True:
class Book:
pass
b = Book()
>>> print(bool(b))
True
上面代码最终输出的的确是True
,我们将上面代码简单修改下:
class Book:
def __bool__(self):
return False
b = Book()
>>> print(bool(b))
Fasle
或者:
class Book:
def __len__(self):
return 0
b = Book()
>>> print(bool(b))
Fasle
大家看到上面2段代码可能会有点懵,这主要是__bool__
和__len__
两个内置方法会影响对象bool值。所以存在的对象有可能不一定是True
bool和len优先级
我们将上面2段代码放在一起来看下谁的优先级高
class Book:
def __bool__(self):
print('bool')
return True
def __len__(self):
print('len')
return 0
b = Book()
>>> print(bool(b))
'bool'
True
从输出结果来看,当一个对象中同时存在__bool__
和__len__
时,会优先从__bool__
中取值,当__bool__
不存在时,才会从__len__
取值。