Python入門(六)之 Python“三大器”

作者:PyQuant
博客https://blog.csdn.net/qq_33499889
慕課https://mooc1-2.chaoxing.com/course/207443619.html


點贊、關注再看,養成良好習慣
Life is short, U need Python
初學Python,快來點我吧
在這裏插入圖片描述




1. 函數對象

Python中任何東東皆爲對象,當然函數也是對象。

  • 函數可以被賦值
  • 函數可以當成參數傳遞
  • 函數可以當成返回值
  • 函數可以當成容器類型的元素
def foo():
    x = 100
    print(x)

print(foo)
f = foo         # 函數可以被賦值
print(f)
f()
<function foo at 0x00000268BBEC2B70>
<function foo at 0x00000268BBEC2B70>
100
def foo():
    x = 100
    print(x)

def bar(func):      # 把函數當參數
    print(func)
    func()

bar(foo)           
<function foo at 0x00000268BBEC2D90>
100
def foo():
    x = 100
    print(x)

def bar(func):    
    print(func)
    return func     # 把函數當返回值

f = bar(foo)
print(f)
f() 
<function foo at 0x00000268BBEC2730>
<function foo at 0x00000268BBEC2730>
100

2. 閉包

  • 閉包是由函數及其相關的引用環境組合而成的實體。
  • 閉包必須是內部定義函數,該函數包含對外部作用域而不是全局作用域名字的引用;沒值的話會返回None。
def ext_f(a):
    x = 100
    def int_f():
        num = x + a
        print(num)
        return
    return int_f

f = ext_f(10)

print(f)
print(f())
print(f.__closure__[0].cell_contents)
print(f.__closure__[1].cell_contents)
<function ext_f.<locals>.int_f at 0x00000268BBEC2EA0>
110
None
10
100
def ext_f(a):
    x = 100
    def int_f(b):
        num = x + a + b
        print(num)
        return 'python'
    return int_f

f = ext_f(10)

print(f)
print(f(20))
print(f.__closure__[0].cell_contents)
print(f.__closure__[1].cell_contents)
<function ext_f.<locals>.int_f at 0x00000268BBEC2BF8>
130
python
10
100
  • 註釋:咋看像是爲後面的類做鋪墊呢???

3. 第一器-----裝飾器

  • 裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。
  • 簡單地講,裝飾器的作用就是爲已經存在的對象添加額外的功能。

【1】嵌套函數

def book(name):
    return 'My name is {}'.format(name)

def foo(func):
    def wrapper(name):
        return '*** {} ***'.format(func(name))
    return wrapper

b = foo(book)
r = b('Python')
print(r) 
*** My name is Python ***

【2】簡單裝飾器

def decorator(func):
    def wrapper(name):
        return '*** {} ***'.format(func(name))
    return wrapper

@decorator                      # 簡單裝飾器,其中符號 @ 是裝飾器語法標記
def book(name):
    return 'My name is {}'.format(name)

r1 = book('Java')
print(r1)
*** My name is Java ***

【3】參數裝飾器

def foo(author):
    def decorator(func):
        def wrapper(name):
            if author == 'quant':
                return '*** {} ***'.format(func(name))
        return wrapper
    return decorator

@foo(author='quant')     # 帶參數的裝飾器1
def book(name):
    return 'My name is {}'.format(name)

r2 = book('Matlab')
r2
'*** My name is Matlab ***'
def foo(author):
    def decorator(func):
        def wrapper(name):
            if author == 'quant':
                return '*** {} ***'.format(func(name))
            else:
                return '$$$ {} $$$'.format(func(name))
        return wrapper
    return decorator

@foo(author='zhang')    # 帶參數的裝飾器2
def book(name):
    return 'My name is {}'.format(name)

r3 = book('Matlab')
r3
'$$$ My name is Matlab $$$'

【4】類裝飾器

class Foo:
    def __init__(self, func):
        self._func = func
    def __call__(self):
        print ('I like Python')
        self._func()
        print ('I like Java')

@Foo 
def bar():
    print ('bar')

bar()
I like Python
bar
I like Java

等價於

class Foo:
    def __init__(self, func):
        self._func = func
    def __call__(self):
        print ('I like Python')
        self._func()
        print ('I like Java')

def bar():
    print ('bar')   
    
b = Foo(bar)
b()
I like Python
bar
I like Java

4. 第二器-----生成器

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

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

  • 調用一個生成器函數,返回的是一個迭代器對像。

【1】函數生成器

def func(n):               
    for i in range(n):
        yield i**2
 
g = func(4)                 # g 是一個迭代器,由生成器返回生成
print(g)
print(list(g))
<generator object func at 0x00000268BBEEE200>
[0, 1, 4, 9]

【2】表達式生成器—元組解析式(有點像列表解析式)

t = (x**2 for x in range(4))
print(t)
print(tuple(t))
<generator object <genexpr> at 0x00000268BBEEE4C0>
(0, 1, 4, 9)

【3】元組生成器 VS 列表解析式

import time
import sys

# 解析式
%time lst = [x + 1 for x in range(100000000)]     # 查看運行時間
print(sys.getsizeof(lst))                         # 查看python對象的內存佔用
# 生成器
%time g = (x + 1 for x in range(100000000))       # 查看運行時間
print(sys.getsizeof(g))                           # 查看python對象的內存佔用
Wall time: 12.5 s
859724472
Wall time: 0 ns
88
  • 結論:生成器遠遠優於解析式!

5. 第三器-----迭代器

【1】可迭代對象

Python中任何可以循環的東東都是可迭代對象(iterable)。容器類型數據(str、list、tuple、dict、set等)都可以被for循環,因此都是可迭代對象。

  • isinstance(x, Iterable)
from collections import Iterable

print(isinstance(1234, Iterable))
print(isinstance('1234', Iterable))
print(isinstance([1,2,3,4], Iterable))  
print(isinstance((1,2,3,4), Iterable))  
print(isinstance({'a':1,'b':2}, Iterable))  
print(isinstance({1,2,3,4}, Iterable))  
False
True
True
True
True
True
  • **dir(x)**查看是否包含__iter__
print(dir([1,2,3]))
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

【2】迭代器

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

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

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

  • 迭代器有兩個基本的方法:iter() 和 next()。

  • 字符串、列表、元組、字典和集合都可用於創建迭代器,但它們不是迭代器。

  • iter 迭代器

list=[1,2,3]
myiter = iter(list)    # 創建迭代器對象

print (next(myiter)) 
print (next(myiter)) 
print (next(myiter)) 
1
2
3
list=[1,2,3]
myiter = iter(list)
for i in myiter:
    print(i)
1
2
3
  • 類迭代器
class MyNumbers:
    def __init__(self):
        self.a = 1
    def __iter__(self):
        return self
    def __next__(self):
        b = self.a
        self.a += 1
        return b

myclass = MyNumbers()

myiter = iter(myclass)
 
print(next(myiter))
print(next(myiter))
print(next(myiter))
1
2
3
print(next(myiter))
4
  • 內置迭代器
import itertools
print(dir(itertools))
['__doc__', '__loader__', '__name__', '__package__', '__spec__', '_grouper', '_tee', '_tee_dataobject', 'accumulate', 'chain', 'combinations', 'combinations_with_replacement', 'compress', 'count', 'cycle', 'dropwhile', 'filterfalse', 'groupby', 'islice', 'permutations', 'product', 'repeat', 'starmap', 'takewhile', 'tee', 'zip_longest']
mycounter = itertools.count()     # 計數器

print(next(mycounter))
print(next(mycounter))
print(next(mycounter))
0
1
2
data = [100,200,300]
mycounter = zip(itertools.count(), data)

print(mycounter)

for i in mycounter:
    print(i)
<zip object at 0x00000268BBF04148>
(0, 100)
(1, 200)
(2, 300)
data = [100,200,300]
mycounter = zip(itertools.count(start=10), data)

for i in mycounter:
    print(i)
(10, 100)
(11, 200)
(12, 300)
data = [100,200,300]
mycounter = zip(itertools.count(start=10,step=10), data)

for i in mycounter:
    print(i)
(10, 100)
(20, 200)
(30, 300)

6. StopIteration

StopIteration 異常用於標識迭代的完成,防止出現無限循環的情況,在 next() 方法中我們可以設置在完成指定循環次數後觸發 StopIteration 異常來結束迭代

list = [1,2,3]
myiter = iter(list)    # 創建迭代器對象
 
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
1
2
3

---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-26-6e3259c059c9> in <module>()
      5 print(next(myiter))
      6 print(next(myiter))
----> 7 print(next(myiter))


StopIteration: 
list = [1,2,3]
myiter = iter(list)    # 創建迭代器對象

for i in myiter:
    print(i)
1
2
3
class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self 
    def __next__(self):
        if self.a <= 3:
            x = self.a
            self.a += 1
            return x
        else:
            raise StopIteration
            
myclass = MyNumbers()
myiter = iter(myclass)
 
for x in myiter:
    print(x)
1
2
3

  • 寫作不易,切勿白剽
  • 博友們的點贊關注就是對博主堅持寫作的最大鼓勵
  • 持續更新,未完待續…

上一篇Python入門(五)之 Python函數
下一篇Python入門(七)之 Python 類與對象

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章