python 学习笔记
python不是有手就行吗?
python 运算符的用法:
算数运算符:
运算符 | 举例 |
---|---|
+ | 1+1=2 |
- | 1-1=0 |
* | 5*3=15 |
/ | 10/3=3.333…… |
// | 10//3=3 (向下取整) |
** | 10**4=10000 |
% | 10%4=2 |
赋值运算符:
运算符 | 举例 |
---|---|
= | c=a+b |
+= | c+=a = c=c+a |
-= | c-=a = c=c-a |
/= | c/=a = c=c/a |
//= | c//=a = c=c//a |
%= | c%=a = c=c%a |
**= | c**=a = c=c**a |
比较运算符(在 if 语句中也会提到):
先介绍一下布尔量是什么
布尔量只有
t
r
u
e
true
true 和
f
a
l
s
e
false
false 两种量, 分别表示真或假
运算符 | 举例 |
---|---|
== 判断两数是否相等 | a=1,b=1; a==b 返回 true |
!= 判断两数是否不等 | a=1,b=1; a!=b 返回 false |
> 判断第一个数是否大于第二个数 | a=1,b=1; a>b 返回 false |
>= 判断第一个数是否大于等于第二个数 | a=1,b=1; a>=b 返回 true |
< 判断第一个数是否小于第二个数 | a=2,b=1; a<b 返回 true |
<= 判断第一个数是否小于等于第二个数 | a=2,b=2; a<=b 返回 true |
逻辑运算符:
非常重要! ! !
a=10,b=20
运算符 | 描述 | 举例 |
---|---|---|
and 表达试:x and y | 如果 x 为 False,x and y 返回 False,否则它返回 y。 | a and b 返回20 |
or 表达试:x or y | 如果 x 是非 0,它返回 x 的值,否则它返回 y 的计算值。 | a or b 返回 10 |
not 表达式:not x | 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 false |
优先级(非常重要):
运算符 | 描述 |
---|---|
** | 指数 (最高优先级) |
~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
* / % // | 乘,除,取模和取整除 |
+ - | 加法减法 |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= %= /= //= -= += *= **= | 赋值运算符 |
not and or | 逻辑运算符 |
python 中 if 语句的用法:
只用 if 的:
Python 编程中 if 语句用于控制程序的执行,基本形式为:
#判断条件可以用 "比较运算符" 来表示其关系
#如果需要多个条件同时判断时,可以使用逻辑运算符
if (判断条件…):
执行语句…
需要注意的是,python没有像其他大多数语言一样使用“{}”表示语句体,所以,它通过语句的缩进来判断语句体,缩进默认为4个空格,不要Tab和空格混用,否则回编译报错。(划重点)
用 if 和 else 的:
else 为可选语句,当需要在条件不成立时执行内容则可以执行相关语句:
if (判断条件…):
执行语句…
else:
执行语句…
用 if 和 elif 和 else 的:
当判断条件为多个值时,可以使用以下形式:
if (判断语句1…):
执行语句1…
elif (判断语句2…):
执行语句2…
else:
执行语句3…
python 中循环语句的用法:
循环语句一共有两种,分别是 for 和 while
for:
1.
#最简单的模板:
for i in range(1, n):
执行语句…
这个式子的含义是将 i 的初始值赋为1,从1开始,每次加1,一直加到大于等于(n-1)
等于C++中的:
for (int i = 1; i < n; i++)
执行语句…
2.
for i in range(1, n, 2):
执行语句…
range里的值从两个变成了三个,这个式子的含义是将 i 的初始值赋为1,每次加 2,一直加到大于等于(n-1)
等于C++中的:
for (int i = 1; i < n; i += 2)
执行语句…
while:
while (条件语句…):
执行语句
非常好理解,重点就是在和许多STL套用的时候,需要你细心一点,分清每个语句的作用,多做题,灵活掌握即可。
python 中一些有用的东西:
内置函数库:
函数 | 用途 |
---|---|
abs() | 返回数字绝对值 |
all() | 判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False |
any() | 判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True |
ascii() | 调用对象的repr()方法,获取该方法的返回值 |
bin() | 将十进制转换为二进制 |
oct() | 将十进制转换为八进制 |
hex() | 将十进制转换为十六进制 |
bool() | 测试对象是True,还是False |
bytes() | 将一个字符转换为字节类型 |
str() | 将字符、数值类型转换为字符串类型 |
callable() | 检查一个对象是否是可调用的 |
chr() | 查看十进制整数对应的ASCll字符 |
ord() | 查看某个ascii对应的十进制 |
classmethod() | 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等 |
compile() | 将字符串编译成python能识别或者可以执行的代码。也可以将文字读成字符串再编译 |
complex () | 创建一个复数 |
delattr() | 删除对象属性 |
dict() | 创建数据字典 |
dir() | 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表 |
divmod() | 分别取商和余数 |
enumerate() | 返回一个可以枚举的对象,该对象的next()方法将返回一个元组 |
eval() | 将字符串str当成有效表达式来求值并返回计算结果取出字符串中内容 |
exec() | 执行字符串或complie方法编译过的字符串,没有返回值 |
filter() | 过滤器,构建一个序列,等价于 |
float() | 将一个字符串或整数转换为浮点数 |
format() | 格式化输出字符串 |
frozenset() | 创建一个不可修改的集合 |
getattr() | 获取对象属性 |
globals() | 返回一个描述当前全局变量的字典 |
hasattr() | 函数用于判断对象是否包含对应的属性 |
hash() | 返回对象的哈希值 |
help() | 返回对象的帮助文档 |
id() | 返回对象的内存地址 |
input() | 获取用户输入内容 |
int() | 用于将一个字符串或数字转换为整型 |
isinstance() | 来判断一个对象是否是一个已知的类型,类似 type() |
issubclass() | 用于判断参数 class 是否是类型参数 classinfo 的子类 |
iter() | 返回一个可迭代对象,sentinel可省略 |
len() | 返回对象的长度 |
list() | 返回可变序列类型 |
map() | 返回一个将function应用于iterable中每一项并输出其结果的迭代器 |
max() | 返回最大值 |
min() | 返回最小值 |
memoryview() | 返回给定参数的内存查看对象(memory view) |
next() | 返回可迭代对象的下一个元素 |
object() | 返回一个没有特征的新对象 |
open() | 返回文件对象 |
pow() | base为底的exp次幂,如果mod给出,取余 |
print() | 打印对象 |
class property() | 返回property属性 |
range() | 生成一个不可变序列 |
reversed() | 返回一个反向的iterator |
round() | 四舍五入 |
class set() | 返回一个set对象,可实现去重 |
class slice() | 返回一个表示有1range所指定的索引集的slice对象 |
sorted() | 对所有可迭代的对象进行排序操作 |
@staticmethod | 将方法转换为静态方法 |
sum() | 求和 |
super() | 返回一个代理对象 |
tuple() | 不可变的序列类型 |
zip() | 将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表 |
在 m a t h math math 库里的:
名称 | 用法 |
---|---|
math.ceil(x) | 返回x的上限,返回最小的整数A (A>=x)。如math.ceil(3.14)返回的整数为4 |
math.fabs(x) | 返回绝对值x。 |
math.factorial(x) | 返回 x!。如果x不是积分或者是负的,就会产生ValueError。 |
math.floor(x) | 返回x的下限,返回一个值最大整数A (A<=x)。如math.floor(3.14)返回的整数为3 |
math.exp(x) | 返回 ex也就是 math.e**x |
math . pow(x,y) | 返回x的y次方,即返回 x**y |
math.sqrt(x) | 返回√x |
math.degrees(x) | 将角x从弧度转换成角度。 |
math.radians(x) | 把角x从度转换成弧度。 |
math.acos(x) | 返回 x 的反余弦 |
math.asin(x) | 返回 x 的反正弦。 |
math.atan(x) | 返回 x 的反正切。 |
math.cos(x) | 返回 x 的余弦。 |
math.sin(x) | 返回 x 的正弦。 |
math.tan(x) | 返回 x 的正切。 |
python 中的 STL:
python 竟然也有 STL!
STL大法好
- str
- List
- Queue
- stk
- Deque 双端队列
- Set
- Map
- 位运算
常用库函数:翻转、去重、随机打乱、sort
lower_bound/upper_bound
字符串:
# 字符串: 属于序列类型
def test2():
print('--Hello World!--') # --Hello World!--
print("--Hello 'World'!--") # --Hello 'World'!--
print('''--'Hello' "World"--''') # --'Hello' "World"--
# 基础使用
print("---------------------------------------")
s = "0123456789"
print(s[0]) # 获得s[0] 0
print(s[0:2]) # 截取s[0, 2)的内容 01
print(s[0:5:2]) # 每个两个截取s[0, 5)的内容 024
print(s[0:-1]) # 最后一个字符被舍弃 012345678
print(s[-4:]) # 截取最后四个字符 6789
print(s[-1000:100]) # 首尾超过有效范围则取到首尾 0123456789
print(s[::-1]) # 翻转字符串 9876543210
print(2 * s) # 复制两次字符串
if "123" in s:
print("'123'在字符串s中")
else:
print("'123'不在字符串s中")
# 字符串处理函数
print("---------------------------------------")
print(len(s)) # 输出s的长度 10
print(str("1.23"))
print(ord('c')) # unicode -> 数字
print(chr(8364)) # 数字 -> unicode
# 字符串处理方法
print("---------------------------------------")
t = "One world, one dream!"
print(t.lower()) # 全部转为小写 one world, one dream!
print(t.upper()) # 全部转为大写 ONE WORLD, ONE DREAM!
print(t.count("one")) # 计算某个字符换出现的次数 1
print(t.replace("world", "life")) # 将world全部替换为life
print(t.center(30, "=")) # t居中,两侧用=填充 ====One world, one dream!=====
print(t.strip("!O")) # 从str中去掉在其左侧和右侧所列出的字符 ne world, one dream
print("+".join("1234")) # 1234用+隔开 1+2+3+4
# 字符串格式化输出
print("---------------------------------------")
print("{0:.2f}".format(12345)) # 保留两位小数(四舍五入) 12345.00
list:
# list: 属于序列类型
def test3():
# list创建
s = [1, 2, "hi", (2, 3)] # 或者 s = list([1, 2, "hi", (2, 3)])
t = [[i + j for j in range(3)] for i in range(2)]
# 序列类型通用操作符
print("hi" in s) # True
print("hi" not in s) # False
print(s + t) # [1, 2, 'hi', (2, 3), [0, 1, 2], [0, 1, 2]]
print(2 * s) # [1, 2, 'hi', (2, 3), 1, 2, 'hi', (2, 3)]
print(s[2]) # hi
print(s[1:3]) # 切片的详细信息请参考字符串 [2, 'hi']
# 序列类型通用函数和方法
print("---------------------------------------")
print(len(s)) # 4
print(min(t)) # 返回序列s的最小元素, s中元素需要可比较 [0, 1, 2]
print(max(t)) # 返回序列s的最大元素, s中元素需要可比较 [1, 2, 3]
print(s.index(2, 1, 3)) # 返回序列s从1开始到3位置中第一次出现元素2的位置,不存在产生ValueError异常
print(s.count(12)) # 返回序列s中出现12的总次数 0
# 列表类型操作函数和方法
print("---------------------------------------")
lt = [] # 定义空列表lt
lt += [1, 2, 3, 4, 5] # 向lt新增5个元素
lt[2] = 6 # 修改lt中第2个元素 [1, 2, 6, 4, 5]
lt.insert(2, 7) # 向lt中第2个位置增加一个元素 [1, 2, 7, 6, 4, 5]
del lt[1] # [1, 7, 6, 4, 5]
del lt[1:4] # [1, 5]
print(0 in lt) # 判断lt中是否包含数字0 False
lt.append(0) # 向lt新增数字0 [1, 5, 0]
print(lt.index(0)) # 返回数字0所在lt中的索引,不存在产生ValueError异常
print(len(lt)) # lt的长度 3
print(max(lt)) # lt中最大元素 5
for x in lt: # 遍历
print(x, end=", ")
print()
for i, x in enumerate(lt): # lt[i] = x
print(i, x)
lt.clear() # 清空lt []
print("---------------------------------------")
t = [i for i in range(5)] # [0, 1, 2, 3, 4]
t.pop(0) # 删除列表中的头元素 [1, 2, 3, 4]
t.append(3) # 在列表的尾部添加元素3 [1, 2, 3, 4, 3]
t.reverse() # 反转列表 [3, 4, 3, 2, 1]
t.remove(3) # 删除第一个3 [4, 3, 2, 1]
t.extend(["xyz", 'abc', 123]) # 追加一个列表 [4, 3, 2, 1, 'hi', 'k', 122]
queue:
# queue
def test2():
# queue: 使用list模拟队列
q = [] # 定义队列
q.append(4) # 入队 [4]
q.append(3) # 入队 [4, 3]
q.append(7) # 入队 [4, 3, 7]
q.pop(0) # 队首出队 [3, 7]
print(q[0]) # 获得队首元素 3
q.clear() # 清空队列
print(len(q)) # 获取队列中元素个数 0
print(len(q) == 0) # 判断队列是否为空 True
# PriorityQueue: 默认小顶堆,是基于heapq实现的
print("---------------------------------------")
from queue import PriorityQueue
heap = PriorityQueue()
heap.put((2, 'hi'))
heap.put((1, 'hello'))
heap.put((3, 'world'))
print(heap.queue) # 输出堆中所有元素
print(heap.queue[0]) # 输出堆顶元素, 不删除
print(heap.get()) # 输出堆顶元素, 并删除堆顶元素
print(heap.qsize())
# python3中不能向PriorityQueue添加参数变为大顶堆,需要自己封装一个,可以参考下述网址
# https://stackoverflow.com/questions/14189540/python-topn-max-heap-use-heapq-or-self-implement
# 当做算法题使用到大顶堆是,不建议使用python
import heapq
class MaxHeap(object):
def __init__(self, x):
self.heap = [-e for e in x]
heapq.heapify(self.heap)
def put(self, value):
heapq.heappush(self.heap, -value)
def get(self):
return -heapq.heappop(self.heap)
stack:
# stk
# stk
def test3():
# python是没有栈的,我们可以列表模拟一个栈
stk = []
stk.append(20) # 入栈
stk.append(10)
stk.append(30)
stk.pop(len(stk) - 1) # 出栈
stk.clear() # 清空栈
print(len(stk)) # 获取栈中元素个数 0
print(len(stk) == 0) # 判断栈是否为空 True
deque:
# deque
def test4():
from collections import deque
# 定义 deque
d = deque()
# 插入、删除元素
d.append(20) # 队尾插入一个元素 deque([20])
d.append(10) # 队尾插入一个元素 deque([20, 10])
d.pop() # 弹出一个尾部数据 deque([20])
d.appendleft(40) # 队首插入一个元素 deque([40, 20])
d.appendleft(30) # 队首插入一个元素 deque([30, 40, 20])
d.popleft() # 弹出一个队首数据 deque([40, 20])
# 遍历
for x in d:
print(x, end=", ")
print()
# 返回队首和队尾元素
print(d[0]) # 队首元素 40
print(d[len(d) - 1]) # 队尾元素 20
# 清空 deque
d.clear()
print(len(d)) # 0
print(len(d) == 0) # True
set:
# set
def test5():
"""
有序的集合:SortedSet
网址:http://www.grantjenks.com/docs/sortedcontainers/sortedset.html
"""
from sortedcontainers import SortedSet
# 创建 SortedSet
ss = SortedSet([3, 1, 2, 5, 4])
print(ss) # SortedSet([1, 2, 3, 4, 5])
from operator import neg
ss1 = SortedSet([3, 1, 2, 5, 4], neg)
print(ss1) # SortedSet([5, 4, 3, 2, 1], key=<built-in function neg>)
# SortedSet 转为 list/tuple/set
print(list(ss)) # SortedSet转为list [1, 2, 3, 4, 5]
print(tuple(ss)) # SortedSet转为tuple (1, 2, 3, 4, 5)
print(set(ss)) # SortedSet转为set {1, 2, 3, 4, 5}
# 插入、删除元素
ss.discard(-1) # 删除不存在的元素不报错
ss.remove(1) # 删除不存在的元素报错, KeyError
ss.discard(3) # SortedSet([1, 2, 4, 5])
ss.add(-10) # SortedSet([-10, 1, 2, 4, 5])
# 返回第一个和最后一个元素
print(ss[0]) # -10
print(ss[-1]) # 5
# 遍历 set
for e in ss:
print(e, end=", ") # -10, 2, 4, 5,
print()
# set 中判断某元素是否存在
print(2 in ss) # True
# bisect_left() / bisect_right()
print(ss.bisect_left(4)) # 返回大于等于4的最小元素对应的下标 2
print(ss.bisect_right(4)) # 返回大于4的最小元素对应的下标 3
# 清空 set
ss.clear()
print(len(ss)) # 0
print(len(ss) == 0) # True
"""
无序的集合: set
"""
# 集合的定义:集合是不可变的,因此集合中元素不能是list
A = {"hi", 2, ("we", 24)}
B = set() # 空集合的定义,不能使用B = {}定义集合,这样是字典的定义
# 集合间的操作, 下面的运算法符都可以写成 op= 的形式
print("---------------------------------------")
S = {1, 2, 3}
T = {3, 4, 5}
print(S & T) # 交集,返回一个新集合,包括同时在集合S和T中的元素
print(S | T) # 并集,返回一个新集合,包括在集合S和T中的所有元素
print(S - T) # 差集,返回一个新集合,包括在集合S但不在T中的元素
print(S ^ T) # 补集,返回一个新集合,包括集合S和T中的非相同元素
# 集合的包含关系
print("---------------------------------------")
C = {1, 2}
D = {1, 2}
print(C <= D) # C是否是D的子集 True
print(C < D) # C是否是D的真子集 False
print(C >= D) # D是否是C的子集 True
print(C > D) # D是否是C的真子集 False
# 集合的处理方法
print("---------------------------------------")
S = {1, 2, 3, 5, 6}
S.add(4) # 如果x不在集合S中,将x增加到S
S.discard(1) # 移除S中元素x,如果x不在集合S中,不报错
S.remove(2) # 移除S中元素x,如果x不在集合S中,产生KeyError异常
for e in S: # 遍历
print(e, end=",")
print()
print(S.pop()) # 从S中随机弹出一个元素,S长度减1,若S为空产生KeyError异常
print(S.copy()) # 返回集合S的一个副本, 对该副本的操作不会影响S
print(len(S)) # 返回集合S的元素个数
print(5 in S) # 判断S中元素x, x在集合S中,返回True,否则返回False
print(5 not in S) # 判断S中元素x, x在集合S中,返回True,否则返回False
S.clear() # 移除S中所有元素
# SortedList: 类似于C++中的multiset
def _test5():
"""
网址:http://www.grantjenks.com/docs/sortedcontainers/sortedlist.html
"""
from sortedcontainers import SortedList
# 定义
sl = SortedList(key=lambda x: -x) # 降序
sl = SortedList([3, 1, 2, 1, 5, 4]) # 升序
print(sl) # SortedList([1, 1, 2, 3, 4, 5])
# 插入、删除元素
sl.add(3)
sl.add(3)
sl.discard(2) # SortedList([1, 1, 3, 3, 3, 4, 5])
print(sl)
# 统计某个元素出现的次数
print(sl.count(3)) # 3
# 返回第一个和最后一个元素
print(sl[0]) # 1
print(sl[-1]) # 5
# 遍历 set
for e in sl:
print(e, end=", ") # 1, 1, 3, 3, 3, 4, 5,
print()
# 判断某元素是否存在
print(2 in sl) # False
# bisect_left() / bisect_right()
print(sl.bisect_left(3)) # 返回大于等于3的最小元素对应的下标 2
print(sl.bisect_right(3)) # 返回大于3的最小元素对应的下标 5
# 清空
sl.clear()
print(len(sl)) # 0
print(len(sl) == 0) # True
map:
# map
def test6():
"""
有序的map: SortedDict
网址: http://www.grantjenks.com/docs/sortedcontainers/sorteddict.html
"""
from sortedcontainers import SortedDict
sd = SortedDict()
# 插入、删除元素
sd["wxx"] = 21
sd["hh"] = 18
sd["other"] = 20
print(sd) # SortedDict({'hh': 18, 'other': 20, 'wxx': 21})
print(sd["wxx"]) # 访问不存在的键会报错, KeyError
print(sd.get("c")) # 访问不存在的键会返回None None
# SortedDict转dict
print(dict(sd)) # {'hh': 18, 'other': 20, 'wxx': 21}
# 返回最后一个元素和最后一个元素
print(sd.peekitem(0)) # 类型tuple, 返回第一个元素 ('hh', 18)
print(sd.peekitem()) # 类型tuple, 返回最后一个元素 ('wxx', 21)
# 遍历
for k, v in sd.items():
print(k, ':', v, sep="", end=", ") # sep取消每行输出之间的空格
print()
for k in sd: # 遍历键k, 等价于for k in d.keys:
print(str(k) + ":" + str(sd[k]), end=", ")
print()
for v in sd.values(): # 遍历值v
print(v, end=", ")
print()
# 返回Map中的一个键
print(sd.peekitem()[0])
# 返回Map中的一个值
print(sd.peekitem()[1])
# 中判断某元素是否存在
print("wxx" in sd) # True
# bisect_left() / bisect_right()
sd["a"] = 1
sd["c1"] = 2
sd["c2"] = 4
print(sd) # SortedDict({'a': 1, 'c1': 2, 'c2': 4, 'hh': 18, 'other': 20, 'wxx': 21})
print(sd.bisect_left("c1")) # 返回键大于等于"c1"的最小元素对应的下标 1
print(sd.bisect_right("c1")) # 返回键大于"c1"的最小元素对应的下标 2
# 清空
sd.clear()
print(len(sd)) # 0
print(len(sd) == 0) # True
"""
无序的map: dict
"""
print("---------------------------------------")
d = {"c1": 2, "c2": 4, "hh": 18, "wxx": 21, 13: 14, 1: 0}
print(d["wxx"]) # 21
print(d[13]) # 14
d[13] += 1
print(d[13]) # 15
d["future"] = "wonderful" # 字典中添加键值对
del d[1] # 删除字典d中键1对应的数据值
print("wxx" in d) # 判断键"wxx"是否在字典d中,如果在返回True,否则False
print(d.keys()) # 返回字典d中所有的键信息 dict_keys(['c1', 'c2', 'hh', 'wxx', 13])
print(d.values()) # 返回字典d中所有的值信息 dict_values([2, 4, 18, 21, 14])
print(d.items()) # dict_items([('c1', 2), ('c2', 4), ('hh', 18), ('wxx', 21), (13, 14)])
for k, v in d.items(): # 遍历 k, v
print(k, ':', v)
for k in d: # 遍历键k, 等价于for k in d.keys:
print(str(k) + ":" + str(d[k]), end=", ")
print()
for v in d.values(): # 遍历值v
print(v, end=", ")
print()
# 字典类型操作函数和方法
print("---------------------------------------")
d = {"中国": "北京", "美国": "华盛顿", "法国": "巴黎"}
print(len(d)) # 返回字典d中元素的个数 3
print(d.get("中国", "不存在")) # 键k存在,则返回相应值,不在则返回<default>值 北京
print(d.get("中", "不存在")) # 不存在
print(d.get("中")) # None
d["美国"] = "Washington" # 修改键对应的值
print(d.pop("美国")) # 键k存在,则返回相应值,并将其从dict中删除
print(d.popitem()) # 随机从字典d中取出一个键值对,以元组形式返回,并将其从dict中删除
d.clear() # 删除所有的键值对
常用库函数:
reverse()和reversed():
reverse()方法:
属于列表的内置方法(即在字典、元组、字符串中没有这个内置方法),可用于列表中数据的翻转。
需要注意的是reverse()方法是直接对原列表进行翻转,没有返回值。
list = [1, 2, 3, 4]
lista.reverse()
print(list)
打印结果:
[4, 3, 2, 1]
reversed()方法:
属于python自带的一个方法,可用于列表、元组和字符串等。
1.列表的翻转:
a = [1,3,5,7]
print(list(reversed(a)))
2.元组的翻转:
a = (1, 2, 3)
print(tuple(reversed(a)))
打印结果:
[3, 2, 1]
3.字符串的翻转
使用join方法
ss = "qwer1234"
print(''.join(reversed(ss)))
打印结果:
4321rewq
sort和sorted:
Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列。
1)排序基础
简单的升序排序是非常容易的。只需要调用sorted()方法。它返回一个新的list,新的list的元素基于小于运算符(__lt__)来排序。
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]
你也可以使用list.sort()方法来排序,此时list本身将被修改。通常此方法不如sorted()方便,但是如果你不需要保留原来的list,此方法将更有效。
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
另一个不同就是list.sort()方法仅被定义在list中,相反地sorted()方法对所有的可迭代序列都有效。
>>> sorted({1: ' D ', 2: ' B ', 3: ' B ', 4: ' E ', 5: ' A '})
[1, 2, 3, 4, 5]
2)key参数/函数
从python2.4开始,list.sort()和sorted()函数增加了key参数来指定一个函数,此函数将在每个元素比较前被调用。 例如通过key指定的函数来忽略字符串的大小写:
>>> sorted( " This is a test string from Andrew ".split(), key=str.lower)
[ ' a ', ' Andrew ', ' from ', ' is ', ' string ', ' test ', ' This ']
key参数的值为一个函数,此函数只有一个参数且返回一个值用来进行比较。这个技术是快速的因为key指定的函数将准确地对每个元素调用。
更广泛的使用情况是用复杂对象的某些值来对复杂对象的序列排序,例如:
>>> student_tuples = [
( ' john ', ' A ', 15),
( ' jane ', ' B ', 12),
( ' dave ', ' B ', 10),
]
>>> sorted(student_tuples, key= lambda student: student[2]) # sort by age
[( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12), ( ' john ', ' A ', 15)]
同样的技术对拥有命名属性的复杂对象也适用,例如:
>>> class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
>>> student_objects = [
Student( ' john ', ' A ', 15),
Student( ' jane ', ' B ', 12),
Student( ' dave ', ' B ', 10),
]
>>> sorted(student_objects, key= lambda student: student.age) # sort by age
[( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12), ( ' john ', ' A ', 15)]
3)Operator 模块函数
上面的key参数的使用非常广泛,因此python提供了一些方便的函数来使得访问方法更加容易和快速。operator模块有itemgetter,attrgetter,从2.6开始还增加了methodcaller方法。使用这些方法,上面的操作将变得更加简洁和快速:
>>> from operator import itemgetter, attrgetter
>>> sorted(student_tuples, key=itemgetter(2))
[( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12), ( ' john ', ' A ', 15)]
>>> sorted(student_objects, key=attrgetter( ' age '))
[( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12), ( ' john ', ' A ', 15)]
operator模块还允许多级的排序,例如,先以grade,然后再以age来排序:
>>> sorted(student_tuples, key=itemgetter(1,2))
[( ' john ', ' A ', 15), ( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12)]
>>> sorted(student_objects, key=attrgetter( ' grade ', ' age '))
[( ' john ', ' A ', 15), ( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12)]
4)升序和降序
list.sort()和sorted()都接受一个参数reverse(True or False)来表示升序或降序排序。例如对上面的student降序排序如下:
>>> sorted(student_tuples, key=itemgetter(2), reverse=True)
[( ' john ', ' A ', 15), ( ' jane ', ' B ', 12), ( ' dave ', ' B ', 10)]
>>> sorted(student_objects, key=attrgetter( ' age '), reverse=True)
[( ' john ', ' A ', 15), ( ' jane ', ' B ', 12), ( ' dave ', ' B ', 10)]
5)排序的稳定性和复杂排序
从python2.2开始,排序被保证为稳定的。意思是说多个元素如果有相同的key,则排序前后他们的先后顺序不变。
>>> data = [( ' red ', 1), ( ' blue ', 1), ( ' red ', 2), ( ' blue ', 2)]
>>> sorted(data, key=itemgetter(0))
[( ' blue ', 1), ( ' blue ', 2), ( ' red ', 1), ( ' red ', 2)]
注意在排序后'blue'的顺序被保持了,即'blue', 1在'blue', 2的前面。
更复杂地你可以构建多个步骤来进行更复杂的排序,例如对student数据先以grade降序排列,然后再以age升序排列。
>>> s = sorted(student_objects, key=attrgetter( ' age ')) # sort on secondary key
>>> sorted(s, key=attrgetter( ' grade '), reverse=True) # now sort on primary key, descending
[( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12), ( ' john ', ' A ', 15)]
6)最老土的排序方法-DSU
我们称其为DSU(Decorate-Sort-Undecorate),原因为排序的过程需要下列三步:
第一:对原始的list进行装饰,使得新list的值可以用来控制排序;
第二:对装饰后的list排序;
第三:将装饰删除,将排序后的装饰list重新构建为原来类型的list;
例如,使用DSU方法来对student数据根据grade排序:
>>> decorated = [(student.grade, i, student) for i, student in enumerate(student_objects)]
>>> decorated.sort()
>>> [student for grade, i, student in decorated] # undecorate
[( ' john ', ' A ', 15), ( ' jane ', ' B ', 12), ( ' dave ', ' B ', 10)]
上面的比较能够工作,原因是tuples是可以用来比较,tuples间的比较首先比较tuples的第一个元素,如果第一个相同再比较第二个元素,以此类推。
并不是所有的情况下都需要在以上的tuples中包含索引,但是包含索引可以有以下好处:
第一:排序是稳定的,如果两个元素有相同的key,则他们的原始先后顺序保持不变;
第二:原始的元素不必用来做比较,因为tuples的第一和第二元素用来比较已经是足够了。
此方法被RandalL.在perl中广泛推广后,他的另一个名字为也被称为Schwartzian transform。
对大的list或list的元素计算起来太过复杂的情况下,在python2.4前,DSU很可能是最快的排序方法。但是在2.4之后,上面解释的key函数提供了类似的功能。
7)其他语言普遍使用的排序方法-cmp函数
在python2.4前,sorted()和list.sort()函数没有提供key参数,但是提供了cmp参数来让用户指定比较函数。此方法在其他语言中也普遍存在。
在python3.0中,cmp参数被彻底的移除了,从而简化和统一语言,减少了高级比较和__cmp__方法的冲突。
在python2.x中cmp参数指定的函数用来进行元素间的比较。此函数需要2个参数,然后返回负数表示小于,0表示等于,正数表示大于。例如:
>>> def numeric_compare(x, y):
return x - y
>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare)
[1, 2, 3, 4, 5]
或者你可以反序排序:
>>> def reverse_numeric(x, y):
return y - x
>>> sorted([5, 2, 4, 1, 3], cmp=reverse_numeric)
[5, 4, 3, 2, 1]
当我们将现有的2.x的代码移植到3.x时,需要将cmp函数转化为key函数,以下的wrapper很有帮助:
def cmp_to_key(mycmp):
' Convert a cmp= function into a key= function '
class K(object):
def __init__(self, obj, *args):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
def __ne__(self, other):
return mycmp(self.obj, other.obj) != 0
return K
当需要将cmp转化为key时,只需要:
>>> sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric))
[5, 4, 3, 2, 1]
从python2.7,cmp_to_key()函数被增加到了functools模块中。
8)其他注意事项
* 对需要进行区域相关的排序时,可以使用locale.strxfrm()作为key函数,或者使用local.strcoll()作为cmp函数。
* reverse参数任然保持了排序的稳定性,有趣的时,同样的效果可以使用reversed()函数两次来实现:
>>> data = [( ' red ', 1), ( ' blue ', 1), ( ' red ', 2), ( ' blue ', 2)]
>>> assert sorted(data, reverse=True) == list(reversed(sorted(reversed(data))))
* 其实排序在内部是调用元素的__cmp__来进行的,所以我们可以为元素类型增加__cmp__方法使得元素可比较,例如:
>>> Student. __lt__ = lambda self, other: self.age < other.age
>>> sorted(student_objects)
[( ' dave ', ' B ', 10), ( ' jane ', ' B ', 12), ( ' john ', ' A ', 15)]
* key函数不仅可以访问需要排序元素的内部数据,还可以访问外部的资源,例如,如果学生的成绩是存储在dictionary中的,则可以使用此dictionary来对学生名字的list排序,如下:
>>> students = [ ' dave ', ' john ', ' jane ']
>>> newgrades = { ' john ': ' F ', ' jane ': ' A ', ' dave ': ' C '}
>>> sorted(students, key=newgrades. __getitem__)
[ ' jane ', ' dave ', ' john ']
*当你需要在处理数据的同时进行排序的话,sort(),sorted()或bisect.insort()不是最好的方法。在这种情况下,可以使用heap,red-black tree或treap。
或者:
# sort
# 可以参考:https://blog.csdn.net/weixin_41611054/article/details/113934296
def test10():
# list成员函数sort()
arr = [3, 5, 1, 6, 9, 2]
arr.sort() # 作用在arr上
print(arr) # [1, 2, 3, 5, 6, 9]
# list成员函数sort() 自定义比较
arr = [(2, 2), (3, 4), (4, 1), (1, 3)]
def cmp(e):
return e[1]
arr.sort(reverse=True, key=cmp) # 根据第二维降序排列
print(arr)
arr.sort(key=lambda x: (-x[0], x[1])) # 第一维降序,第二维升序排列
print(arr)
# sorted
print("---------------------------------------")
arr = [3, 5, 1, 6, 9, 2]
print(sorted(arr)) # 返回排序(默认升序)后的list
print(sorted(arr, reverse=True)) # 返回排序(降序)后的list
# sorted 自定义比较
arr = [(2, 2), (3, 4), (4, 1), (1, 3)]
print(sorted(arr, key=lambda e: -e[1])) # 根据第二维降序排列
# sorted对dict排序
print("---------------------------------------")
d = {'c': 21, 'a': 24, 'b': 12}
print(sorted(d)) # 返回list ['a', 'b', 'c']
print(sorted(d.items())) # 返回list [('a', 24), ('b', 21), ('c', 12)]
print(sorted(d.items(), key=lambda e: e[1], reverse=True)) # 按照值降序排列
去重:
# 方法一
# 利用集合的元素唯一性,对列表进行去重
def three_question():
li = [11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
se = set(li)
print('列表中不重复元素个数:',len(se))
# three_question()
# 方法二
# 定义一个空列表,用for循环遍历要去重的列表,判断不存在与新定义的空列表的元素就添加实现去#重
def three_question02():
li = [11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
li2 = []
for item in li:
if item not in li2:
li2.append(item)
else:
continue
print('列表中不重复元素个数:',len(li2))
# three_question02()
# 方法三
# 利用嵌套for循环,比对出重复元素进行删除操作,实现列表去重
def three_question03():
li = [11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
num=0
for item in li[0:]:
num+=1
for id in li[num:]:
if id == item:
li.remove(id)
else:
continue
print(li)
print('列表中不重复元素个数:', len(li))
# three_question03()
# 第四种 将值转化为字典的键值,利用键值的唯一性
def three_question04():
print("第三种 将值转化为字典的键值,利用键值的唯一性")
li=[11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
dict1={}
for i in li:
dict1[i]=i
number=len(dict1)
print("列表中不重复的元素个数为:{}".format(number))
# three_question04()
# 方法五:
def three_question05():
li = [11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
li3 =[]
s=set()
for i in li:
if li.count(i) == 1:
if i not in li3:
li3.append(i)
elif li.count(i)>1:
s.add(i)
for se in s:
li3.append(se)
print('不重复元素个数',len(li3))
# three_question05()
# 方法六:
def three_question06():
li = [11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
li3 =[]
s={}
for i in li:
if li.count(i) == 1:
if i not in li3:
li3.append(i)
elif li.count(i)>1:
s[i]=i
for se in s.values():
li3.append(se)
print('不重复元素个数',len(li3))
# three_question06()
#方法七:(利用字典健值去重)字典函数去重
def three_question07():
li=[11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
d = {}
d = d.fromkeys(li)
li2 = list(d.keys())
print(li2)
print('不重复元素个数', len(li2))
# three_question07()
# 方法八:
def three_question08():
li=[11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
li3=[]
index=0
while index < len(li):
if li[index] not in li3:
li3.append(li[index])
index += 1
if index >= len(li):
break
print('不重复元素个数',len(li3))
# three_question08()
# 方法九:
def three_question09():
li=[11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
formatList = list(set(li))
formatList.sort(key=li.index)
print('不重复元素个数',len(formatList))
three_question09()
或者:
1.使用循环进行遍历,将重复的元素去掉。
def test1():
lst = [1,2,5,6,3,5,7,3]
tmp = []
for it in lst:
if it not in tmp:
tmp.append(it)
print(tmp)
结果:
[1, 2, 5, 6, 3, 7]
2.使用集合的唯一性,对列表进行去重。
def test2():
lst = [1,2,5,6,3,5,7,3]
tmp = list(set(lst))
print(tmp) # 顺序改变
tmp.sort(key=lst.index)
print(tmp) # 顺序不变
结果:
[1, 2, 3, 5, 6, 7]
[1, 2, 5, 6, 3, 7]
随机打乱:
Random中有一个random.shuffle()方法提供了完美的解决方案。代码如下:
x = [1,2,3,4,5,6]
random.shuffle(x)
print(x)
输出结果:
第一次输出内容:[6, 5, 1, 3, 2, 4]
第二次输出内容:[6, 1, 3, 5, 2, 4]
第三次输出内容:[5, 3, 1, 2, 4, 6]
lower_bound:
lower_bound(nums, target)
在非递减数组nums中,lower_bound(nums, target)返回第一个大于等于target的值得位置,如果nums中元素均小于target(即不存在>=target的元素),则返回nums的长度(即target如果要插入到nums中,应该插入的位置)
#coding=utf-8
#返回nums中第一个>=target的值得位置,如果nums中都比target小,则返回len(nums)
def lower_bound(nums, target):
low, high = 0, len(nums)-1
pos = len(nums)
while low<high:
mid = (low+high)/2
if nums[mid] < target:
low = mid+1
else:#>=
high = mid
#pos = high
if nums[low]>=target:
pos = low
return pos
测试:
nums = [10, 10, 10, 20, 20, 20, 30, 30]
print lower_bound(nums, 9),
print lower_bound(nums, 10),
print lower_bound(nums, 15),
print lower_bound(nums, 20),
print lower_bound(nums, 25),
print lower_bound(nums, 30),
print lower_bound(nums, 40)
运行结果:
0 0 3 3 6 6 8
upper_bound:
upper_bound(nums, target)
在非递减数组nums中,upper_bound(nums, target)返回第一个大于target的值的位置,如果nums中元素均小于等于target(即不存在>target的元素),则返回nums的长度(即target如果要插入到nums中,应该插入的位置)
#返回nums中第一个>target的值得位置,如果nums中都不比target大,则返回len(nums)
def upper_bound(nums, target):
low, high = 0, len(nums)-1
pos = len(nums)
while low<high:
mid=(low+high)/2
if nums[mid]<=target:
low = mid+1
else:#>
high = mid
pos = high
if nums[low]>target:
pos = low
return pos
测试:
nums = [10, 10, 10, 20, 20, 20, 30, 30]
print upper_bound(nums, 9),
print upper_bound(nums, 10),
print upper_bound(nums, 15),
print upper_bound(nums, 20),
print upper_bound(nums, 25),
print upper_bound(nums, 30),
print upper_bound(nums, 40)
运行结果:
0 3 3 6 6 8 8