前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >流畅的Python 5. 函数

流畅的Python 5. 函数

作者头像
Michael阿明
发布2021-09-06 10:31:18
2870
发布2021-09-06 10:31:18
举报
文章被收录于专栏:Michael阿明学习之路

文章目录

1. 函数对象

代码语言:javascript
复制
def factorial(n):
    '''
    returns n! n的阶乘
    '''
    return 1 if n < 2 else n * factorial(n - 1)


print(factorial(42))
print(factorial.__doc__)  # returns n! n的阶乘
print(type(factorial))  # <class 'function'>

fact = factorial
print(fact)  # <function factorial at 0x0000021512868EA0>
print(fact(4))  # 24
print(list(map(factorial, range(11))))
# [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

2. 高阶函数

  • 接受函数作为参数,如 map,sorted
代码语言:javascript
复制
fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
print(sorted(fruits, key=len))  # 按长度排序
# ['fig', 'apple', 'cherry', 'banana', 'raspberry', 'strawberry']

def reveres(word):
    return word[::-1]

print(reveres("michael"))  # leahcim
print(sorted(fruits, key=reveres)) # 逆序字符串排序
# ['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

3. 匿名函数

  • lambda
代码语言:javascript
复制
print(sorted(fruits, key=lambda w : w[::-1]))
# ['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

4. 可调用函数

  • 对象是否可调用:callable()
代码语言:javascript
复制
print([callable(obj) for obj in (abs, str, 13, factorial)]) # [True, True, False, True]
  • 任意对象实现可调用:实现 __call__()
代码语言:javascript
复制
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):
        return self.pick()


arr = [1, 2, 3, 4, 5]
bc = BingoCage(arr);
print(bc._items)  # [1, 4, 3, 5, 2]
print(bc.pick())  # 2
print(bc._items)  # [1, 4, 3, 5]
print(bc())  # 5, bc 实现了 __call_() 可调用
print(bc._items)  # [1, 4, 3]
print(callable(bc))  # True

5. 定位参数、仅限关键字参数

代码语言:javascript
复制
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)


print(tag('br'))  # <br />
print(tag('p', 'hello'))  # <p>hello</p>
print(tag('p', 'hello', 'world')) 
# 第一个参数后的任意个 参数 被 *content 捕获,存入元组
# <p>hello</p>
# <p>world</p>
print(tag('p', 'hello', id=33, pid=24)) 
# 没有明确指定名称的关键字参数被 **attrs 捕获,存入字典
# <p id="33" pid="24">hello</p>
print(tag('p', 'hello', 'world', id=33, cls='sidebar', pid=24)) 
# cls 参数只能作为关键字参数
# <p class="sidebar" id="33" pid="24">hello</p>
# <p class="sidebar" id="33" pid="24">world</p>
print(tag(cont='testing', name="img"))
# <img cont="testing" />
my_tag = {'name': 'img', 'title': 'Sunset Boulevard',
          'src': 'sunset.jpg', 'cls': 'framed'}
print(tag(**my_tag)) 
# ** 字典中所有元素作为单个参数传入,同名键绑定到对应具名参数,余下被 **attrs 捕获
# <img class="framed" src="sunset.jpg" title="Sunset Boulevard" />
代码语言:javascript
复制
def f(a, *c, b):
    return a, b


print(f(1, b=2))  # (1, 2)
print(f(1, 2, b=3))  # (1, 3) b= 必须写,因为前面有 * 参数


# print(f(1, 2))  # f() takes 1 positional argument but 2 were given

def f1(a, b, *c):
    return a, b


print(f1(1, b=2))  # (1, 2)
print(f1(1, 2))  # (1, 2)
print(f1(1, 2, 3))  # (1, 2)

6. 获取参数信息

代码语言:javascript
复制
from inspect import signature
sig = signature(tag)
print(sig) # (name, *content, cls=None, **attrs)

my_tag = {'name': 'img', 'title': 'Sunset Boulevard',
          'src': 'sunset.jpg', 'cls': 'framed'}
bound_args = sig.bind(**my_tag)
print(bound_args)
# <BoundArguments (name='img', cls='framed', attrs={'title': 'Sunset Boulevard', 'src': 'sunset.jpg'})>
del my_tag['name']
bound_args = sig.bind(**my_tag)
# TypeError: missing a required argument: 'name'

7. 函数注解

  • 对参数,返回值进行注释,解释器不做检查
代码语言:javascript
复制
def clip(text: str, max_len: 'int > 0' = 80) -> str:
    pass


print(clip.__annotations__)  # 一个字典
# 注解可以是 类 或者 字符串
# {'text': <class 'str'>, 'max_len': 'int > 0', 'return': <class 'str'>}
sig = signature(clip)
print(sig)  # (text: str, max_len: 'int > 0' = 80) -> str
print(sig.return_annotation)  # <class 'str'>
for param in sig.parameters.values():
    print(param.name, " ", param.annotation, " ", param.default)
# text   <class 'str'>   <class 'inspect._empty'>
# max_len   int > 0   80

8. 支持函数式编程的包

  • operator
代码语言:javascript
复制
from functools import reduce


def fact(n):
    return reduce(lambda a, b: a * b, range(1, n + 1))


print(fact(5))

from operator import mul


def fact1(n):
    return reduce(mul, range(1, n + 1))


print(fact1(5))
代码语言:javascript
复制
metro_data = [
    ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
    ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
    ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
    ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
    ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]
from operator import itemgetter
import operator
for city in sorted(metro_data, key=itemgetter(1)):
    print(city)  # 按照 索引 1 排序

cc_name = itemgetter(1, 0)
for city in metro_data:
    print(cc_name(city))
# ('JP', 'Tokyo')
# ('IN', 'Delhi NCR')
# ('MX', 'Mexico City')
# ('US', 'New York-Newark')
# ('BR', 'Sao Paulo')

print([name for name in dir(operator) if not name.startswith('_')])
# ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
# 'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
# 'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul', 'index',
# 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift', 'is_', 'is_not',
# 'isub', 'itemgetter', 'itruediv', 'ixor', 'le', 'length_hint', 'lshift',
# 'lt', 'matmul', 'methodcaller', 'mod', 'mul', 'ne', 'neg', 'not_', 'or_',
# 'pos', 'pow', 'rshift', 'setitem', 'sub', 'truediv', 'truth', 'xor']
代码语言:javascript
复制
from operator import methodcaller

s = 'the time has come'
upcase = methodcaller('upper') # 调用指定的方法 'upper'
print(upcase(s))  # THE TIME HAS COME
connect = methodcaller('replace', ' ', '-')
print(connect(s)) # the-time-has-come
代码语言:javascript
复制
from operator import mul
from functools import partial

triple = partial(mul, 3)
print(triple(7))  # 21
print(list(map(triple, range(1, 10))))
# [3, 6, 9, 12, 15, 18, 21, 24, 27]
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/03/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 函数对象
  • 2. 高阶函数
  • 3. 匿名函数
  • 4. 可调用函数
  • 5. 定位参数、仅限关键字参数
  • 6. 获取参数信息
  • 7. 函数注解
  • 8. 支持函数式编程的包
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档