ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-12-15 14:55:59  阅读:316  来源: 互联网

标签:__ 一章 函数 Python range 第五章 def print fact


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有