随手记录日常学习和工作中学到或用到的python的“小知识”,“小飞刀”,便于自己随时查阅。若碰巧也对网友们也能有点帮助和启发,那纯属巧合^-^
字典是存储{key: value}对的数据结构,python中的字典是对抽象的哈希表数据结构的实现。当字典中所存储的value为数值时,如何确定拥有最大(当然,最小也一样)数值的key呢?
最naive的方法当然是遍历字典的key,然后通过比较确定对应最大数值的key。
可以用python 内置的max()函数来实现这一目的。
myDict = {'one': 24, 'two': 13, 'three': 54, 'four': 9}
keyWithMaxValue = max(myDict, key=myDict.get)
print(keyWithMaxValue)
运行结果:three
经常刷leetcode的伙伴们可能碰到过这个问题。
比如说,针对python解leetcode会给一下如下所示的Class solution和函数接口示例(定义这个接口是为了方便自动判题):
class Solution:
def robSlow(self, nums: List[int]) -> int:
但是把这个template复制到本地进行解题调试(向我这样的渣渣基本没有勇气直接在leetcode页面直接coding并提交),就蹦出上面这样的错误,这是咋回事呢?
答案的关键在于:Typing package
Typing defines a standard notation for Python function and variable type annotations. The notation can be used for documenting code in a concise, standard format, and it has been designed to also be used by static and runtime type checkers, static analyzers, IDEs and other tools.
Typing为Python函数和变量类型注解定义了一套标准的符号体系。这一符号体系可以用于以精简、标准的格式进行代码的文档化。它也被静态以及运行时类型检查器、静态分析器、IDEs以及其它工具所使用。
由于python在具体使用时,尤其是在函数参数中,对于变量的类型并不会过多关注,虽然更加方便,但会使代码的易读性变差,有时候自己都不知道传入的是什么参数。因此在python3中引入了一个typing模块,这个模块可以很好解决这个问题。在python2中是无法实现参数类型说明的。
Typing模块的作用:
(1) 提供类型检查的参照,防止运行时出现参数和返回值类型不对的情况
(2) 作为开发文档附加说明,方便使用函数时传入和返回正确的参数,利于开发效率
Typing常用类型如下所示:
int,long,float: 整型,长整形,浮点型;
bool,str: 布尔型,字符串类型;
List, Tuple, Dict, Set:列表,元组,字典, 集合;
Iterable,Iterator:可迭代类型,迭代器类型;
Generator:生成器类型
所以,标题所示的那个问题的解决方案就是导入Typing包。这里需要的是List,所以可以以以下方式导入:
from typing import List
class Solution:
def robSlow(self, nums: List[int]) -> int:
Often, when dealing with iterators, we also get a need to keep a count of iterations. Python eases the programmers’ task by providing a built-in function enumerate() for this task.
Enumerate() method adds a counter to an iterable and returns it in a form of enumerating object. This enumerated object can then be used directly for loops or converted into a list of tuples using the list() method.
对于一个可迭代数据对象(如列表、元组或字符串),基本的遍历方式有两种,如下所示:
a = 'I am a python fan'
for k in range(len(a)):
print(a[k],end=' ')
print('\n')
for c in a:
print(c,end=' ')
print('\n')
两者都会输出:I a m a p y t h o n f a n
enumerate() 函数提供了一个更紧凑的方式,可以将遍历对象中的元素及其遍历序号组合在一起输出,一般用在 for 循环当中。如下例所示:
for k,c in enumerate(a):
print('{0}:{1}'.format(k,c))
print('\n')
缺省地,遍历序号是从0开始。但是也可以通过start参数来指定从任意某个整数开始计数。如下例通过start设定为-4表示遍历计数器从-4开始。注意,元素本身还是从头开始的,受影响的只是计数器。
for k,c in enumerate(a, start=-4):
print('{0}:{1}'.format(k,c))
print('\n')
也可以直接将enumerated object转换为list,如下所示:
enumobj = enumerate(a);
print(list(enumobj))
有三种方法。
(1) By type constructor: list(your_iterator)
(2) Using iterable unpacking operator "*": [*your_iterator]
(3)Using list comprehension: [k for k in your_iterator]
如以下例所示:
myIterator = iter(range(10))
print('Iterator unpacking operator: ',[*myIterator])
print('List Comprehension: ',[i for i in myIterator])
print('Type constructor: ',list(myIterator))
输出结果如下:
Iterator unpacking operator: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
List Comprehension: []
Type constructor: []
咦,有没有发现什么不对劲?如果你有点吃鲸那么你不是孤独的,因为我已经被吓了一跳。后面两条语句怎么打印出一个空的列表了呢?我做了实验,发现这三条打印语句不管怎么排序,只有第一条能打印出完整的列表,后面两条都是空的。这个我还没有找到解释,不过我猜测是这样的:Iterator是个消耗品,使用了就没有了。跟真正的list不一样!所以第一条print语句执行完后,myIterator就变成了空列表了。。。
如果安装了python,测试一台机器是big endian还是little endian的最简单的方法是:
from sys import byteorder
print(byteorder)
在C/C++中可以用如下代码段进行测试(ref:c - Little vs Big Endianess: How to interpret the test - Stack Overflow):
int n = 1;
// little endian if true
if(*(char *)&n == 1) {...}
有以下几种初始化set的方法
(1) 使用集合构造函数(constructor). 如下,可以利用list、tuple或者string来创建并同时初始化set,如果没有传入初始化参数的话则创建一个空的set
s = set((1, 2, 3)) # create set from tuple
s = set([1, 2, 3]) # create set from list
s = set('ABC') # create set from string
s = set() # Create an empty set
(2) 使用{}进行set创建及初始化
s = {1, 2, 3}
print(s) # {1, 2, 3}
但是要注意的是,这种方式不能用于创建空的set。因为空的{}创建的是dict!如下例所示:
s = {}
print(type(s)) # <class 'dict'>
(3) Using iterable unpacking operator
x = [1, 2, 3] # list
s = {*x}
print(s) # { 1, 2, 3}
用bin()将一个整数转换为二进制数表示转换得到的字符串中前面的0会被忽略掉。
例:bin(14) --> '0b1110'
有没有什么办法能够保留前面0,生成固定长度的二进制字符串的表示呢?用format()函数可以实现这一点。
format(14,'#016b') # Output: '0b00000000001110'
The#makes the format include the0bprefix, and the010size formats the output to fit in 10 characters width, with0padding; 2 characters for the0bprefix, the other 8 for the binary digits.
This is the most compact and direct option.
在以下参考链接中还有一些更复杂的应用选项,请参考。
Ref:Convert to binary and keep leading zeros
二进制、八进制和十六进制分别用0b, 0o, 0x开头,b,o和x不区分大小写。
a = 0o762
b = 0b101
c = 0x1d8
print('a={0}, b={1}, c={2}'.format(a,b,c))
输出:a=498, b=5, c=472
分别用bin()、oct()和hex()函数可以将整数转换为二进制、八进制和十六进制的表示。但是要注意的是,这些函数转换输出的结果是字符串。
print(bin(c))
print(oct(a))
print(hex(b))
print(type(a), type(bin(a)))
输出:
0b111011000
0o762
0x5
<class 'int'> <class 'str'>
用eval函数可以将bin()、oct()和hex()转换生成的字符串的表示转换会它原本的值。
当然,也可以用int()以强制转换的方式将字符串表示转换为整数值。int()的输入参数的形式与eval()不同,int()接收两个参数,第一个是去掉前缀的字符串,第二个参数指定进制。int()还有另一种参数传递方式,就是将第2个参数置为0,则第一个参数可以用带前缀的字符串。
print(eval(bin(1276)))
print(eval(oct(1276)))
print(eval(hex(1276)))
print(int(bin(1276)[2:],2))
print(int(oct(1276)[2:],8))
print(int(hex(1276)[2:],16))
print(int(bin(1276),0))
print(int(oct(1276),0))
print(int(hex(1276),0))
以上这9条语句都将打印同样的结果:1276
int()还可以进行任意进制数据的转换。
print(int('J', 21))
print(int('G', 17))
print(int('GF', 17))
输出:1916287