1. 程式人生 > >4 - 函數&裝飾器 and 叠代器&生成器

4 - 函數&裝飾器 and 叠代器&生成器

有一個 調用函數 rod 什麽 老師 log and 條件 執行函數

函數是什麽

函數一詞來源於數學,但編程中的「函數」概念,與數學中的函數是有很大不同的。程序裏函數的定義是:

定義:將一組語句的集合通過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名即可

特性

  1. 減少重復代碼
  2. 使程序變的可擴展
  3. 使程序變得易維護

實例1

def calcu(x,y):
    res = x**y
    return res #返回執行結果
 
result = calc(2,2)
print(result )

實例2

def student_fun(name,age,post):
    print("----學生信息------")
    print("姓名:",name)
    print("年齡:",age)
    print("職業:",post)
    print(‘‘)


student_fun(‘鄒俊安‘,17,‘學生‘)
student_fun(age=17,name=‘文藝‘,post=‘學生‘)
student_fun(‘王秋傑‘,45,‘老師‘)

函數的參數

形參:變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量

實參:可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。因此應預先用賦值,輸入等辦法使參數獲得確定值

name = "鄒俊安"

def change_name(name):
    print("修改前:", name)
    name = "羅奧"
    print("修改後", name)


change_name(name)

print("name是什麽?", name) #輸出的name還是鄒俊安

函數的作用域

函數內一般情況無法修改函數外變量

name = "鄒君安"

def change_name():
    name = "羅奧"

change_name(name)

print("name是什麽?", name)  #name還是鄒俊安

可以通過global關鍵字來訪問外部變量

name = "鄒君安"

def change_name():
    global name
    name = "羅奧"

change_name(name)

print("name是什麽?", name)  #
name還是鄒俊安

函數遞歸

在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。

註意:

1. 必須有一個明確的結束條件。

2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少。

3. 遞歸效率不高,遞歸層次過多會導致棧溢出。(經過測試python3.6的最大的遞歸此時為978次)

def calc(n):
    print(n)
    if int(n/2) ==0:
        return n
    return calc(int(n/2))
 
calc(10)

"""
輸出:
10
5
2
1
"""

匿名函數

匿名函數就是不需要顯式的指定函數

def calc1(n):
    return n ** 2

calc2 = lambda n: n ** 2

#結果相同
print(calc1(10))
print(calc2(10))

高階函數

一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。

def f(n):
    return n*2

def add(a,b,f):
    return f(a) + f(b)

result = add(1,2,f)
print(result)       #結果:6

裝飾器

需要知識
1.函數即變量
2.高階函數
a.把函數名當實參傳給另外一個函數
b.返回值包含函數名
3.嵌套函數
高階函數+嵌套函數=》裝飾器

*裝飾器*
定義:本質是函數,(裝飾其他函數)就是為其他函數添加功能
原則:a.不能修改被裝飾的函數源代碼
b.不能修改被裝飾的函數調用方式

模型:
def 函數名1(裝飾器參數):
    def 函數名2(被裝飾函數名):
        def 函數名3(被裝飾函數的參數)
            。。使用裝飾器參數。。
            返回值 = 被裝飾函數使用(傳遞被裝飾函數的參數)
            。。balabala。。
            return 返回值
        return 函數名3
    return 函數名2

@函數名1(裝飾器參數)
def 裝飾函數(參數):
    。。balabala。。

現在你新入職了一家公司,工作是維護更新本公司網站,公司網站有3個入口: index、manage、topic,現在公司要求要在manage和topic入口需要登陸驗證,函數代碼極其復雜,而且很多地方都有調用,這時裝飾器就派上了用處。

實例:

username,password = 09w09,12345

def check_user(check_type):
    def decorator(func):
        def func_num(*arg1,**arg2):
            if check_type == True:
                usernm = input("Please input username:")
                passwd = input("Please input username:")
                if usernm == username and passwd == password:
                    res = func(*arg1,**arg2)
                    print(執行函數後繼續執行.center(50,-))
                    return res
                else:
                    exit(0)
            else:
                passwd = input("09w09 please input password:")
                if passwd == password:
                    res = func(*arg1, **arg2)
                    print(執行函數後繼續執行.center(50, -))
                    return res
                else:
                    exit(0)
        return func_num
    return decorator



def index():
    print(Welcome to 09w09\‘s index.ljust(50,*))

@check_user(True)
def manage(x):
    print(this is manage page!.ljust(50,*),x)

@check_user(False)
def topic():
    print(this is topic page.ljust(50,*))
    return \nok!\n

index()
manage(09w09)
print(topic())

叠代器

叠代是Python最強大的功能之一,是訪問集合元素的一種方式。

叠代器是一個可以記住遍歷的位置的對象。

叠代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。叠代器只能往前不會後退。

叠代器僅僅在叠代到某個元素時才計算該元素,而在這之前或之後,元素可以不存在或者被銷毀。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合,比如幾個G的文件

實例:

>>> a = iter([1,2,3,4,5])
>>> a
<list_iterator object at 0x00000238F2D6DE48>
>>> a.__next__()
1
>>> a.__next__()
2
>>> next(a)
3
>>> next(a)
4
>>> next(a)
5
>>> next(a)
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    next(a)
StopIteration

生成器

在 Python 中,使用了 yield 的函數被稱為生成器(generator)。

跟普通函數不同的是,生成器是一個返回叠代器的函數,只能用於叠代操作,更簡單點理解生成器就是一個叠代器。

在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續運行

實例1:

#生成器變成list
print([i*2 for i in range(10)])

#list變成生成器
print(iter([1,2,3,4,10,6,7,8]))

實例2:

def produce(x):
    str = *
    for i in range(x):
        yield str
        str+=*

def print_(p):
    while True:
        try:
            print(next(p))
        except StopIteration :
            print(ok:)
            break

print_(produce(10))


"""
輸出結果:

*
**
***
****
*****
******
*******
********
*********
**********
ok!
"""

yield實現在單線程的情況下實現並發運算的效果

import time

def consumer(name):
    print(%s同學準備吃包子了 % name)
    while True:
        baozi = yield #每次執行都會停留在這裏,
        print("%s同學吃了%s餡包子" % (name,baozi))

def producer(filling):
    c1 = consumer(陳敏)
    c2 = consumer(馬國正)
    c1.__next__()
    c2.__next__()
    print(王嘉寧開始做包子了!)
    for i in range(10):
        time.sleep(1)
        print(陳敏做了2個%s餡包子 % filling)
        c1.send(filling)
        c2.send(filling)

producer(韭菜)

 

4 - 函數&裝飾器 and 叠代器&生成器