1. 程式人生 > >python3 基礎和進階詳細個人筆記整理

python3 基礎和進階詳細個人筆記整理

lambda表示式

lambda用來宣告匿名函式,用於臨時需要一個類似函式功能的場景,可以結合python的內建函式使用,比如map()。

>>> function=lambda a,b,c: a*b*c # 起名lambda表示式為function
>>> print(function(2,3,4))
24
# 定義一個字典,裡面有兩個鍵f1,f2,對應兩個lambda函式
>>> dict={'f1':(lambda x,y:x+y),'f2':(lambda x,y:x*y)}
>>> print(dict['f1'
](2,3)) 5 >>> print(dict['f2'](2,3)) 6

關於lambda區域性變數的錯誤:

>>> r=[]
>>> for x in range(10):
...     r.append(lambda: x**2)
... 
>>> r[1]()
81
>>> r[0]()
81
>>> r[2]()
81
>>> r[3]()
81
>>> x=2
>>> r[1]()
4
>>> r[2
]() 4 >>> r[3]() 4

如果改為以下則正確:

>>> r=[]
>>> for x in range(10):
...     r.append(lambda n=x: n**2)
... 
>>> r[0]()
0
>>> r[1]()
1
>>> r[2]()
4
>>> r[3]()
9
>>> x=2
>>> r[0]()
0
>>> r[1]()
1
>>> r[3]()
9

關於以上全域性和區域性錯誤的另一個示例:

>>> f=lambda:i #返回i
>>> i=2
>>> f()
2
>>> i=5
>>> f()
5
>>> i=4
>>> f()
4

生成器

包含yield語句的函式叫做生成器函式。
生成器具有惰性求值的特點,可以用於大資料。
return一旦執行就立刻結束函式;yield則是返回一個值,然後掛起yield語句後面的程式碼,使用__next__()可以恢復執行。

# 使用生成器生成斐波那契數列
>>> def f():
...     a,b=1,1
...     while True:
...             yield a
...             a,b=b,a+b #序列解包
... 
>>> a=f()
>>> for i in range(10):
...     print(a.__next__(),end=' ')
... 
1 1 2 3 5 8 13 21 34 55 

簡單的分析(此處是草稿可跳過,我只是看看
markdown的圖表怎麼弄 -_-||)

a b yield
1 1 1
1 2 1
2 3 2
3 5 3
5 8 5

*args 和 **kwargs

這是魔法變數,實際上args和kwargs不是固定的,可以是任何命名,只要有和*就行。
*args 和 **kwargs 主要用於在函式定義的時候把不定數量的引數傳遞給一個函式。

*args

簡單的例子:

def test_var_args(f_arg, *argv):
    print("first normal arg:", f_arg)
    for arg in argv:
        print("another arg through *argv:", arg)

test_var_args('yasoob', 'python', 'eggs', 'test')
這會產生如下輸出:
first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: test

**kwargs

**kwargs 將不定長度的鍵值對,作為引數傳遞給一個函式。

  1 def greet_me(*args, **kwargs):
  2     for v in args:
  3         print("hello, {0}".format(v))
  4     for key, value in kwargs.items():
  5         print("{0} is {1}".format(key, value))
  6 
  7 
  8 greet_me('andy', 'smith', name1="jane", name2='john', name3='claire')

輸出:
hello, andy
hello, smith
name1 is jane
name2 is john
name3 is claire

使用 *args 和 **kwargs 來呼叫函式

def test_args_kwargs(arg1, arg2, arg3):
    print("arg1:", arg1)
    print("arg2:", arg2)
    print("arg3:", arg3)

# 使用 *args
args = ("two", 3, 5)
test_args_kwargs(*args)
# 結果:
arg1: two
arg2: 3
arg3: 5

# 使用 **kwargs:
kwargs = {"arg3": 3, "arg2": "two", "arg1": 5}
test_args_kwargs(**kwargs)

# 結果:
arg1: 5
arg2: two
arg3: 3

使用時的順序

標準的引數, 然後是*, 然後是**
some_func(fargs, *args, **kwargs)

修飾器(裝飾器)

是函式巢狀的一個重要應用。
本質:修飾器是一個函式,只不過函式的引數是其它函式,也就是說接受其它函式作為傳入引數,對傳入的函式做一定的修改之後,返回一個新的函式。

從函式中返回函式

   1 def hi(name="vic"):
  2     def greet():
  3         return "now you are in the greet() function. hello vic."
  4 
  5     def welcome():
  6         n = name
  7         return "now you are in the welcome() function. hello " + n
  8 
  9     if name == "vic":
 10         return greet
 11     else:
 12         return welcome
 13 
 14 a = hi()
 15 print(a)
 16 #outputs: <function greet at 0x7f2143c01500>
 17 
 18 #上面清晰地展示了`a`現在指向到hi()函式中的greet()函式
 19 #現在試試這個
 20 
 21 print(a())
 22 #outputs: now you are in the greet() function. hello, vic.
 23 
 24 b = hi('lara')()
 25 print(b)
 26 
 27 # namely
 28 # b = hi('lara')
 29 # print(b())
 30 
 31 #outputs: now you are in the welcome() function. hello lara

什麼是裝飾器

裝飾器裡面定義一個wrap函式對需要裝飾的函式進行包裝,裝飾器返回wrap函式,注意是wrapTheFunction不帶括號

  1 def a_new_decorator(a_func):
  2 
  3     def wrapTheFunction():
  4         print("I am doing some boring work before executing a_func()")
  5 
  6         a_func()
  7 
  8         print("I am doing some boring work after executing a_func()")
  9 
 10     return wrapTheFunction
 11 
 12 def a_function_requiring_decoration():
 13     print("I am the function which needs some decoration to remove my foul smell")
 14 
 15 a_function_requiring_decoration()
 16 #outputs: "I am the function which needs some decoration to remove my foul smell"
 17 
 18 # 對a_function_requiring_decoration進行裝飾
 19 a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
 20 #now a_function_requiring_decoration is wrapped by wrapTheFunction()
 21 
 22 a_function_requiring_decoration()
 23 #outputs:I am doing some boring work before executing a_func()
 24 #        I am the function which needs some decoration to remove my foul smell
 25 #        I am doing some boring work after executing a_func()

使用@符號修改上面的栗子:

  1 def a_new_decorator(a_func):
  2 
  3     def wrapTheFunction():
  4         print("I am doing some boring work before executing a_func()")
  5 
  6         a_func()
  7 
  8         print("I am doing some boring work after executing a_func()")
  9 
 10     return wrapTheFunction
 11 
 12 @a_new_decorator # 相當於一種簡寫,在需要裝飾的函式定義上面加上@裝飾器即可。
 13 def a_function_requiring_decoration():
 14     print("I am the function which needs some decoration to remove my foul smell")
 15 
 16 a_function_requiring_decoration()
 17 #outputs:I am doing some boring work before executing a_func()
 18 #        I am the function which needs some decoration to remove my foul smell
 19 #        I am doing some boring work after executing a_func()

但是目前存在一個問題:
如果我們執行打印出a_function_requiring_decoration的函式名,會發現實際上答應出了wrapTheFunction

 # print the name of the decorated funciton
 print(a_function_requiring_decoration.__name__)

會打印出:

wrapTheFunction

而不是我們所想要的“a_function_requiring_decoration”。因為wrapTheFunction重寫了我們函式的名字和註釋文件(docstring)。
可以通過一個內建函式解決這個問題:
functools.wraps

  1 #匯入一個內建函式wrap
  2 from functools import wraps
  3 
  4 def a_new_decorator(a_func):
  5 
  6     #使用wrap裝飾傳入進來作為的引數函式
  7     @wraps(a_func)
  8     def wrapTheFunction():
  9         print("I am doing some boring work before executing a_func()")
 10 
 11         a_func()
 12 
 13         print("I am doing some boring work after executing a_func()")
 14 
 15     return wrapTheFunction
 16 
 17 @a_new_decorator
 18 def a_function_requiring_decoration():
 19     print("I am the function which needs some decoration to remove my foul smell")
 20 
 21 a_function_requiring_decoration()
 22 #outputs:I am doing some boring work before executing a_func()
 23 #        I am the function which needs some decoration to remove my foul smell
 24 #        I am doing some boring work after executing a_func()
 25 
 26 # print the name of the decorated funciton
 27 print(a_function_requiring_decoration.__name__)

輸出為:
I am doing some boring work before executing a_func()
I am the function which needs some decoration to remove my foul smell
I am doing some boring work after executing a_func()
a_function_requiring_decoration

另外一個裝飾器使用的示例:

定義函式呼叫之前和之後要執行的程式碼

  1 def before(func):
  2     def wrapper(*args, **kwargs):
  3         print('Before function is called.')
  4         return func(*args, **kwargs)
  5     return wrapper
  6 
  7 def after(func):
  8     def wrapper(*args, **kwargs):
  9         result = func(*args, **kwargs)
 10         print('After function is called.')
 11         return result
 12     return wrapper
 13 
 14 @before
 15 @after
 16 def test():
 17     print(3)

執行結果:
Before function is called.
3
After function is called.

協程

協程(Coroutine)可以實現單執行緒併發程式碼。
即各個子任務協作執行的意思,可以解決非同步問題。

這裡寫程式碼片

元類 - metaclass

參考文獻