编程语言
首页 > 编程语言> > 流畅的Python第五章,一等函数笔记(未完,准备从一章开始看)。

流畅的Python第五章,一等函数笔记(未完,准备从一章开始看)。

作者:互联网

Python中又一个名称叫一等对象,满足以下条件的程序实体:

1、在运行时创建

2、能赋值给变量或数据结构中的元素

3、能作为参数传给函数

4、能作为函数的返回结果

所以Python中,正数、字符串、字典与函数都是一等对象。

5.1把函数当做对象:

把函数当做对象,通过简单的__doc__可以输出函数的说明。

In [55]: def demo(a,b): 
    ...:     '''返回a,b''' 
    ...:     return a,b 
    ...:                                                                                                                

In [56]: demo.__doc__                                                                                                   
Out[56]: '返回a,b'

In [57]:  

 通过高阶函数把函数传递进去。

def fact(n):
    '''returns n!'''
    return 1 if n < 2 else n * fact(n - 1)

print(list(map(fact, range(10))))

 

[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]

 fact就是传递进去的函数。

5.2高阶函数

接受函数为参数,或者把函数作为结果返回的函数为高阶函数(hight-order function)。

map,filter,reduce,包括sorted都是高阶,sorted的key可以接收函数.

按照这个定义,我们的闭包函数,装饰器函数,都可以称为高阶函数。

 

map,filter和reduce的现代替换品

map与filter因为列表生成式的使用,基本很多需要使用他们的地方都可以用列表生成式。

 

def fact(n):
    '''returns n!'''
    return 1 if n < 2 else n * fact(n - 1)

'''
接收函数为参数,或者把函数作为结果返回的函数是高阶函数。
所以,map,filter,reduce,sorted(因为key能接收函数)
'''

print(fact(10))

print(list(map(fact, range(10))))   # map需要传入函数fact

print([fact(i) for i in range(10)])   # 直接列表生成式,每个参数直接使用了函数fact,产生的返回值放入列表。

print(list(map(fact, filter(lambda n : n % 2, range(10)))))   # 在map的函数后面的可迭代对象进行了filter的过滤,需要能被2整除

# filter第一个只返回:后面条件成立的数值。
def condition(n):
    if n % 2 != 0:
        return n
print(list(map(fact, filter(condition, range(10)))))

print([fact(i) for i in range(10) if i % 2])     # 列表生成式第一个写函数或者参数,第二个写循环体,第三个写条件。
# 书中直接写if i % 2应该就是! % 2不能为0,这个写法更加精简。所以以后条件如果返回只要是真,写入就可以,生成的时候就会执行。
print([fact(i) for i in range(10) if i % 2 !=0])   # 如果我写,我一半写成这样。

 

 

/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/高级函数.py
3628800
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
[1, 6, 120, 5040, 362880]
[1, 6, 120, 5040, 362880]
[1, 6, 120, 5040, 362880]

Process finished with exit code 0

 reduce现在用的很少,一般用在求和上面。

from functools import reduce
from operator import add

def s_add(x, y):
    return x + y

print(reduce(add, range(100)))
print(reduce(s_add, range(100)))
print(sum(range(100)))

 

/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/t5.2.py
4950
4950
4950

Process finished with exit code 0

 归约函数all,any是蛮好的函数.

all(iterable)  里面的可迭代对象全部为真返回真。(有点像and)

any(iterable) 有一个真就返回真。 (有点像or)

a1 = '1232434'
a2 = [1, 2, 3, 0]
a3 = {'name': 'sidian', 'age': None}
a4 = (None, 9, 8)

print(a1, all(a1), any(a1))
print(a2, all(a2), any(a2))
print(a3, all(a3), any(a3))
print(a4, all(a4), any(a4))

 

1232434 True True
[1, 2, 3, 0] False True
{'name': 'sidian', 'age': None} True True
(None, 9, 8) False True

 

5.3匿名函数

lambda是Python表达式内创建匿名函数。然而Python简单的语法限制了lambda函数的定义题只能使用纯表达式。换句话说,lambda函数的定义体中不能赋值,也不能使用while和try等Python语句。

lambda(init:return),lambda函数通过分号相隔,前面是输入参数,后面是返回参数。

lambda语法是语法糖,更def一样,会创建可以调用的函数对象。

 

5.4可调用对象

可调用对象就是能用()的对像(里面有__call__的方法),可以用callable来测试是否是可调用对象,Python数据模型里面有7种可调用对象。

1、用户定义的函数

比如使用def或者lambda创建的对象。

2、内置函数

使用C语言显示的函数,比如len或time.strftime

3、内置方法

使用C语言实现的方法,比如dict.get

4、方法

在类的实体中定义的函数

5、类

在实例化类的使用,首先调用的是__call__,然后调用__new__创建对象,最后__init__来初始化对象。

6、类的实例

在类里面定义了__call__,那么实例就可以成为调用对象。

7、生成器

调用生成器函数可以返回一个生成器对象。

 

5.5 用户定义的可调用类型。

通过类里面给予定义函数__call__

import random

class BingCage:

    def __init__(self, items):
        self._items = list(items)     # 设置成私有变量
        random.shuffle(self._items)

    def pick(self):
        try:
            return self._items.pop()
        except IndexError:
            raise LookupError('pick from empty BingoCage')

    def __call__(self, *args, **kwargs):     # 让对象拥有call方法,能直接被调用
        return self.pick()

bingo = BingCage('abc')
for i in range(5):
    try:
        print(bingo.pick())
    except LookupError as e:
        print(e)

 

/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/t_5.5.py
b
c
a
pick from empty BingoCage
pick from empty BingoCage

Process finished with exit code 0

 

5.6 函数内省

函数有很多属性,我们通过dir来查看。

dir(lambda x : x[2])                                                                                           
Out[57]: 
['__annotations__',
 '__call__',
 '__class__',
 '__closure__',
 '__code__',
 '__defaults__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__get__',
 '__getattribute__',
 '__globals__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__kwdefaults__',
 '__le__',
 '__lt__',
 '__module__',
 '__name__',
 '__ne__',
 '__new__',
 '__qualname__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__']

 首先说一个,函数对象有__dict__属性,所以可以通过.或者setattr来进行属性赋值,这个我以前还真不知道。(但一般很少对函数对象进行属性赋值)

def demo(): 
    ...:     ... 
    ...:                                                                                                                

In [63]: demo.abc = 'abc'                                                                                               

In [64]: demo.__dict__                                                                                                  
Out[64]: {'abc': 'abc'}

In [65]: setattr(demo,'name','sidian')                                                                                  

In [66]: demo.name                                                                                                      
Out[66]: 'sidian'

In [67]: demo.__dict__                                                                                                  
Out[67]: {'abc': 'abc', 'name': 'sidian'}

In [68]:                                                                                                                

 下面列出函数独有,但对象没有的属性,我准备跟类也对比一下。

class C:
    ...

def func():
    ...

c = C()

print(set(dir(C)) - set(dir(func)))
print(set(dir(func)) - set(dir(C)))
print(set(dir(c)) - set(dir(func)))
print(set(dir(func)) - set(dir(c)))

 

/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/t_5.6.py
{'__weakref__'}
{'__annotations__', '__get__', '__globals__', '__call__', '__name__', '__qualname__', '__code__', '__kwdefaults__', '__defaults__', '__closure__'}
{'__weakref__'}
{'__annotations__', '__get__', '__globals__', '__call__', '__name__', '__qualname__', '__code__', '__kwdefaults__', '__defaults__', '__closure__'}
Hello sidian

Process finished with exit code 0

 从中可以看出来,对象或者类比函数对了一个属性__weakref__,我查了一些资料好像是关于垃圾回收相关,具体资料很少。

https://stackoverflow.com/questions/36787603/what-exactly-is-weakref-in-python这个链接有一些英文的答案。

但函数比对象多了很多属性。

标签:__,一章,函数,Python,range,第五章,def,print,fact
来源: https://www.cnblogs.com/sidianok/p/12044154.html