Python函数重载实例

函数重载是Python中的稀罕东西。注意观察@functools.singledispatch 的使用;

下面贴出functools模块函数的使用示例,及简短描述。来自如下文档。

Python » 3.6.0a4 Documentation » The Python Standard Library » 10. Functional

10.2. functools — Higher-order functions and operations on callable objects



# 10.2. functools — Higher-order functions and operations on callable objects

import functools
import locale
from urllib import request

# functools.cmp_to_key(func) 转换旧的key函数为新函数
d = sorted('ABCDEFG', key=functools.cmp_to_key(locale.strcoll))  
print(d)

#  LRU (least recently used) cache
@functools.lru_cache(maxsize=32)
def get_pep(num):
    'Retrieve text of a Python Enhancement Proposal'
    resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
    try:
        with request.urlopen(resource) as s:
            return s.read()
    except Exception:
        return 'Not Found'

#for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
for n in 8, 290:
    pep = get_pep(n)
    print(n, len(pep))

print(get_pep.cache_info())


# 排序比较。

# 提供__lt__(), __le__(), __gt__(), or __ge__()之一。
# 再提供__eq__() 方法
@functools.total_ordering
class Student:
    def _is_valid_operand(self, other):
        return (hasattr(other, "lastname") and
                hasattr(other, "firstname"))
    def __eq__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) ==
                (other.lastname.lower(), other.firstname.lower()))
    def __lt__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) <
                (other.lastname.lower(), other.firstname.lower()))


# functools.partial(func, *args, **keywords)
basetwo = functools.partial(int, base=2)
basetwo.__doc__ = 'Convert base 2 string to an int.'
print(basetwo('10010'))


# class functools.partialmethod(func, *args, **keywords) 
# partialmethod 设计用于方法定义
class Cell(object):
    def __init__(self):
        self._alive = False
    @property
    def alive(self):
        return self._alive
    def set_state(self, state):
        self._alive = bool(state)
    set_alive = functools.partialmethod(set_state, True)
    set_dead = functools.partialmethod(set_state, False)

c = Cell()
print(c.alive)
c.set_alive()
print(c.alive)


# functools.reduce(function, iterable[, initializer]) 
# 累加
# reduce 减少; 缩小; 使还原; 使变弱; 
# 此处是累加的意思
d= functools.reduce(lambda x, y: x+y, [1, 2, 3, 4, 5],100)
print(d)


# 函数重载 
@functools.singledispatch 
def fun(arg, verbose=False):
    if verbose:
        print("Let me just say,", end=" ")
    print(arg)

@fun.register(int)
def _(arg, verbose=False):
    if verbose:
        print("Strength in numbers, eh?", end=" ")
    print(arg)

@fun.register(list)
def _(arg, verbose=False):
    if verbose:
        print("Enumerate this:")
    for i, elem in enumerate(arg):
        print(i, elem)

print('函数重载')
fun("test.", verbose=True)
fun(42, verbose=True)
fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
fun({'a':'txt','b':'dat'}, verbose=True)

'''
函数重载
Let me just say, test.
Strength in numbers, eh? 42
Enumerate this:
0 spam
1 spam
2 eggs
3 spam
Let me just say, {'b': 'dat', 'a': 'txt'}
'''

# 默认partial对象没有__name__和__doc__, 这种情况下,
# 对于装饰器函数非常难以debug.使用update_wrapper(),
# 从原始对象拷贝或加入现有partial对象

# 它可以把被封装函数的__name__、 module 、__doc__和 __dict__
# 都复制到封装函数去(模块级别常量WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES)

# 缺省是模块级别常量 WRAPPER_ASSIGNMENTS 
# 赋给包装器__module__, __name__, __qualname__, __annotations__ 和 __doc__

# WRAPPER_UPDATES 更像包装器的__dict__

# functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 
# 更新包装器函数以便更像被包装的函数
from functools import update_wrapper
def wrap2(func):
    def call_it(*args, **kwargs):
        """wrap func: call_it2"""
        print('before call')
        return func(*args, **kwargs)
    return update_wrapper(call_it, func)

@wrap2
def hello2():
    """test hello"""
    print('hello world2')

hello2()
print(hello2.__name__)
print(hello2.__doc__)


# @functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 
from functools import wraps
def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        print('Calling decorated function')
        return f(*args, **kwds)
    return wrapper

@my_decorator
def example():
    """Docstring"""
    print('Called example function')

example()
print(example.__name__)
print(example.__doc__)

你可能感兴趣的:(python)