3.2 深入函数

调用函数

def read_prices(filename, debug):
...


prices = read_prices('prices.csv', True)


prices = read_prices(filename='prices.csv', debug=True)


默认参数

def read_prices(filename, debug=False):
...


d = read_prices('prices.csv')


首选关键字参数作为可选参数

parse_data(data, False, True) # ?????

parse_data(data, ignore_errors=True)
parse_data(data, debug=True)
parse_data(data, debug=True, ignore_errors=True)


设计最佳实践

d = read_prices('prices.csv', debug=True)


Python 开发工具将会在帮助功能或者帮助文档中显示这些名称。

返回值

return 语句返回一个值：

def square(x):
return x * x


def bar(x):
statements
return

a = bar(4)      # a = None

# OR
def foo(x):
statements  # No return

b = foo(4)      # b = None


多个返回值

def divide(a,b):
q = a // b      # Quotient
r = a % b       # Remainder
return q, r     # Return a tuple


x, y = divide(37,5) # x = 7, y = 2

x = divide(37, 5)   # x = (7, 2)


变量作用域

x = value # Global variable

def foo():
y = value # Local variable


局部变量

def read_portfolio(filename):
portfolio = []
for line in open(filename):
fields = line.split(',')
s = (fields[0], int(fields[1]), float(fields[2]))
portfolio.append(s)
return portfolio


>>> stocks = read_portfolio('portfolio.csv')
>>> fields
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'fields' is not defined
>>>


全局变量

name = 'Dave'

def greeting():
print('Hello', name)  # Using name global variable


name = 'Dave'

def spam():
name = 'Guido'

spam()
print(name) # prints 'Dave'


修改全局变量

name = 'Dave'

def spam():
global name
name = 'Guido' # Changes the global name above


参数传递

def foo(items):
items.append(42)    # Modifies the input object

a = [1, 2, 3]
foo(a)
print(a)                # [1, 2, 3, 42]


重新赋值与修改

def foo(items):
items.append(42)    # Modifies the input object

a = [1, 2, 3]
foo(a)
print(a)                # [1, 2, 3, 42]

# VS
def bar(items):
items = [4,5,6]    # Changes local items variable to point to a different object

b = [1, 2, 3]
bar(b)
print(b)                # [1, 2, 3]


练习

report.py 的中心部分主要用于读取 CSV 文件。例如，read_portfolio() 函数读取包含投资组合数据的文件，read_prices() 函数读取包含价格数据的文件。在这两个函数中，有很多底层的“精细的”事以及相似的特性。例如，它们都打开一个文件并使用 csv 模块来处理，并且将各种字段转换为新的类型。

练习 3.3：读取 CSV 文件

# fileparse.py
import csv

def parse_csv(filename):
'''
Parse a CSV file into a list of records
'''
with open(filename) as f:

records = []
for row in rows:
if not row:    # Skip rows with no data
continue
records.append(record)

return records


>>> portfolio = parse_csv('Data/portfolio.csv')
>>> portfolio
[{'price': '32.20', 'name': 'AA', 'shares': '100'}, {'price': '91.10', 'name': 'IBM', 'shares': '50'}, {'price': '83.44', 'name': 'CAT', 'shares': '150'}, {'price': '51.23', 'name': 'MSFT', 'shares': '200'}, {'price': '40.37', 'name': 'GE', 'shares': '95'}, {'price': '65.10', 'name': 'MSFT', 'shares': '50'}, {'price': '70.44', 'name': 'IBM', 'shares': '100'}]
>>>


练习 3.4：构建列选择器

>>> # Read all of the data
>>> portfolio = parse_csv('Data/portfolio.csv')
>>> portfolio
[{'price': '32.20', 'name': 'AA', 'shares': '100'}, {'price': '91.10', 'name': 'IBM', 'shares': '50'}, {'price': '83.44', 'name': 'CAT', 'shares': '150'}, {'price': '51.23', 'name': 'MSFT', 'shares': '200'}, {'price': '40.37', 'name': 'GE', 'shares': '95'}, {'price': '65.10', 'name': 'MSFT', 'shares': '50'}, {'price': '70.44', 'name': 'IBM', 'shares': '100'}]

>>> # Read only some of the data
>>> shares_held = parse_csv('Data/portfolio.csv', select=['name','shares'])
>>> shares_held
[{'name': 'AA', 'shares': '100'}, {'name': 'IBM', 'shares': '50'}, {'name': 'CAT', 'shares': '150'}, {'name': 'MSFT', 'shares': '200'}, {'name': 'GE', 'shares': '95'}, {'name': 'MSFT', 'shares': '50'}, {'name': 'IBM', 'shares': '100'}]
>>>


# fileparse.py
import csv

def parse_csv(filename, select=None):
'''
Parse a CSV file into a list of records
'''
with open(filename) as f:

# If a column selector was given, find indices of the specified columns.
# Also narrow the set of headers used for resulting dictionaries
if select:
indices = [headers.index(colname) for colname in select]
else:
indices = []

records = []
for row in rows:
if not row:    # Skip rows with no data
continue
# Filter the row if specific columns were selected
if indices:
row = [ row[index] for index in indices ]

# Make a dictionary
records.append(record)

return records


>>> headers = ['name', 'date', 'time', 'shares', 'price']
>>>


>>> select = ['name', 'shares']
>>>


>>> indices = [headers.index(colname) for colname in select ]
>>> indices
[0, 3]
>>>


>>> row = ['AA', '6/11/2007', '9:50am', '100', '32.20' ]
>>> row = [ row[index] for index in indices ]
>>> row
['AA', '100']
>>>


练习 3.5：执行类型转换

>>> portfolio = parse_csv('Data/portfolio.csv', types=[str, int, float])
>>> portfolio
[{'price': 32.2, 'name': 'AA', 'shares': 100}, {'price': 91.1, 'name': 'IBM', 'shares': 50}, {'price': 83.44, 'name': 'CAT', 'shares': 150}, {'price': 51.23, 'name': 'MSFT', 'shares': 200}, {'price': 40.37, 'name': 'GE', 'shares': 95}, {'price': 65.1, 'name': 'MSFT', 'shares': 50}, {'price': 70.44, 'name': 'IBM', 'shares': 100}]

>>> shares_held = parse_csv('Data/portfolio.csv', select=['name', 'shares'], types=[str, int])
>>> shares_held
[{'name': 'AA', 'shares': 100}, {'name': 'IBM', 'shares': 50}, {'name': 'CAT', 'shares': 150}, {'name': 'MSFT', 'shares': 200}, {'name': 'GE', 'shares': 95}, {'name': 'MSFT', 'shares': 50}, {'name': 'IBM', 'shares': 100}]
>>>


...
if types:
row = [func(val) for func, val in zip(types, row) ]
...


练习 3.6：处理无标题的数据

"AA",9.22
"AXP",24.85
"BA",44.85
"BAC",11.27
...


>>> prices = parse_csv('Data/prices.csv', types=[str,float], has_headers=False)
>>> prices
[('AA', 9.22), ('AXP', 24.85), ('BA', 44.85), ('BAC', 11.27), ('C', 3.72), ('CAT', 35.46), ('CVX', 66.67), ('DD', 28.47), ('DIS', 24.22), ('GE', 13.48), ('GM', 0.75), ('HD', 23.16), ('HPQ', 34.35), ('IBM', 106.28), ('INTC', 15.72), ('JNJ', 55.16), ('JPM', 36.9), ('KFT', 26.11), ('KO', 49.16), ('MCD', 58.99), ('MMM', 57.1), ('MRK', 27.58), ('MSFT', 20.89), ('PFE', 15.19), ('PG', 51.94), ('T', 24.79), ('UTX', 52.61), ('VZ', 29.26), ('WMT', 49.74), ('XOM', 69.35)]
>>>


练习 3.7：选择其它的列分隔符

name shares price
"AA" 100 32.20
"IBM" 50 91.10
"CAT" 150 83.44
"MSFT" 200 51.23
"GE" 95 40.37
"MSFT" 50 65.10
"IBM" 100 70.44


csv.reader() 函数允许像下面这样指定不同的分隔符：

rows = csv.reader(f, delimiter=' ')


>>> portfolio = parse_csv('Data/portfolio.dat', types=[str, int, float], delimiter=' ')
>>> portfolio
[{'price': '32.20', 'name': 'AA', 'shares': '100'}, {'price': '91.10', 'name': 'IBM', 'shares': '50'}, {'price': '83.44', 'name': 'CAT', 'shares': '150'}, {'price': '51.23', 'name': 'MSFT', 'shares': '200'}, {'price': '40.37', 'name': 'GE', 'shares': '95'}, {'price': '65.10', 'name': 'MSFT', 'shares': '50'}, {'price': '70.44', 'name': 'IBM', 'shares': '100'}]
>>>


说明

posted @ 2021-03-01 23:16  codists  阅读(234)  评论(0编辑  收藏  举报