把函数视作对象

本文介绍了Python中函数被视为对象的概念,包括函数的属性、高阶函数、匿名函数(lambda)、可调用对象、用户定义的可调用类型、函数内省以及参数处理方式。内容涉及map函数的应用、使用lambda进行排序、callable()函数的使用、用户自定义类的调用、生成器函数以及如何获取函数参数的信息。
摘要由CSDN通过智能技术生成

把函数视作对象

创建一个函数,并读取它的__doc__属性,再检查它的类型

>>> def factorial(n):
...     '''return n!'''
...     return 1 if n < 2 else n * factorial(n-1)
>>> factorial.__doc__
'return n!'
>>> factorial(40)
815915283247897734345611269596115894272000000000
>>> type(factorial)
<class 'function'>

__doc__ 属性用于生成对象的帮助文本。

通过别的名称使用函数,再把函数作为参数传递

>>> fact = factorial	# 将函数赋值给一个变量 然后通过变量名调用
>>> fact
<function factorial at 0x0310D340>
>>> fact(5)
120

>>> map(factorial, range(11))
<map object at 0x03108298>
>>> list(map(fact, range(11)))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

map 函数返回一个可迭代对象, 里面的元素是把第一个参数(一个函数),应用到第二个函数(一个可迭代对象,这里是range(11)中各个元素上得到的结果。

高阶函数

高阶函数:接受函数为参数,或者把函数作为结果返回的函数。如:map、sorted也是:可选的key参数用于提供一个函数,它会应用到各个元素上排序。

根据反向拼写给一个单词列表 排序

>>> def reverse(word):
...     return word[::-1]
>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=reverse)
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

这样可以创建押韵词典,把各个单词反过来拼写。

匿名函数

lambda 关键字在Python表达式内创建匿名函数。

lambda 函数的定义提中不能赋值, 也不能使用 while 和 try 等语句。

使用lambda,反向给单词列表排序

>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=lambda word: word[::-1])
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

可调用对象

可以通过 callable() 函数来进行判断


用户定义的函数

​ 使用 def 语句或 lambda 表达式创建。

内置函数

​ 使用 C 语言(CPython)实现的函数,如 len 或 time…strftime

内置方法

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

方法

​ 在类的定义体中定义的函数。

​ 调用类时会运行类的__new__方法创建一个实例,然后运行 __init__方法,初始化实例,最后把实例返回给调用方。

类的实例

​ 如果类定义__call__方法,那么它的实例可以作为函数调用。

生成器函数

​ 使用 yield 关键字的函数或方法。调用生成器函数返回的时生成器对象。

判断对象能否调用,最安全的方法时使用内置的 callable() 函数

>>> abs, str, 13
(<built-in function abs>, <class 'str'>, 13)
>>> [callable(obj) for obj in (abs, str, 13)]
[True, True, False]

用户定义的可调用类型

如何 Python 对象都可以表现得像函数。只需实现方法__call__

调用 BingoCago 实例,从打乱的列表中取出一个元素。

import random


class BingoCage:
    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):
        # bingo.pick()的快捷方式时bingo()
        return self.pick()


bingo = BingoCage(range(3))
print(bingo.pick())
print(bingo())
print(callable(bingo))	# 返回True表示可调用
0
1
True

shuffle() 方法将序列的所有元素随机排序。没有返回值,参数中可以是列表。

函数内省

Python 函数可以进行内省 -Introspection,查看函数内部细节,使用 __code__ 属性。

dir(function) 查看函数具有的属性。

从定位参数到仅限关键字参数

tag 函数用于生成 HTML 标签;使用名为 cls 的关键字参数传入 “class” 属性

def tag(name, *content, cls=None, **attrs):
    # 生成一个或多个HTML标签
    if cls is not None:
        attrs['class'] = cls
    if attrs:
        attr_str = ''.join(' %s="%s"' % (attr, value)
                           for attr, value
                           in sorted(attrs.items()))
    else:
        attr_str = ''
    if content:
        return '\n'.join('<%s%s>%s</%s>' %
                         (name, attr_str, c, name) for c in content)
    else:
        return '<%s%s />' % (name,attr_str)
>>> tag('br')
'<br />'
>>> tag('p', 'hello')'<p>hello</p>'
>>> print(tag('p', 'hello', 'world'))
<p>hello</p>
<p>world</p>
>>> tag('p', 'hello', id=33)'<p id="33">hello</p>'
>>> print(tag('p', 'hello', 'world', cls='sidebar'))
<p class="sidebar">hello</p>
<p class="sidebar">world</p>
>>> tag(content='testing', name="img")
'<img content="testing" />'
>>> my_tag = {'name':'img', 'title': 'Sunset Boulevard',
...           'src': 'sunset,jpg', 'cls': 'framed'}
>>> tag(**my_tag)'<img class="framed" src="sunset,jpg" title="Sunset Boulevard" />'

② 第一个参数后面的任意个参数会被 *content 捕获,存入一个元组。

③ tag 函数签名中没有明确指定名称的关键字参数会被 **attrs 捕获,存入一个字典。

⑤ 加上 ** 字典中的所有元素作为单个参数传入,同名键会绑定到对应的具名参数上,余下被**attrs捕获


如果不想支持数量不定的定位参数,但是像支持仅限关键字参数,在签名中放一个*

>>> def f(a, *, b):
...     return a, b
...
>>> f(1, b=2)
(1, 2)

注意,仅限关键字不一定要有默认值,如上例中所示,强制必须传入实参。

获取关于参数的信息

提取函数的签名

def clip(text, max_len=80):
    """
    在max_len前面或后面的第一个空格处阶段文本
    """
    end = None
    if len(text) > max_len:
        space_before = text.rfind(' ', 0, max_len)
        if space_before >= 0:
            end = space_before
        else:
            space_after = text.rfind(' ',max_len)
            if space_after >= 0:
                end = space_after
        if end is None:     # 没有找到空格
            end = len(text)
        return text[:end].rstrip()
>>> from inspect import signature
>>> sig = signature(clip)
>>> sig
<Signature (text, max_len=80)>
>>> str(sig)
'(text, max_len=80)'
>>> for name, param in sig.parameters.items():
...     print(param.kind, ':', name, '=', param.default)
...
POSITIONAL_OR_KEYWORD : text = <class 'inspect._empty'>	# 表示没有默认值
POSITIONAL_OR_KEYWORD : max_len = 80

inspect.signature 函数返回一个 inspect.Signature 对象,它有一个 parameters 属性,知识一个有序映射,把参数名 inspect.Parameter 对象对应起来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值