您当前的位置:首页 > 计算机 > 编程开发 > Python

Python tips:Typing包、enumerate,进制转换等

时间:12-28来源:作者:点击数:

前言

随手记录日常学习和工作中学到或用到的python的“小知识”,“小飞刀”,便于自己随时查阅。若碰巧也对网友们也能有点帮助和启发,那纯属巧合^-^

1. 字典中拥有最大映射值的键的搜索

字典是存储{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

2.NameError: name ‘List’ is not defined

经常刷leetcode的伙伴们可能碰到过这个问题。

比如说,针对python解leetcode会给一下如下所示的Class solution和函数接口示例(定义这个接口是为了方便自动判题):

class Solution:
    def robSlow(self, nums: List[int]) -> int:

但是把这个template复制到本地进行解题调试(向我这样的渣渣基本没有勇气直接在leetcode页面直接coding并提交),就蹦出上面这样的错误,这是咋回事呢?

答案的关键在于:Typing package

2.1 Typing包是什么?

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以及其它工具所使用。

2.2 Typing包要解决什么问题?

由于python在具体使用时,尤其是在函数参数中,对于变量的类型并不会过多关注,虽然更加方便,但会使代码的易读性变差,有时候自己都不知道传入的是什么参数。因此在python3中引入了一个typing模块,这个模块可以很好解决这个问题。在python2中是无法实现参数类型说明的。

Typing模块的作用:

(1) 提供类型检查的参照,防止运行时出现参数和返回值类型不对的情况

(2) 作为开发文档附加说明,方便使用函数时传入和返回正确的参数,利于开发效率

Typing常用类型如下所示:

int,long,float: 整型,长整形,浮点型;

bool,str: 布尔型,字符串类型;

List, Tuple, Dict, Set:列表,元组,字典, 集合;

Iterable,Iterator:可迭代类型,迭代器类型;

Generator:生成器类型

2.3 解决方案

所以,标题所示的那个问题的解决方案就是导入Typing包。这里需要的是List,所以可以以以下方式导入:

from typing import List

class Solution:
    def robSlow(self, nums: List[int]) -> int:

3. enumerate(iterable, start=0)

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))

4. 将一个迭代器转换为list

有三种方法。

(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就变成了空列表了。。。

5. Endian Test

如果安装了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) {...}

6. Initialize a Python set

有以下几种初始化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}

7.Convert to binary and keep leading zeros

用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

8. 各种进制的表示和转换

8.1 表示

二进制、八进制和十六进制分别用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

8.2 转换

分别用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'>

8.3 评估字符串表示的值

用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

8.4 任意进制

int()还可以进行任意进制数据的转换。

print(int('J', 21))
print(int('G', 17))
print(int('GF', 17))

输出:1916287

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门