Python几个内置函数

zip()

在多个迭代器上并行迭代,从每个迭代器返回一个数据项组成元组。

1
2
3
4
5
6
7
8
9
10
a = [1, 2, 3]
b = ["a", "b", "c"]
c = zip(a,b)
for idx, (i,j) in enumerate(c):
print(idx, i, j)

# 输出如下
0 1 a
1 2 b
2 3 c

这里需要注意的是

  1. 默认情况下,zip() 在最短的迭代完成后停止。较长可迭代对象中的剩余项将被忽略,结果会裁切至最短可迭代对象的长度
  2. 通常 zip()用于可迭代对象等长的情况下。这时建议用 strict=True 的选项(3.10版本后)。输出与普通的 zip()相同,但会检查是否等长,不等长会报ValueError

map()

map(function,iterable,…)

返回一个将 function 应用于 iterable 中每一项并输出其结果的迭代器。

如果传入了额外的 iterable 参数,function 必须接受相同个数的实参并被应用于从所有可迭代对象中并行获取的项。

1
2
3
4
5
6
7
8
def square(x) :            # 计算平方数
return x ** 2

input_ = [1,2,3,4,5]
out_ = map(square, input_)
print(list(out_)) # 计算列表各个元素的平方
# 输出如下:
[1, 4, 9, 16, 25]

也可以使用匿名函数作为map的第一个参数

1
2
3
list(map(lambda x:x**2, [2,4,6]))
# 输出如下:
[4, 16, 36]

在NLP中常用的将字符串列表转为float

1
2
3
4
str_ = "0.1,0.2,0.3"
list(map(float, str_.split(",")))
# 输出为:
[0.1, 0.2, 0.3]

当有多个迭代对象时

1
2
3
4
list(map(lambda x, y : (x**y,x+y), [2,4,6],[3,2,1]))

# 输出如下:
[(8,5),(16,6),(6,7)]

当有多个可迭代对象时,最短的可迭代对象耗尽则整个迭代就将结束。

1
2
3
4
list(map(lambda x, y : (x**y,x+y), [2,4,6],[3,2,1,23,4]))

# 输出如下:
[(8,5),(16,6),(6,7)]

filter()

iterable 中函数 function 返回真的那些元素,构建一个新的迭代器。

iterable 可以是一个序列,一个支持迭代的容器,或一个迭代器。

如果 functionNone ,则会假设它是一个身份函数,即 iterable 中所有返回假的元素会被移除。

注意: filter(function, iterable) 相当于一个生成器表达式,当 function 不是 None 的时候为 (item for item in iterable if function(item))

1
2
3
list(filter(lambda x:x>3, range(10)))
# 输出如下
[4, 5, 6, 7, 8, 9]

function 是 None 的时候为 (item for item in iterable if item)

注意:这里的0, “”, None, [], {}都为None

1
2
3
4
5
6
7
8
9
10
11
12
13
list(filter(None, [0, "1", "2", "3"]))
for i in [0, "", None, [], {}]:
if i:
print(f"{i} not None")
else:
print(f"{i} is None")

# 输出如下
0 is None
is None
None is None
[] is None
{} is None

callable()

检测对象是否可被调用

对于函数、方法、lambda 函式、 类以及实现了 __call__ 方法的类实例, 它都返回 True

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def play():
print("play")
print(f"def callable {callable(play)}")

class Person(object):
def __init__(self):
self.age = None

print(f"class callable {callable(Person)}")

Person_ = Person()
print(f"class object callable {callable(Person_)}")

class Person(object):
def __init__(self):
self.age = None

def __call__(self):
print("this is a call method!")

Person_ = Person()
print(f"class object callable {callable(Person_)}")

# 输出如下:
def callable True
class callable True
class object callable False
class object callable True

__call__

Python中的函数是一级对象。

Python中的函数的引用可以作为输入传递到其他的函数/方法中,并在其中被执行。
而Python中类的实例(对象)可以被当做函数对待。也就是说,我们可以将它们作为输入传递到其他的函数/方法中并调用他们,正如我们调用一个正常的函数那样。

为了将一个类实例当做函数调用,我们需要在类中实现__call__()方法。

__call__(self, *args, **kwargs) 如果类实现了这个方法,相当于把这个类型的对象当作函数来使用,相当于 重载了括号运算符

假设x是X类的一个实例。那么调用x.__call__(1, 2)等同于调用x(1, 2)。这个实例本身在这里相当于一个函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person(object):
def __init__(self, age):
self.age = age

def __call__(self, name):
self.name = name
print("this is a call method!")
return self.name * 2

Person_ = Person(5)
print(Person_("heng"))
print(Person_.__call__("heng"))
print(Person_.age)
# 输出如下:
this is a call method!
hengheng
this is a call method!
hengheng
5

super()

super()函数用于提供对父类或兄弟类的方法和属性的访问。

super()函数返回一个代表父类的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Parent:
def __init__(self, txt):
self.message = txt

def print_message(self):
print(self.message)


class Child(Parent):
def __init__(self, txt):
super().__init__(txt)


x = Child("Hello, and welcome!")
x.print_message()

isinstance()

isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
isinstance() 与 type() 区别:

  • type() 不会认为子类是一种父类类型,不考虑继承关系。
  • isinstance() 会认为子类是一种父类类型,考虑继承关系。

如果要判断两个类型是否相同推荐使用 isinstance()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a = 0
print(f"a is int : {isinstance(a, int)}")
print(f"a is str : {isinstance(a, str)}")

class Person(object):
def __init__(self) -> None:
super().__init__()
self.age = None

class Heng(Person):
def __init__(self) -> None:
super().__init__()
self.age = None

Person_ = Person()
Heng_ = Heng()
print(f"heng is Person : {isinstance(Heng_, Person)}")
print(f"heng is Heng : {isinstance(Heng_, Heng)}")

# 输出如下:
a is int : True
a is str : False
heng is Person : True
heng is Heng : True

@classmethod

将一个方法封装成类方法。

该方法不需要实例化,不需要 self 参数,第一个参数是表示自身类的 cls 参数。

self 和cls 没有特别的含义,作用只是把参数绑定到普通的函数上, 不一定非得是self 或cls , 可以换成别的

可以用来调用类的属性,类的方法等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class A(object):
def m1(self, n):
print("self:", self, n, n)

@classmethod
def m2(cls, n):
print("cls:", cls, n)

@staticmethod
def m3(n):
pass

@classmethod
def m4(cls):
print(cls.m2(2))

def m5(self):
print(self.m1(4))

a = A()
a.m1(1)
A.m2(1)
A.m3(1)
A.m4()
a.m5()
# 输出如下:
self: <__main__.A object at 0x7ff484027c40> 1 1
cls: <class '__main__.A'> 1
cls: <class '__main__.A'> 2
None
self: <__main__.A object at 0x7ff484027c40> 4 4
None

如果希望在方法里面调用静态类,那么把方法定义成类方法是合适的,因为要是定义成静态方法,那么你就要显示地引用类A,这对继承来说不是一件好事情。

1
2
3
4
5
6
7
8
9
10
11
12
class A:
@staticmethod
def m1()
pass

@staticmethod
def m2():
A.m1() # bad

@classmethod
def m3(cls):
cls.m1() # good

参考:

  1. Python官方文档
  2. Python内置函数
  3. 标点符
  4. 菜鸟教程
  5. 知乎