在这个例子中我们用到了一种特殊的函数:lambda表达式。Lambda表达式在Python中是一种匿名函数,lambda关键字后面跟输入参数,然后冒号后面是返回值(的表达式),比如上边例子中就是一个取下标1元素的函数。当然,还是那句话,万物皆对象,给lambda表达式取名字也是一点问题没有的:
some_ops = lambda x, y: x + y + x*y + x**y
some_ops(2, 3) # 2 + 3 + 2*3 + 2^3 = 19
生成器(Generator)
生成器是迭代器的一种,形式上看和函数很像,只是把return换成了yield,在每次调用的时候,都会执行到yield并返回值,同时将当前状态保存,等待下次执行到yield再继续:
# 从10倒数到0
def countdown(x):
while x >= 0:
yield x
x -= 1
for i in countdown(10):
print(i)
# 打印小于100的斐波那契数
def fibonacci(n):
a = 0
b = 1
while b < n:
yield b
a, b = b, a + b
for x in fibonacci(100):
print(x)
生成器和所有可迭代结构一样,可以通过next()函数返回下一个值,如果迭代结束了则抛出StopIteration异常:
a = fibonacci(3)
print(next(a)) # 1
print(next(a)) # 1
print(next(a)) # 2
print(next(a)) # 抛出StopIteration异常
Python3.3以上可以允许yield和return同时使用,return的是异常的说明信息:
# Python3.3以上可以return返回异常的说明
def another_fibonacci(n):
a = 0
b = 1
while b < n:
yield b
a, b = b, a + b
return "No more ..."
a = another_fibonacci(3)
print(next(a)) # 1
print(next(a)) # 1
print(next(a)) # 2
print(next(a)) # 抛出StopIteration异常并打印No more消息
类(Class)
Python中的类的概念和其他语言相比没什么不同,比较特殊的是protected和private在Python中是没有明确限制的,一个惯例是用单下划线开头的表示protected,用双下划线开头的表示private:
class A:
"""Class A"""
def __init__(self, x, y, name):
self.x = x
self.y = y
self._name = name
def introduce(self):
print(self._name)
def greeting(self):
print("What's up!")
def __l2norm(self):
return self.x**2 + self.y**2
def cal_l2norm(self):
return self.__l2norm()
a = A(11, 11, 'Leonardo')
print(A.__doc__) # "Class A"
a.introduce() # "Leonardo"
a.greeting() # "What's up!"
print(a._name) # 可以正常访问
print(a.cal_l2norm()) # 输出11*11+11*11=242
print(a._A__l2norm()) # 仍然可以访问,只是名字不一样
print(a.__l2norm()) # 报错: 'A' object has no attribute '__l2norm'
类的初始化使用的是__init__(self,),所有成员变量都是self的,所以以self.开头。可以看到,单下划线开头的变量是可以直接访问的,而双下划线开头的变量则触发了Python中一种叫做name mangling的机制,其实就是名字变了下,仍然可以通过前边加上“_类名”的方式访问。也就是说Python中变量的访问权限都是靠自觉的。类定义中紧跟着类名字下一行的字符串叫做docstring,可以写一些用于描述类的介绍,如果有定义则通过“类名.__doc__”访问。这种前后都加双下划线访问的是特殊的变量/方法,除了__doc__和__init__还有很多,这里就不展开讲了。
Python中的继承也非常简单,最基本的继承方式就是定义类的时候把父类往括号里一放就行了:
class B(A):
"""Class B inheritenced from A"""
def greeting(self):
print("How's going!")
b = B(12, 12, 'Flaubert')
b.introduce() # Flaubert
b.greeting() # How's going!
print(b._name()) # Flaubert
print(b._A__l2norm()) # “私有”方法,必须通过_A__l2norm访问
map, reduce和filter
map可以用于对可遍历结构的每个元素执行同样的操作,批量操作:
map(lambda x: x**2, [1, 2, 3, 4]) # [1, 4, 9, 16]
map(lambda x, y: x + y, [1, 2, 3], [5, 6, 7]) # [6, 8, 10]
reduce则是对可遍历结构的元素按顺序进行两个输入参数的操作,并且每次的结果保存作为下次操作的第一个输入参数,还没有遍历的元素作为第二个输入参数。这样的结果就是把一串可遍历的值,减少(reduce)成一个对象:
reduce(lambda x, y: x + y, [1, 2, 3, 4]) # ((1+2)+3)+4=10
filter顾名思义,根据条件对可遍历结构进行筛选:
filter(lambda x: x % 2, [1, 2, 3, 4, 5]) # 筛选奇数,[1, 3, 5]
需要注意的是,对于filter和map,在Python2中返回结果是列表,Python3中是生成器。
列表生成(list comprehension)
列表生成是Python2.0中加入的一种语法,可以非常方便地用来生成列表和迭代器,比如上节中map的两个例子和filter的一个例子可以用列表生成重写为:
[x**2 for x in [1, 2, 3, 4]] # [1, 4, 9 16]
[sum(x) for x in zip([1, 2, 3], [5, 6, 7])] # [6, 8, 10]
[x for x in [1, 2, 3, 4, 5] if x % 2] # [1, 3, 5]
评论
查看更多