# 数据类型转换
int(x, [, base])
: 将 x 转换为整数, base 表示进制float(x)
: 将 x 转换为一个浮点数complex(x, [, imag])
创建一个复数,imag 是虚部的数值str(x)
: 将对象 x 转换为字符串repr(x)
: 将对象 x 转换为表达式字符串eval(str)
: 计算在字符串中有效的表达式,并返回一个对象tuple(s)
: 将序列 s 转换为一个元组list(s)
: 将序列 s 转换为一个列表set(s)
: 转换为一个可变的集合dict(d)
: 创建一个字典,d 是一个 key,value 元组frozenset(s)
: 转换为不可变集合chr(x)
: 将一个整数转换为一个字符ord(x)
: 将一个字符转换为他的整数值hex(x)
: 将一个整数转换为一个十六进制字符串oct(x)
: 将一个整数转换为一个八进制字符串
# list 列表
列表常见方法
a.append(x) 等价于 a[len(a):] = [x]
a.extend(iterable) 使用可迭代对象的元素扩展指定列表
a.insert(i, x) 在指定位置插入对象 insert(0, 1)
a.remove(x) 从列表中删除第一个值为 x 的元素,找不到触发 ValueError
a.pop([i]) 删除列表中的指定位置的元素,没有指定的时候删除最后一个元素,并返回
a.clear() 删除列表中的所有元素 等价于 del a[:]
a.index(x, [start [, end]]) 返回指定序列中第一个值是 x 的索引
a.count(x) 返回列表中元素 x 出现的次数
a.reverse() 翻转列表中的所有元素
init list
开辟指定大小的 list
path = [0 for i in range(n)]
开辟指定大小的 bool list
used = [False for i in range(n)]
开辟 n * m 的全零 list
ans = [[0 for j in range(m)] for i in range(n)]
应该使用匿名函数无副作用的计算平方列表
squares = list(map(lambda x: x**2, range(10)))
squares = [x**2 for x in range(10)]
# tuple 元组
元组写在小括号中,不能修改元素
创建只有一个元素的元组需要在结尾添加一个逗号
t1 = tuple()
t2 = ()
t3 = (1, 2, '2', [1, 2], 5)
t4 = (7, )
对于函数中的多返回值,返回的就是一个元组
count(x)
计算某一个元素出现的次数index(x)
寻找某一个元素第一次出现的索引位置
# set 集合
集合是由不重复元素组成的无序容器。基本用法包括成员检测、消除重复元素。集合对象支持合集、交集、差集、对称差分等数学运算
创建集合用花括号或 set()
函数。注意,创建空集合只能用 set()
,不能用 {}
, {}
创建的是空字典
使用推导式进行创建:
a = {x for x in 'abracadabra' if x not in 'abc'}
a
{'r', 'd'}
常用操作:
s1.add('dd')
s1.update('b') s1.update(s2)
s3.pop() # 随机删除一个元素
s3.clear()
s3.remove('fengwei')
b.issubset(a) # 判断 b 是否是 a 的子集
a.union(c) # a 和 c 的并集
a & c # 交集
a.difference(c) # 只在 a 中的元素
a ^ c # 求只在一个集合中的所有元素
# queue 队列
规矩:使用 collections
中的 deque
返回一个新的双向队列对象,在队列两端插入或删除元素时间复杂度都是 O(1)
,区别于列表,在列表的开头插入或删除元素的时间复杂度为 O(N)
。
from collections import deque
queue = deque(["a", "b", "c"])
queue.append("d")
queue.appendleft("leftElement")
queue.popleft() # popleft , 同时将删除的值返回
queue.clear() # 移除所有元素
queue.copy() # 创建一份浅拷贝
queue.count(x) # 计算队列中等于 x 的个数
queue.extend() # 添加到队列的右侧
queue.extendleft() # 添加到队列的左侧
queue.index(x, [start, end])
# 在 start 之后,stop 之前返回第一个 x 在 deque 中的位置
insert(i, x)
# 在位置 i 插入 x
pop() # 移除最右侧的那一个
reverse() # 将队列逆序
rotate(n=1)
# 向右循环移动 n 步。 如果 n 是负数,就向左循环。
使用队列实现保留最后 N 个元素
使用 deque(maxlen=N)
构造函数会新建一个固定大小的队列。当新的元素加入并且这个队列已满的时候, 最老的元素会自动被移除掉。
>>> q = deque(maxlen=3)
>>> q.append(1)
>>> q.append(2)
>>> q.append(3)
>>> q
deque([1, 2, 3], maxlen=3)
>>> q.append(4)
>>> q
deque([2, 3, 4], maxlen=3)
>>> q.append(5)
>>> q
deque([3, 4, 5], maxlen=3)
# heap 堆
创建一个堆
heap = []
heap = heapify([])
heappush(heap, item)
# 将 item 的值加入到 heap 中
heappop(heap)
# 弹出并返回 heap 的最小的元素,保持堆的不变性。
# 使用 heap[0] ,可以只访问最小的元素而不弹出它。
heappushpop(heap, item)
# 将 item 放入堆中,然后弹出并返回 heap 的最小元素。
# 该组合操作比先调用 heappush() 再调用 heappop() 运行起来更有效率。
heapreplace(heap, item)
# 弹出并返回 heap 中最小的一项,同时推入新的 item。 堆的大小不变。
# 返回的值可能会比添加的 item 更大
nlargest(n, iterable, key=None)
# 从 iterable 所定义的数据集中返回前 n 个最大元素组成的列表。
nsmallest(n, iterable, key=None)
# 从 iterable 所定义的数据集中返回前 n 个最小元素组成的列表。
# 这两个函数在 n 值较小时性能最好。
# 对于更大的值,使用 sorted() 函数会更有效率。
# 此外,当 n==1 时,使用内置的 min() 和 max() 函数会更有效率。
# 如果需要重复使用这些函数,请考虑将可迭代对象转为真正的堆。
# 或者使用 sorted(items)[:N], sorted(items)[-N:]
使用:查找最大的或者最小的 N 个元素
import heapq
nums = [1. 4. 2, 8, 5, 7]
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))
再添加匿名函数参数对于复杂的结构使用 heap
laptops = [
{'name': 'ThinkPad', 'amount': 100, 'price': 91.1},
{'name': 'Mac', 'amount': 50, 'price': 543.22},
{'name': 'Surface', 'amount': 200, 'price': 21.09},
{'name': 'Alienwar', 'amount': 35, 'price': 31.75},
{'name': 'Lenovo', 'amount': 45, 'price': 16.35},
{'name': 'Huawei', 'amount': 75, 'price': 115.65}
]
cheap = heapq.nsmallest(3, laptops, key=lambda s: s['price'])
expensive = heapq.nlargest(3, laptops, key=lambda s: s['price'])
实现优先级队列:
SHOWMORE
import heapq
class PriorityQueue:
def __init__(self):
self._queue = []
self._index = 0
def push(self, item, priority):
heapq.heappush(self._queue, (-priority, self._index, item))
# 负数的目的是使得元素按照优先级从高到低进行排序,添加 self._index 实现不可能有两个元素具有相同的 index 值
# python 在做元组比较的时候,如果前面的比较已经可以确定结果了,后面的比较操作就不会发生了
self._index += 1
# 保证第一个元素拥有最高的优先级
def pop(self):
return heapq.heappop(self._queue)
# 每次弹出 最小的元素 return heapq.heappop(self._queue)[-1]
class Item:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Item({!r})'.format(self.name)
q = PriorityQueue()
q.push(Item('1'), 1)
q.push(Item('2'), 5)
q.push(Item('3'), 4)
q.push(Item('4'), 1)
print(q.pop())
# Item('2')
# Item('3')
# Item('1')
# Item('4')
heap 自定义排序,重写 __lt__
方法
SHOWMORE
import heapq
class P():
def __init__(self,a,b):
self.a = a
self.b = b
def __lt__(self, other):
if self.b<other.b:
return True
else:
return False
def p(self):
print(self.a,self.b)
a = P(3,1)
b = P(2,3)
c = P(10,0)
d = P(3,1)
h = []
heapq.heappush(h,a)
heapq.heappush(h,b)
heapq.heappush(h,c)
heapq.heappop(h).p()
10 0
# hash 哈希表
dict
和 defaultdict
还有 collections.Counter
三个的用法
# dict 字典
- 字典是默认的 python 数据类型使用
{}
进行标识,是一个无序的key-value
集合 - key 必须是不可变类型,使用
hash(x)
来判断 x 是否是一个可变的数据类型 - 同一个字典中
key
必须是唯一的
创建方法:
大括号形式
dict1 = {'name': 'python', 'age': 20}
使用内置方法 dict()
dict2 = dict(name='p', age=3)
使用字典推导式
dict3 = {x: x**2 for x in {1, 4, 2, 8}}
常用的三个方法 keys()
, values()
, items()
分别代表键,值,对
直接使用 list(dict)
得到的是一个包含所有 key 的列表
修改和访问:
dict1 = dict()
dict1['age'] = 20
dict1.setdefault('name', "fengwei")
遍历:
for k, v in dict1.items():
print(k, v)
访问某一个键:
print(dict1['name'])
print(dict1.get('name'))
删除某一个键:
dict1.pop('age')
del dict1['age']
清空
dict1.clear()
合并两个字典
dict1.update(dict2)
# Counter
本身用于统计给定的变量对象的次数
word_counter = Counter(text.split(" "))
print(word_count_dist.most_common(10)) # 输出出现次数最多的 10 个单词
c = Counter(a=4, b=2)
a = sorted(c.elements()) # 忽略小于 1 的
['a', 'a', 'a', 'a', 'b', 'b']
如果存在两个 counter 可以使用 substract 来进行减法操作
c = Counter(a=4, b=2, c=0, d=-2)
d = Counter(a=1, b=2, c=3, d=4)
c.subtract(d)
print(c)
# Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
还有以下方法
# 求和
sum(c.values())
# 清空 Counter
c.clear()
# 转换为 列表
list(c)
# 转换为 集合
set(c)
# 转换为 字典
dict(c)
# 键值对
c.items()
# 返回非零正数
+c
# 返回负数
-c
from collections import Counter
c = Counter(cats=4, flower=2, dogs=8)
print(sum(c.values()))
print(c.most_common()[:-3:-1])
# 输出出现频次最小的 2 个 key-value 对
# defaultdict
因为 Counter 的问题是数值必须是整数,本身就是用来拥挤数量,因此如果需要的 value 是字符串,列表,或者元组,就不能使用 Counter 了
defaultdict 相比于 dict 的最大的区别就是可以设置默认的数值,即便 key 不存在
s = [('color', 'blue'), ('color', 'orange'), ('fruit', 'banana')]
d = defaultdict(list)
# d = defaultdict(set)
for k, v in s:
d[k].append(v)
# d[k].add(v)
print(d)
# string 字符串
print(r"origin string")
print("""\
Usage: thing [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
""")
还有这个连接的规则:
print('py'
'thon' * 3)
# string 常见操作
strip(x)
当包含参数 x 表示删除句首或句末 x 的部分,否则就是删除举手和句末的空白字符。可以根据需要调用lstrip()
和rstrip()
分别删除句首或句末的空白字符split() rsplit()
str.split(str="", num=string.count(str))
- str – 分隔符,默认为所有的空字符,包括空格、换行 (\n)、制表符 (\t) 等。
- num – 分割次数。
返回分割之后的字符串列表
splitlines()
以换行为分割符进行分割,默认参数是 False,True 参数代表结果中保留换行符(靠左保留)。
join()
'sep'.join(seq)
- sep:分隔符。可以为空
- seq:要连接的元素序列、字符串、元组、字典
返回值:返回一个以分隔符 sep 连接各个元素后生成的字符串
replace(old, new[, max])
将 old 替换为 new ,不超过 max 次index()
查找指定字符串的起始位置startwith() / endwith()
分别判断字符串是否以某个字符串为开始,或者结束find()
返回最左端的索引,找不到返回 -1, 可以指定范围 start, endupper() * lower()
swapcase(), isspace(), isdigit(), isalpha(), isalnum(), isupper(), islower()
# fuction
def fib(n):
""" fib function
function document rule
"""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
# arguments 函数参数
参数传递规则: (python 中的一切都是对象)
如果传递的参数是不可变类型,类似于 cpp 中的值传递,传递的只是 a 的值,没有影响 a 对象本身的状态
如果传递的参数是可变的类型,例如一个 list, dict 那么就是类似于 cpp 中的引用传递,修改之后外部的 list, dict 也会受到影响
位置参数
位置参数必须按照正确的顺序传入函数中,调用的时候的数量必须和声明的时候相同
不加任何修饰符
- 默认参数
添加 =v
的修饰,表示默认参数,在定义函数的时候事先赋予一个默认的数值,调用函数的时候可以不需要传递值给默认参数
def function_name(arg1, arg2=v):
"""docstring"""
statement
- 可变参数
使用 *
进行修饰,就是输入参数的数量可以 是从 0 个到 任意多个,他们会自动组装为元组装入被修饰的变量
- 关键字参数
使用 **
进行修饰,和可变参数类似,不同的是,不会自动组装为一个元组,而是组装为一个字典
传入方式:
def print_info(name, age=18, height=178, *args, **kwargs):
print_info('fengwei', 20, 188, 'c++', 'python', birth='2002/01/20', weight=145)
keyword: {'birth': '2002/01/20', 'weight': 145}
- 命名关键字参数
使用 *,nkw
修饰这个参数的作用是限制调用者可以传递的参数名字
# 装饰器
内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。
装饰器本质上是一个 Python 函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
如何理解 Python 装饰器? - 刘志军的回答 - 知乎 (opens new window)
# lambda function
basic usage
def make_lambda(n):
return lambda x: x + n
f = make_lambda(10)
f(1)
f(2)
在 sort 中使用 lambda 函数
pairs = [(1, 'one'), (4, 'four'), (2, 'two'), (3, 'three') ]
pairs.sort(key=lambda pair: pair[0])
print(pairs)
# built in function
一些常用的内置函数
# enumerate()
在序列中循环时,用 enumerate()
函数可以同时取出位置索引和对应的值:
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe
在 enumerate 中添加第二个参数,可以指定具体的下标起始位置
# zip () 解构
同时循环两个或多个序列时,用 zip()
函数可以将其内的元素一一匹配:
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print('What is your {0}? It is {1}.'.format(q, a))
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
同时,可以使用 *
作为解构语句的中间变量修饰
>>> *trailing, current = [10, 8, 1, 4, 2, 8, 5, 7]
>>> trailing
[10, 8, 1, 4, 2, 8, 5]
>>>
>>> current
7
又比如只想要一个列表中的首部和尾部的几个元素,可以使用星号解压语法操作
record = ('fw', 50, 123.45, (12, 18, 2002))
name, *_, (*_, year) = record
# fw 2002
例如使用星号解压来实现递归算法
>>> def sum(items):
... head, *tail = items
... return head + sum(tail) if tail else head
...
>>> sum(items)
36
>>>
# reverse()
逆向循环序列时,先正向定位序列,然后调用 reversed()
函数:
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
1
# random()
采用 random 模块可以对一个列表随机采样 n 个元素
import random
my_list = ['a', 'b', 'c', 'd', 'e']
num_samples = 2
samples = random.sample(my_list, num_samples)
print(samples)
# [ 'a', 'e'] this will have any 2 random values
# sorted()
sorted () 都不会改变列表本身的顺序,只是对列表临时排序,并返回一个新的列表对象;
相反,列表本身的 sort () 会永久性改变列表本身的顺序。
list5 = [3, 1, 4, 2, 5]
print('list5:', list5)
# use sorted
list6 = sorted(list5)
print('list6=sorted(list5), list5={}, list6={}'.format(list5, list6))
# use list.sort()
list5.sort()
print('list5.sort(), list5: ', list5)
使用 set () 去除序列中的重复元素。使用 sorted () 加 set () 则按排序后的顺序,循环遍历序列中的唯一元素:
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
... print(f)
...
apple
banana
orange
pear
使用 sorted 不区分大小写安装小写字母从小到大的进行排序
sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
排序结构体:
>>> 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)]
使用 operator 模块中的函数
>>> 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)]
同 key 的使用方式相同,添加 reverse=True
可以逆序排序
排序保证是稳定的
# IO
# input
按照 int 格式输入:
a = int(input())
int 数据中间空格分割
a, b = map(int, input().split(' '))
读入数组:
d = list(map(float, input().split(' ')))
# output
C 格式的 print:
print("string: %.2lf" % (a))
输出不换行:
print(i, end=' ')
Python 格式的输出:
print('What is your {0}? It is {1}.'.format(q, a))
# match 关键字
after python 3.10 version
def http_error(status):
match status:
case 400:
return "Bad request"
case 401 | 403 | 404:
return "Not allowed"
case _:
return "Something's wrong with the internet"
注意 match 中的 |
操作符和 _
通配符的使用
match 在枚举中的使用:
from enum import Enum
class Color(Enum):
RED = 'red'
GREEN = 'green'
BLUE = 'blue'
color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))
match color:
case Color.RED:
print("I see red!")
case Color.GREEN:
print("Grass is green")
case Color.BLUE:
print("I'm feeling the blues :(")
# class
class Test:
staticVar = 1
def __init__(self, *args, **kwargs):
self.name = "test"
pass
# __repr__
和 __str__
内置函数 repr()
能够把对象用字符串的形式表达出来
repr()
就是通过 __repr__
方法来得到一个对象的字符串表示形式
repr 返回的就是正式的字符串的表示,而 stre 返回的是非正式的
str(4) == str("4") # True
repr(4) == repr("4") # False
# yield
为自定义类添加 迭代器访问:
义一个 __iter__()
方法来返回一个带有 __next__()
方法的对象。 如果类已定义了 __next__()
,则 __iter__()
可以简单地返回 self:
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
使用生成器:
def reverse(date):
for index in range(len(data) - 1, -1, -1):
yeild date[index]
for char in reverse('golf'):
print(char)
可以用生成器来完成的操作同样可以基于类的迭代器来完成。 但生成器的写法更为紧凑,因为它会自动创建 __iter__()
和 __next__()
方法。
生成器表达式:
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product
260
# module
__name__
可以获取模块名字
if __name == "__main__":
Python 只把含 __init__.py
文件的目录当成包。这样可以防止以 string
等通用名称命名的目录,无意中屏蔽出现在后方模块搜索路径中的有效模块。 最简情况下, __init__.py
只是一个空文件,但该文件也可以执行包的初始化代码,或设置 __all__
变量
__all__
用来设置使用 from .. import *
时具体导入的函数
__all__ = ["echo", "surround", "reverse"]
# 技巧
# sizeof
可以使用 sys.getsizeof () 检查一个对象的内存使用量
import sys
num = 21
print(sys.getsizeof(num))
# In Python 2, 24
# In Python 3, 28
# 计算代码执行时间
采用 time 模块来计算一段代码的执行时间,例子如下:
import time
start_time = time.time()
# Code to check follows
a = [0 for i in range(100000000)]
# a = [0] * 100000000
print(a[10])
# Code to check ends
end_time = time.time()
time_taken_in_micro = (end_time - start_time) * (10 ** 6)
print(time_taken_in_micro, "ms")
# 展平元素为列表的列表
有时候并确定一个列表中的深度有多深,所以你只想简单的将所有元素都放在一个列表中,实现技巧代码如下所示:
from iteration_utilities import deepflatten
# 列表只有一层深度的情况,采用这个函数
def flatten(l):
return [item for sublist in l for item in sublist]
l = [[1,2,3],[3]]
print(flatten(l))
# [1, 2, 3, 3]
# 不知道列表的深度的情况
l = [[1,2,3],[4,[5],[6,7]],[8,[9,[10]]]]
print(list(deepflatten(l, depth=3)))
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 其他
参考资料: