python简介

函数是第一类对象

在Python中,函数的行为类似于任何其他对象,例如int或list。这意味着您可以将函数用作其他函数的参数,将函数存储为字典值,或从另一个函数返回函数。这就产生了许多强大的函数使用方法。

def square(x):
    """Square of x."""
    return x*x

def cube(x):
    """Cube of x."""
    return x*x*x

将函数保存到字典中

# create a dictionary of functions

funcs = {
    'square': square,
    'cube': cube,
}
x = 2
print square(x)
print cube(x)

for func in sorted(funcs):
    print func, funcs[func](x)
# output
4
8
cube 8
square 4

有些数据类型,如字符串和元组,不能直接修改,称为不可变。整数或浮点数等原子变量总是不可变的。其他数据类型,如列表和字典,可以直接修改,称为可变数据类型。将可变变量作为函数参数传递可能会产生不同的结果,这取决于函数内部对变量所做的操作。

高阶函数 Higher-order functions

使用另一个函数作为输入参数或返回函数(HOF)的函数称为高阶函数。最常见的例子是mapfilter
map函数将一个函数应用于集合的每个成员

map(square, range(5))
#output
[0, 1, 4, 9, 16]

filter函数将判断应用于集合的每个成员,只保留判断为真的那些成员。

def is_even(x):
    return x%2 == 0

filter(is_even, range(5))
# output
[0, 2, 4]

reduce函数使用二进制运算符一次合并两个项来计算

def my_add(x, y):
    return x + y
# 通过reduce函数也可以实现同意的结果
reduce(my_add, [1,2,3,4,5])
# output 15

# 自定义函数也可以是HOFs

def custom_sum(xs, transform):
    """计算通过转化后的xs的和."""
    return sum(map(transform, xs))

xs = range(5)
print custom_sum(xs, square)
# output 30
print custom_sum(xs, cube)
# output 100
# 直接返回函数
def make_logger(target):
    def logger(data):
        with open(target, 'a') as f:
            f.write(data + '\n')
    return logger

foo_logger = make_logger('foo.txt')
foo_logger('Hello')
foo_logger('World')

匿名函数 Anonymous functions

当使用函数风格时,通常需要创建一些小的特定函数,这些函数执行有限的任务,作为HOF的输入,例如mapfilter 。在这种情况下,这些函数通常被写成匿名函数或lambda函数。如果您发现很难理解lambda函数在做什么,那么可能应该将其重写为常规函数。

# 使用标准函数

def square(x):
    return x*x

print map(square, range(5))
# output
[0, 1, 4, 9, 16]

# 使用匿名函数
print(map(lambda x: x*x, range(5))

# 这个函数在做什么
s1 = reduce(lambda x, y: x+y, map(lambda x: x**2, range(1,10)))
print(s1)
s2 = sum(x**2 for x in range(1,10))
# output都是285

纯函数 Pure functions

如果函数没有任何副作用,并且不依赖于全局变量,那么它们就是纯函数。纯函数类似于数学函数——每次给出相同的输入时,都会返回相同的输出。这对于减少bug和并行编程非常有用,因为每个函数调用都独立于任何其他函数调用,因此可以进行简单的并行化。

def pure(xs):
    """Make a new list and return that."""
    xs = [x*2 for x in xs]
    return xs

xs = range(5)
print("xs =", xs)
print(pure(xs))
print("xs =", xs)
# output 
xs = [0, 1, 2, 3, 4]
[0, 2, 4, 6, 8]
xs = [0, 1, 2, 3, 4]
# 这里定义一个“不纯”的函数
def impure(xs):
    for i, x in enumerate(xs):
        xs[i] = x*2
    return xs

xs = range(5)
print("xs =", xs)
print(impure(xs))
print("xs =", xs)
# output 
xs = [0, 1, 2, 3, 4]
[0, 2, 4, 6, 8]
# note here
xs = [0, 2, 4, 6, 8]
# Note that mutable functions are created upon function declaration, not use.
# This gives rise to a common source of beginner errors.

def f1(x, y=[]):
    """不要将空列表或其他可变结构作为默认值"""
    y.append(x)
    return sum(y)
print(f1(10)) # 10
print(f1(10)) # 20
print(f1(10, y =[1,2])) # 13
# Here is the correct Python idiom
def f2(x, y=None):
    """Check if y is None - if so make it a list."""
    if y is None:
        y = []
    y.append(x)
    return sum(y)
print(f2(10)) # 10
print (f2(10)) # 10
print (f2(10, y =[1,2])) # 13

递归函数Recursion function

递归函数是一个调用自身的函数。递归函数是算法开发中分而治之范式divide-and-conquer的非常有用的例子,是有限差分方程的直接表达式。然而,它们的计算效率很低,在Python中使用它们在实践中非常罕见。递归函数通常有一组基本情况,其中答案是显而易见的,可以立即返回,还有一组递归情况,它们被分成更小的部分,每个部分都被赋予递归调用的同一个函数。举几个例子可以更清楚地说明这一点。

# The factorial function is perhaps the simplest classic example of recursion.

def fact(n):
    """n的阶乘."""
    # base case
    if n==0:
        return 1
    # recursive case
    else:
        return n * fact(n-1)

print([fact(n) for n in range(10)])
# output
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
# The Fibonacci sequence is another classic recursion example
# 斐波那契序列是另一个经典的递归例子

def fib1(n):
    """Fib with recursion."""

    # base case
    if n==0 or n==1:
        return 1
    # recurssive caae
    else:
        return fib1(n-1) + fib1(n-2)

print([fib1(i) for i in range(10)])
# output
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
# In Python, a more efficient version that does not use recursion is
#在Python中,不使用递归的更高效版本是

def fib2(n):
    """Fib without recursion."""
    a, b = 0, 1
    for i in range(1, n+1):
        a, b = b, a+b
    return b

print([fib2(i) for i in range(10)])
# output
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
# Note that the recursive version is much slower than the non-recursive version
# 请注意,递归版本比非递归版本慢得多

%timeit fib1(20)
%timeit fib2(20)

# this is because it makes many duplicate function calls
# Note duplicate calls to fib(2) and fib(1) below
# fib(4) -> fib(3), fib(2)
# fib(3) -> fib(2), fib(1)
# fib(2) -> fib(1), fib(0)
# fib(1) -> 1
# fib(0) -> 1
#output
100 loops, best of 3: 5.64 ms per loop
100000 loops, best of 3: 2.87 µs per loop
def almost_quick_sort(xs):
    """Almost a quick sort."""

    # base case
    if xs == []:
        return xs
    # recursive case
    else:
        pivot = xs[0]
        less_than = [x for x in xs[1:] if x <= pivot]
        more_than = [x for x in xs[1:] if x > pivot]
        return almost_quick_sort(less_than) + [pivot] + almost_quick_sort(more_than)

xs = [3,1,4,1,5,9,2,6,5,3,5,9]
print(almost_quick_sort(xs))
[1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9, 9]

迭代器 Iterators

迭代器表示数值流。因为一次只消耗一个值,所以它们使用的内存非常少。使用迭代器对于处理太大而无法放入RAM的数据集非常有用。

 Iterators can be created from sequences with the built-in function iter()

xs = [1,2,3]
x_iter = iter(xs)

print x_iter.next() # 1
print x_iter.next() # 2
print x_iter.next() # 3
print x_iter.next() # 报错
# Most commonly, iterators are used (automatically) within a for loop
# which terminates when it encouters a StopIteration exception

x_iter = iter(xs)
for x in x_iter:
    print (x)

生成器 Generators

# Functions containing the 'yield' keyword return iterators
# After yielding, the function retains its previous state

def count_down(n):
    for i in range(n, 0, -1):
        yield i
counter = count_down(10)
print(counter.next())
print(counter.next())
for count in counter:
    print (count)
10
9
8 7 6 5 4 3 2 1
#还可以使用“生成器表达式”创建迭代器
#其编码类似于列表生成器,但带有括号
#代替方括号
xs1 = [x*x for x in range(5)]
print (xs1)
# output
[0, 1, 4, 9, 16]
xs2 = (x*x for x in range(5))
print xs2
# output
<generator object <genexpr> at 0x1130d09b0>

for x in xs2:
    print(x)
0 1 4 9 16
#许多内置Python函数返回迭代器
#包括文件处理程序
#因此,使用下面的习惯用法,您可以逐行处理1TB的文件
#在你的笔记本电脑上没有任何问题
#在Pyhton 3中,map和filter返回iterators,而不是list
for line in open('foo.txt'):
    print(line)

foo.txt这个是前面保存的文件。

Hello
World
Hello
World
Hello
World
Hello
World

生成器和推导式 Generators and comprehensions

print((x for x in range(10)))
print([x for x in range(10)])
print({x  for x in range(10)})
print({x: x for x in range(10)})
# output
<generator object <genexpr> at 0x0000013FC931A2E0>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}

实用程序-枚举、zip和三元if-else运算符 Utilites - enumerate, zip and the ternary if-else operator

两个有用的函数和一个不同寻常的运算符。

#在许多编程语言中,循环使用索引。
#这在Python中是可能的,但使用枚举函数更为惯用。
# using and index in a loop
xs = [1,2,3,4]
for i in range(len(xs)):
    print(i, xs[i])
#output
0 1
1 2
2 3
3 4

# using enumerate
for i, x in enumerate(xs):
    print(i, x)
#output
0 1
1 2
2 3
3 4
#当需要迭代多个列表中匹配的元素时,zip非常有用
# 当最短列表用尽时,zip停止
xs = [1, 2, 3, 4]
ys = [10, 20, 30, 40]
zs = ['a', 'b', 'c', 'd', 'e']

for x, y, z in zip(xs, ys, zs):
    print (x, y, z)
1 10 a
2 20 b
3 30 c
4 40 d

对于列表理解,三元if-else运算符有时非常有用

[x**2 if x%2 == 0 else x**3 for x in range(10)]
# output
[0, 1, 4, 27, 16, 125, 36, 343, 64, 729]

装饰器 Decorators

装饰器是一种HOF,它接受一个函数并返回一个包装函数,该函数提供了额外的有用属性。
Examples:

  • logging
  • profiling
  • Just-In-Time (JIT) compilation
# Here is a simple decorator to time an arbitrary function

def func_timer(func):
    """Times how long the function took."""

    def f(*args, **kwargs):
        import time
        start = time.time()
        results = func(*args, **kwargs)
        print "Elapsed: %.2fs" % (time.time() - start)
        return results

    return f
# There is a special shorthand notation for decorating functions

@func_timer
def sleepy(msg, sleep=1.0):
    """Delays a while before answering."""
    import time
    time.sleep(sleep)
    print msg

sleepy("Hello", 1.5)
Hello
Elapsed: 1.50s

The itertools module

这为使用迭代器提供了许多基本函数。permuations置换和combinations组合生成器对于模拟可能特别有用,而groupby生成器对于数据分析非常有用。

from itertools import cycle, groupby, islice, permutations, combinations

print list(islice(cycle('abcd'), 0, 10))

# output 
['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b']
# 根据字符串长度分组
animals = sorted(['pig', 'cow', 'giraffe', 'elephant',
                  'dog', 'cat', 'hippo', 'lion', 'tiger'], key=len)
for k, g in groupby(animals, key=len):
    print k, list(g)
# output
3 ['pig', 'cow', 'dog', 'cat']
4 ['lion']
5 ['hippo', 'tiger']
7 ['giraffe']
8 ['elephant']

print [''.join(p) for p in permutations('abc')]
# output
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

print [list(c) for c in combinations([1,2,3,4], r=2)]
#output
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

翻译自 https://people.duke.edu/~ccc14/sta-663/FunctionsSolutions.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值