51假期读书笔记(下)——流畅的python

5.4 5.4 5.4 可调用对象

除了用户定义的函数,调用运算符(即())还可以应用到其他对象上。如果想判断对象能否调用,可以使用内置的callable()函数。Python的数据模型文档列出了以下7种可调用对象。

  • 用户定义的函数
    使用def语句或lambda表达式创建

  • 内置函数
    使用C语言(CPython)实现的函数,如len或者time.strtime

  • 内置方法
    使用C语言实现的方法,如dict.get

  • 方法
    在类的定义体中定义的函数


  • 调用类时会运行类的__new__方法创建一个实例,然后运行__init__方法,初始化该实例,然后把实例返回给调用方。因为 Python 没有new运算符,所以调用类时相当于调用函数。(通常,调用类会创建那个类的实例,不过覆盖__new__方法的话,也可能出现其他行为。)

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

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

python中的可调用类型有很多,因此可以通过内置函数callable()来判断对象是否可调用。

用户自定义函数 ———— 每个函数名都有一个值,该值的类型是可以被解释器识别为用户定义函数的类型

(还是用了上一节中的例子?)

>>> [callable(i) for i in (fruits, func1, 12, 'hello')]
[False, True, False, False]
>>> [callable(i) for i in (my_func, int, str)]
[True, True]

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

import random

class BingoCase:
    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 BingoCase')

    def __call__(self, *args, **kwargs):
        return self.pick()


bc = BingoCase(range(4))
print(bc.pick())  # 3
print(bc())  # 0
print(callable(bc))  # True

实现__call__方法的类是创建函数类对象的简便方法。
我们把这个类型的对象当作函数来使用,相当于重载了括号运算符。

5.6 5.6 5.6 函数内省

函数对象有很多很多的属性,除了我们之前提到的__doc__还有以下常用属性:

属性说明
doc用于获取函数的文档说明,如果没有,则返回 None
name获取函数的名称
module返回函数所在的模块,如果无则返回None
defaults以元组的形式返回函数的默认参数,如果无默认参数则返回None
dict包含了类里可用的属性名-属性的字典;也就是可以使用类名.属性名访问的对象
class该实例的类对象
self仅方法可用,如果是绑定的(bound),则指向调用该方法的类(如果是类方法)或实例(如果是实例方法),否则为None

示例如下:

>>> func1.__doc__
' return n!'
>>> func1.__name__
'func1'
>>> func1.__class__
# <class 'function'>
 '__iter__'
>>> func1.__qualname__
'func1'
>>> func1.__module__
'__main__'
>>> func1.__code__
<code object func1 at 0x103c5c270, file "<stdin>", line 1>
>>> func1.__globals__
"""
{'__name__': '__main__', 
'__doc__': None, 
'__package__': None, 
'__loader__': <class '_frozen_importlib.BuiltinImporter'>, 
'__spec__': None, 
'__annotations__': {}, 
'__builtins__': <module 'builtins' (built-in)>, 'func1': <function func1 at 0x103c67b70>, 'my_func': <function func1 at 0x103c67b70>, 'fruits': ['strawberry', 'apple', 'watermalon', 'lemon'], 
'reverse': <function reverse at 0x10360ce18>, 'reduce': <built-in function reduce>, 
'add': <built-in function add>}
"""

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

python中有一个很好的特性就是提供了极为灵活的参数处理机制。*args, **kwargs这两个不定参数可以帮我们省去很多麻烦。

在调用函数时,使用*或者**可以展开迭代对象,从而映射到单个参数。

示例如下:

>>> def books(name, cls=None, *content, **attrs):
...     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)

>>> books('br')
'<br />'
>>> books('p', 'hello')
'<p class="hello" />'
>>> books('p', div, 'hello', 'world')
'<p class="div">hello<p>\n<p class="div">world<p>'
>>> my_tag = {'name': 'img','title':'maixue','cls':'framed','src': 'sun.jpg'}
>>> books(**my_tag)
'<img class="framed" src="sun.jpg" title="maixue" />'

在my_tag前面加上了**之后,字典中的所有元素都作为单个参数传入,同名的键就会自动绑定在指定位置,余下的则被**attrs捕获。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值