Python进阶一:Python列表生成式的高效使用和Python对象间相等性比较
1. 写在前面
今天整理列表生成式的常用使用场景, 列表生成式是生成python列表的一种高效的方式,并且优雅简洁,可以尝试多多使用。 首先整理11种列表生成式的使用场景(有难有易吧), 然后是Python对象间的对比简单梳理(is, in, ==)。今天是python进阶的第一篇, python进阶开始就更关注python的更多细节层面, 当然依然是从使用的角度出发, 理论部分不做过多整理。
大纲如下:
- Python列表生成式的高效使用案例
- Python对象相等性的比较
Ok, let’s go!
2. Python列表生成式高效使用
下面是11种列表生成式的使用方式:
-
数据再运算
使用列表生成式的方式实现数据再运算, 即生成新的列表# 元素平方(当然不只是这一种操作) a = range(0, 11) b = [x**2 for x in a] b # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100] # 数值型元素列表转成字符串 c = [str(i) for i in a] c ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
-
一串随机数
# 生成10个0到1的随机浮点数, 保留小数点后两位 from random import random a = [round(random(), 2) for _ in range(10)] a # 生成10个0到10的满足均匀分布的浮点数 from random import uniform b = [round(uniform(0, 10), 2) for _ in range(10)] b
-
if和嵌套for
# 对一个列表里面的数据筛选, 只计算[0, 11)中偶数的平方 a = [x**2 for x in range(12) if x%2==0] a # [0, 4, 16, 36, 64, 100] # 列表生成式中嵌套for a = [i*j for i in range(10) for j in range(1, i+1)] a
-
zip和列表
a = range(5) b = ['a', 'b', 'c', 'd', 'e'] c = [str(y) + str(x) for x, y in zip(a, b)] c # ['a0', 'b1', 'c2', 'd3', 'e4']
-
打印键值对
a = {'a': 1, 'b': 2, 'c': 3} b = [k + '=' + str(v) for k, v in a.items()] b ['a=1', 'b=2', 'c=3']
-
文件列表
import os a = [d for d in os.listdir('E:/Jupyter Notebook/Python全栈')]
-
保留唯一值
这个当然有比较快的方式,就是利用setdef filter_non_unique(lst): return [item for item in lst if lst.count(item)==1] filter_non_unique([1, 2, 2, 1, 3])
-
筛选分组
def bifurcate(lst, filte): return [[x for i, x in enumerate(lst) if filte[i]==True], [x for i, x in enumerate(lst) if filte[i]==False] ] bifurcate(['beep', 'boop', 'foo', 'bar'], [True, True, False, True]) # [['beep', 'boop', 'bar'], ['foo']]
-
函数分组
通过函数的方式对列表中的元素分组, 这个还是很常用的。def bifurcate_by(lst, fn): return [[x for x in lst if fn(x)], [x for x in lst if not fn(x)]] # 筛选出以u开头的元素 bifurcate_by(['python3', 'up', 'users', 'people'], lambda x: x[0]=='u') # [['up', 'users'], ['python3', 'people']]
-
两个列表的差集
筛选出在列表1中出现的元素, 而不在列表2中出现。def difference(a, b): _a, _b = set(a), set(b) return [item for item in _a if item not in _b] difference([1, 1, 2, 3, 3], [1, 2, 4])
-
函数差集
# 列表a, b中元素经过fn映射后, 返回在a不在b中的元素 def difference_by(a, b, fn): _b = set(map(fn, b)) return [item for item in a if fn(item) not in _b] from math import floor difference_by([2.1, 1.2], [2.3, 3.4], floor) # 1.2 difference_by([{'x': 2}, {'x':1}], [{'x': 1}], lambda v:v['x']) # [{'x': 2}]
3. Python对象间的相等性比较
python中, 对象相等性比较相关关键字包括is, in
, 比较运算符有==
-
is
判断两个对象的标识号是否相等a = [1, 2, 3] id(a) #2646376974856 b = [1, 2, 3] id(b) # 2646141534088 a is b # False a == b # True
对于序列型、字典型、集合型对象,一个对象实例指向另一个对象实例,
is
比较才返回真值。a, b = {'a': [1, 2, 3]}, {'id': 'book id', 'price': 'book price'} a = b a is b # True
对于值类型而言,不同的编译器可能会做不同的优化。从性能角度考虑,它们会缓存一些值类型的对象实例。所以,使用
is
比较时,返回的结果看起来会有些不太符合预期。注意观察下面两种情况,同样的整数值,使用is
得到不同结果。a = 123 b = 123 a is b # True c = 123456 d = 123456 c is d # False
Python 解释器,对位于区间 [-5,256] 内的小整数,会进行缓存,不在该范围内的不会缓存,所以才出现上面的现象。
# Python中None对象是一个单例类的实例, 具有唯一的标识号 id(None) # 1542233392
-
in
用于成员检测
如果元素i是s的成员, 则i in s 为True, 否则返回False。# 对于字符串类型,i in s 为 True,意味着 i 是 s 的子串,也就是 s.find(i) 返回大于 - 的值 'ab' in 'abc' # True
内置的序列类型, 字典类型和集合类型, 都支持in操作。 对于字典类型, in操作判断i是否是字典的键
[1, 2] in [[1, 2], 'str'] 'apple' in {'orange': 1.6, 'banana': 2.3, 'apple': 5.2} # True
对于自定义类型, 判断是否位于序列类型中, 需要重写序列类型的魔方方法
contains
。 比如下面的例子, 自定义一个Student类, 然后再定义一个继承于list的Students类, 根据Student类的name属性, 判断某Student是否在Students列表中。class Student(): def __init__(self, name): self._name = name @property def name(self): return self._name @name.setter def name(self, val): self._name = val class Students(list): def __contains__(self, stu): for s in self: if s.name == stu.name: return True return False
下面进行测试:
s1 = Student('xiaoming') s2 = Student('xiaohong') a = Students() a.extend([s1, s2]) s3 = Student('xiaohong') s3 in a # True
-
==
用于判断值或者内容是否相等, 默认是基于两个对象的标识号比较。
对于数值型, 字符串, 列表, 字典, 集合, 默认只要元素值相等,==
比较结果是True。str1 = 'alg-channel' str2 = 'alg-channel' str1 == str2 # True
对于自定义类型, 当所有属性取值完全相同的两个实例, 判断
==
时, 返回false。但是, 大部分场景下, 我们希望两个对象是相等的, 这样不用重复添加到列表中, 比如,判断用户是否已经登入时,只要用户所有属性与登入列表中某个用户完全一致时,就认为已经登入。这时候需要重写方法
eq
.class Student(): def __init__(self, name, age): self._name = name self._age = age @property # 装饰器, 把方法装饰成属性 def name(self): return self._name @name.setter def name(self, val): self._name = val @property def age(self): return self._age @age.setter def age(self, val): self._age = val def __eq__(self, val): print(self.__dict__) return self.__dict__ == val.__dict__
下面尝试加入几个对象, 然后如果是相等的两个对象, 看看输出什么结果:
a = [] xiaoming = Student('xiaoming', 29) if xiaoming not in a: a.append(xiaoming) xiaohong = Student('xiaohong', 30) if xiaohong not in a: a.append(xiaohong) xiaoming2 = Student('xiaoming', 29) if xiaoming2 == xiaoming: # 会发现这个是相等的 print('equal')
本文地址:https://blog.csdn.net/wuzhongqiang/article/details/107423473
上一篇: Servlet实现简单的用户登录功能
下一篇: Eureka(服务注册与发现)简单入门