zoukankan      html  css  js  c++  java
  • 5. First-Class Functions

    Function in python are first-class objects (runtime / element / argument / return)

    1. Treating a Function Like an Object

    def test(n):
        """ return n*2 """
        return n * 2
    
    print test(5)  # 10
    # '__doc__' is used to generate the help text of an object
    # 'help(test)' do like this in Python Interactive Console
    print test.__doc__  # ' return n*2 '
    # Function object is an instance of the function class.
    print type(test)  # <type 'function'>
    # assign it, call it, use it as an argument
    tmp = test
    print tmp(5)  # 10
    print list(map(tmp, range(5)))  # [0, 2, 4, 6, 8]
    

    2. Higher-Order Functions

    • A function that takes a function as argument or returns a function
    fruits = ['fig', 'apple', 'cherry']
    
    print sorted(fruits, key=len)  # ['fig', 'apple', 'cherry']
    # Any one-argument function can be used as the key.
    print sorted(fruits, key=lambda word: word[::-1])  # ['apple', 'fig', 'cherry']

    2.1 Modern Replacements for map, filter, and reduce

    def test(n):
        return n * 2
       
    print list(map(test, range(5)))  # [0, 2, 4, 6, 8]
    print [test(n) for n in range(5)]  # [0, 2, 4, 6, 8]
    
    print list(map(test, filter(lambda n: n % 2, range(5))))  # [2, 6]
    print [test(n) for n in range(5) if n % 2]  # [2, 6]
    
    print reduce(lambda x,y: x+y, range(100))  # 4950
    print sum(range(100))  # 4950
    

    3. The Seven Flavors of Callable Objects

    • User-defined functions: def or lambda.
    • Built-in functions: like len or time.strftime.
    • Built-in methods: like dict.get.
    • Methods: functions in class.
    • Classes: a class runs its __new__ method to create an instance, then __init__ to initialize it, and finally the instance is returned to the caller.
    • Class instances: if a class defines a __call__ method, then its instances may be invoked as functions.
    • Generator functions: functions or methods that use the yield keyword.

    [notes]: To determine whether an object is callable, use the callable() built-in function.

    4. User-Defined Callable Types

    • Python objects may also be made to behave like functions
    class Test:
        def __init__(self, items):
            self._items = list(items)
        def pick(self):
            return self._items.pop()
        def __call__(self):
            return self.pick()
    
    t = Test(range(5))
    print t.pick()  # 4
    print t()  # 3
    print callable(t)  # True
    

    5. Keyword-Only Parameters

    • Can only be given as a keyword argument.
    • Python 3 only.
    def tag(name, *content, cls=None, **attrs):  # cls: Keyword-Only
        """ Generate one or more HTML tags """
        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 '
    '.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('a', 'hello', 'world', href='#'))  # <a href="#">hello</a>
    <a href="#">world</a>
    print(tag('div', 'im div~', cls='f-left'))  # <div class="f-left">im div~</div>
    print(tag(**{'name': 'img', 'id': 'my_img'}))  # <img id="my_img" />
    
    def f(a, *, b):  # b: Keyword-Only
        return a, b
    print(f(1, b=2))  # (1, 2)

    6. Function Introspection

    def test(n):
         return n * 2
    test.name = 'double it!'
    
    # a function uses the __dict__ attribute to store user attributes assigned to it
    print test.__dict__  # {'name': 'double it!'}
    • Attributes of functions that don’t exist in plain instances

    7. Retrieving Information About Parameters

    def test(a, b=2, c=3, **x):
        d = a * b * c
        return d
       
    print test.__defaults__  # (2, 3)
    # defaults for keyword-only arguments
    # print(test.__kwdefaults__)  # {'e': 3}
    print test.__code__  # <code object test at 0x...>
    # does't include any variable arguments prefixed with * or **
    print test.__code__.co_varnames  # ('a', 'b', 'c', 'd')
    print test.__code__.co_argcount  # 3
    def test(a, b=2, c=3, **x):
        d = a * b * c
        return d
    
    from inspect import signature  # python 3
    tmp = signature(test)
    print(str(tmp))  # (a, b=2, c=3, **x)
    for name, param in tmp.parameters.items():
    	# 'kind' can also be: VAR_POSITIONAL / VAR_KEYWORD / KEYWORD_ONLY / POSITIONAL_ONLY
        print(param.kind)  # POSITIONAL_OR_KEYWORD
        print(name)  # a
        print(param.default)  # <class 'inspect._empty'>
    
    bind_tmp = tmp.bind(**{'a': 11, 'b': 22})
    for name, value in bind_tmp.arguments.items():
        print(name, '=', value)  # a = 11 
     b = 22

    8. Function Annotations

    • Just annotation, noting else!
    • Python 3 only.
    def test(a:str, b:'in>0'=1) -> str:
        return a
    print(test('qqq', 2))  # qqq
    print(test.__annotations__)   # {'a': <class 'str'>, 'b': 'in>0', 'return': <class 'str'>}
    
    from inspect import signature  # python 3
    tmp = signature(test)
    for name, param in tmp.parameters.items():
        print(param.annotation)  # <class 'str'>
        print(param.name)  # a
        print(param.default)  # <class 'inspect._empty'>
    

     9. Packages for Functional Programming

    9.1 operator

    from operator import mul
    print mul(4, 5)  # 20
    
    
    from operator import itemgetter  # pick items from sequences
    test_data = [('b', 2), ('a', 1), ('c', 3)]
    for item in sorted(test_data, key=itemgetter(1)):  # lambda i: i[1]
        print item  # ('a', 1)
    func = itemgetter(1, 0)  # lambda i: (i[1], i[0])
    for item in test_data:
        print func(item)  # (2, 'b')
    
    
    from operator import attrgetter  # read attributes from objects
    class A:
        tmp = 1
    class B:
        a = A()
    class C:
        b = B()
        tmp = 2
    c = C()
    func = attrgetter('b.a.tmp', 'tmp')
    print func(c)  # (1, 2)
    
    
    from operator import methodcaller
    s = 'The time has come'
    my_upper = methodcaller('upper')
    print my_upper(s)  # s.upper()
    my_replace = methodcaller('replace', ' ', '-')
    print my_replace(s)  # s.replace(' ', '-')
    
    
    #['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
    # 'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
    # 'iconcat', 'ifloordiv', 'ilshift', 'imod', 'imul', 'index', 'indexOf',
    # 'inv', 'invert', 'ior', 'ipow', 'irshift', 'is_', 'is_not', 'isub',
    # 'itemgetter', 'itruediv', 'ixor', 'le', 'length_hint', 'lshift',
    # 'lt', 'methodcaller', 'mod', 'mul', 'ne', 'neg', 'not_', 'or_', 'pos',
    # 'pow', 'rshift', 'setitem', 'sub', 'truediv', 'truth', 'xor']

    9.2 functools

    def test(a, b, c):
        return a * b * c
        
    from functools import partial
    tmp = partial(test, 1, c=2)  # can't 'b=2' because 'c'
    print list(map(tmp, range(5)))  # [0, 2, 4, 6, 8]
    print test      # <function test at 0x10dca0e60>
    print tmp.func  # <function test at 0x10dca0e60>
    print tmp.args  # (1,)
    print tmp.keywords  # {'c': 2}
    
  • 相关阅读:
    猿辅导-去除数组中数量大于k的数
    OSI体系结构各层协议
    京东-学生合唱队分组
    146-LRUCache
    76-最长上升子序列
    无序数组中三个数字乘积最大值
    38-字符串的排列
    35-复杂链表的复制
    208-Implement Trie(Prefix Tree)
    69-求一个整数的平方根
  • 原文地址:https://www.cnblogs.com/lb477/p/10902762.html
Copyright © 2011-2022 走看看