python函數之默認參數、可變參數、關鍵字參數和更pythonic的編程

默認參數、可變參數、關鍵字參數

如果一個函數的參數中含有默認參數,則這個默認參數後的所有參數都必須是默認參數

也就是說默認參數要放在參數最後。

def format_date(year = 2007, month, day):
    print("%d-%02d-%02d" % (year, month, day))
# SyntaxError: non-default argument follows default argument
def format_date(year, month, day = 1):
    print("%d-%02d-%02d" % (year, month, day))

format_date(1994, 3) # 1994-03-01    
format_date(year = 1994, month = 3) # 1994-03-01
format_date(month = 3, day = 1, year = 1996) # 1994-03-01
format_date(1994, 3, 5) # 1994-03-05

使用 * 收集位置參數

>>> def print_args(*args):
...     print('Positional argument tuple:', args) 
...
>>> def print_more(required1, required2, *args):
...     print('Need this one:', required1)
...     print('Need this one too:', required2)
...     print('All the rest:', args)
...
>>> print_more('cap', 'gloves', 'scarf', 'monocle', 'mustache wax') 
Need this one: cap
Need this one too: gloves
All the rest: ('scarf', 'monocle', 'mustache wax')

求輸入正數的最大值

def _max(*num):
    tmp = 0
    for i in num:
        if i > tmp:
            tmp = i
    return tmp
_max(1,2,3,4,0)

輸出

4

使用 ** 收集關鍵字參數

>>> def print_kwargs(**kwargs):
...     print('Keyword arguments:', kwargs) ...
>>> print_kwargs(wine='mer', entree='mut', dessert='mac')
Keyword arguments: {'dessert': 'mac', 'wine': 'mer', 'entree': 'mut'}

函數定義小結

定義函數時,需要確定函數名和參數個數;
如果有必要,可以先對參數的數據類型做檢查;
函數體內部可以用return隨時返回函數結果;
函數執行完畢也沒有return語句時,自動return None。
函數可以同時返回多個值,但其實就是一個tuple

更pythonic的編程

循環遍歷區間元素

在Python2中,有range和xrange2種寫法,xrange是生成器寫法,更節省內存
Python3中的range等價於Python2中的xrange
生成器,只有在使用時纔會動態生成,而且只能使用1次,比如range(1000000),Python2中會在內存中生成1百萬個元素的列表,而在Python3不會生成列表,而是生成器,佔用很小的內存。

# 生成器與列表更加節省內存
# range(start, end, step)
# [start, end) 包含開頭不包含結尾
for i in range(1, 1000, 2) # python3
for i in range(6) # python2
for i in xrange(6) #python2

生成器擴展

 #定義一個生成器
odd = (num for num in range(10) if num % 2 == 1)
for num in odd:
    print(num)

# 定義一個生成器
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
print(type(fib(3)) )

<generator object fib at 0x10e610728>

for num in fib(3):
	print(num)

1
1
2

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield 3
    print('step 3')
    yield 5

gen = odd()

print(next(gen))
print(next(gen))
print(next(gen))

1
3
5

字符串拼接

更Pythonic寫法

names = ['Tom', 'Jack', 'Sam']
','.join(names) 

普通寫法

names = 'Tom' + 'Jack' + 'Sam'

每次+操作都會產生新字符串,造成內存浪費而join,整個過程中只會產生一個字符串對象

文件打開與關閉

更Pythonic寫法

with open('a.txt') as f:
    data = f.read()

普通寫法

f = open('a.txt')
try:
    data = f.read()
finally:
    f.close()

使用with,Python將自動管理文件流的打開與關閉,無需手動操作。

列表操作

更Pythonic寫法

from collections import deque

names = deque(['c', 'd', 'e'])
names.popleft()
names.appendleft('b')
names.append('f')
print(names)

deque([‘b’, ‘d’, ‘e’, ‘f’])

普通寫法

names = list['c', 'd', 'e']
names.pop(0)
names.insert(0, 'b')
names.append('f')

list也可以用pop(0)來刪除第一個元素,但是list在內存中是順序存儲的,刪除第一個元素,會導致之後的所有元素都會前移,效率很低,插入類似。 開頭如果有大量的刪除和插入操作,避免使用list。

解構賦值

Pythonic寫法

student = ['Tom', 18, 'male']
name, age, gender = student
print(name, age, gender)

Tom 18 male

num_list = [100, 19, 20, 98]
first, *left_num_list, last = num_list
print(first, left_num_list, last)

100 [19, 20] 98

student = [['Tom', (98, 96, 100)], ['Jack', (98, 96, 100)]]

for name, (first, second, third) in student:
    print(name, first, second, third)

Tom 98 96 100
Jack 98 96 100

student = {
    'name': 'Tom',
    'age': 18
}
# python3
for k, v in student.items():
    print('k', '-->', v)

# python2
for k, v in student.iteritems():
    print('k', '-->', v)

k --> Tom
k --> 18
字典也類似,在Python2中,字典的items方法將返回列表,當字典比較大時,這樣會很耗內存。而iteritems方法返回的是生成器。
Python3中,沒有iteritems,items等價於Python2的iteritems。

推導式

Pythonic寫法

# 生成1-100的奇數
odd = [i for i in range(1, 100) if i % 2 == 1]

# 集合a,b分別取一個數,找出和大於100的所有組合
result = [(x, y) for x in a_set for y in b_set if x + y > 100]

普通寫法

# 生成1-100的奇數
result = []
for i in range(100):
    if i % 2 == 1:
        result.append(i)
    
# 集合a,b分別去一個數,找出和大於100的所有組合
result = []
for x in a_set:
    for y in b_set:
        if x + y > 100:
        result.append((x, y))

參考文獻:Python專題-讓你的代碼更Pythonic

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