1. 程式人生 > >py學習筆記2-函式

py學習筆記2-函式

函式語法


    def power(x):
        return x*x

    # enroll('Bob', 'M', 7)
    # enroll('Adam', 'M', city='Tianjin')
    def enroll(name, gender, age=6, city='Beijing'):
        print('name:', name)
        print('gender:', gender)
        print('age:', age)
        print('city:', city)

    # L 是一個已經被計算出的引數,  預設引數應該指向不變的物件
    def add_end(L=[]):
        L.append('END')
        return L
    
    # >>> add_end()
    # ['END', 'END']
    # >>> add_end()
    # ['END', 'END', 'END']
    # 改進如下
    def add_end(L=None):
        if L is None:
            L = []
        L.append('END')
        return L
    
    #  calc(1, 3, 5, 7) numbers會被作為一個 list 解析
    def calc(*numbers):
        sum = 0
        for n in numbers:
            sum = sum + n * n
        return sum

    def person(name,age,**kw):
        print('name:', name, 'age:', age, 'other:', kw)
    # >>> person('Bob', 35, city='Beijing')
    # name: Bob age: 35 other: {'city': 'Beijing'}
    # >>> person('Adam', 45, gender='M', job='Engineer')
    # name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

    # 命名關鍵字引數需要一個特殊分隔符*,*後面的引數被視為命名關鍵字引數
    def person(name, age, *, city, job):
        print(name, age, city, job)
    # >>> person('Jack', 24, city='Beijing', job='Engineer')
    # Jack 24 Beijing Engineer

    def f1(a, b, c=0, *args, **kw):
        print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

    def f2(a, b, c=0, *, d, **kw):
        print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
    
    >>> f1(1, 2)
    a = 1 b = 2 c = 0 args = () kw = {}
    >>> f1(1, 2, c=3)
    a = 1 b = 2 c = 3 args = () kw = {}
    >>> f1(1, 2, 3, 'a', 'b')
    a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
    >>> f1(1, 2, 3, 'a', 'b', x=99)
    a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
    >>> f2(1, 2, d=99, ext=None)
    a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

    >>> args = (1, 2, 3, 4)
    >>> kw = {'d': 99, 'x': '#'}
    >>> f1(*args, **kw)
    a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
    >>> args = (1, 2, 3)
    >>> kw = {'d': 88, 'x': '#'}
    >>> f2(*args, **kw)
    a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}

函數語言程式設計

函式名本身就是一個變數,指向一個函式,因此函式也可以作為變數使用賦值給其他變數

map

    def f(x):
        return x*x

    arr = [1,2,3,4,5]
    ir = map(f,arr)
    print(list(ir))

map(fun,Iterable) 它將會把 fun 用在 Iterable 每一個元素上,生成一個迭代器 Iterator,Ierator 是惰性的,用 list(Iterator) 將強制生成一個 Iterable

reduce

map 只能傳入一個引數,如果我們想傳入兩個引數呢
在 Python3 中,reduce() 函式已經被從全域性名字空間裡移除了,它現在被放置在 fucntools 模組裡,如果想要使用它,則需要通過引入 functools 模組來呼叫 reduce() 函式


    from functools import reduce
    def sum(x,y):
        return  x + y

    print(reduce(sum,[1,2,3,4,5])) # return sum(sum(sum(sum(1,2),3),4),5)

filter

filter()把傳入的函式依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素

    def is_odd(v):
        return v % 2 == 0

    f = filter(is_odd,[1,2,3,4,5])
    print(list(f))

filter 得到的也是一個惰性的 Iterator

sorted

key指定的函式將作用於list的每一個元素上,並根據key函式返回的結果進行排序,並按照對應關係返回list相應的元素


    print(sorted([-5,-88,9,4,33,84]))
    print(sorted([-5,-88,9,4,33,84],key=abs))
    print(sorted([-5,-88,9,4,33,84],key=abs,reverse=False))
    print(sorted(['bob', 'about', 'Zoo', 'Credit'],key=str.lower))
    # [-88, -5, 4, 9, 33, 84]
    # [4, -5, 9, 33, 84, -88]
    # [4, -5, 9, 33, 84, -88]
    # ['about', 'bob', 'Credit', 'Zoo']

閉包

    def lazy_sum(*args):
        def sum():
            n = 0
            for v in args:
                n += v
            return n

        return sum

    s = lazy_sum(1,2,3,4,5,6,7,8,9)
    print(s()) # 45 閉包與惰性求和

匿名函式

    f = lambda x: x*x

    def fun(x):
        return x*x

如上,兩個函式等價

裝飾器

所有的函式都可以通過 fun.name 得到定義時的函式名,即使被賦值給其他變數,也會得到原來的函式名

	def log(fun):
		def warpper(*args,**kw): # 對原來的函式進行包裝,類似於切面
			print('like sprint aop')
			fun(*args,**kw)
		return warpper
		
	def p(*args,**kw):
		for v in args:
			print(v)
	
	f = log(p)
	f(1,2,3)

我們首先建立了一個函式修飾器,它為函式的功能做了擴充,然後傳入要被裝飾的函式,並得到一個被裝飾後的函式並呼叫它

使用 python 的語法糖可以簡化這一過程

	def log(fun):
		def warpper(*args,**kw):
			print('like sprint aop')
			fun(*args,**kw)
		return warpper
		
	@log # 相當於 p = log(p)
	def p(*args,**kw):
		for v in args:
			print(v)
	
	p(1,2,3)

在做包裝時傳入引數


	import functools
	
	def log(b,l):
		def decorator(func):
			def warpper(*args,**kw):
				print(b,' middle ',l)
				func(*args,**kw)
			return warpper
		return decorator
	
	@log('begin','last') # 等同於 p = log('begin','last')(p),兩層修飾
	def p(*args,**kw):
		for v in args:
			print(v)
		
	print(p.__name__) # warpper 其實現在的 p 是指向 warpper 函式的,我們要修改回來,避免出問題
	p.__name__ = p
	p(1,2,3,a='a')
	
	# 修改後的函式如下
	def log(b,l):
		def decorator(func):
			@functools.wraps(func)
			def warpper(*args,**kw):
				print(b,' middle ',l)
				func(*args,**kw)
			return warpper
		return decorator

偏函式

py 提供的內建函式大多都可以傳入其他引數以滿足需求,如果每次呼叫都需要傳入一個額外引數,我們可以把這引數固定下來

	import functools
	
	print(int('12345'))
	print(int('01011',base=2))
	
	def int2(x):
		return int(x,base=2)
	
	print(int2('001010'))
	
	int2 = functools.partial(int,base=2) # 和上面 int2 的效果相同