0%

Python学习笔记-5-函数

Python中内置了许多函数,但也允许用户自己构建函数。为了更好的理解Python函数,下面先学习如何构建函数,再学习Python的内置函数。

1 构建函数

1.1 参数

先来看一个简单的自定义函数:

1
2
3
4
5
# 构建一个问候用户的函数
def greet_user(username):
print(f"Hello, {username.title()}!")

greet_user('jack')
Hello, Jack!

在上面这个例子中,定义了一个向用户打招呼的函数,变量username是一个形参,即完成其工作所需要的一项信息。调用此函数时,值‘jack’是一个实参,实参是调用函数时传递给函数的信息。

函数的参数还可分为位置参数和关键字参数。

1.1.1 位置参数

使用位置参数来调用函数时,实参的顺序很重要。

1
2
3
4
5
def describe_pet(animal_type, pet_name):
print(f"I have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet('dog', 'willie')
I have a dog.
My dog's name is Willie.

在调用这个描述宠物的函数时,要按照对应位置写明实参,‘dog’和‘willie’的顺序不可更改。否则容易引起歧义或报错:

1
describe_pet('willie', 'dog')
I have a willie.
My willie's name is Dog.

1.1.2 关键字参数

关键字实参是传递给函数的名称-值对。直接在实参中将名称和值关联起来,因此向函数传递实参时不会混淆。关键字参数让你无需考虑函数调用中的实参顺序,还清楚的指出了函数调用中各个值用途。

1
describe_pet(animal_type = 'dog', pet_name = 'willie')
I have a dog.
My dog's name is Willie.
1
describe_pet(pet_name = 'willie', animal_type = 'dog')
I have a dog.
My dog's name is Willie.

1.1.3 默认值

编写函数时,可以给每个形参指定默认值。在调用函数时,如果给形参提供了实参,Python将使用指定的实参值,否则会使用形参的默认值。注意:在编写函数时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的实参。

1
2
3
4
5
6
def describe_pet(pet_name, animal_type = 'dog'):
print(f"I have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")

# 不提供‘animal_type’,函数将使用默认值‘dog’
describe_pet('willie')
I have a dog.
My dog's name is Willie.
1
2
# 提供‘animal_type’,函数将使用提供值
describe_pet('harry', 'cat')
I have a cat.
My cat's name is Harry.
1
2
# 使用关键字参数,可以忽略顺序
describe_pet(animal_type='cat', pet_name='harry')
I have a cat.
My cat's name is Harry.

1.2 返回值

函数并非直接显示输出,它还可以处理一些数据,并返回一个或一组值。函数返回的值被称为返回值。在函数中,可使用return语句将值返回到函数的代码行。返回值能让你将程序的大部分繁重工作移到函数中,从而简化主程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_formatted_name(first_name, last_name, middle_name=''):
if middle_name:
full_name = ' '.join([first_name,middle_name,last_name])
else:
full_name = ' '.join([first_name,last_name])
return full_name.title()


musician = get_formatted_name('jimi', 'hendrix')
print(musician)

musician = get_formatted_name('jimi','hooker','lee')
print(musician)
Jimi Hendrix
Jimi Lee Hooker

函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。

1
2
3
4
5
6
7
8
def build_person(first_name, last_name, age=''):
person = {'first_name':first_name, 'last_name':last_name}
if age:
person['age'] = age
return person

musician = build_person('jimi', 'hendrix', 18)
print(musician)
{'first_name': 'jimi', 'last_name': 'hendrix', 'age': 18}

把函数和while循环结合使用,可以完成更多更复杂的任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def get_formatted_name(first_name, last_name, middle_name=''):
if middle_name:
full_name = ' '.join([first_name,middle_name,last_name])
else:
full_name = ' '.join([first_name,last_name])
return full_name.title()

while True:
print('\nPlease tell me your name: ')
print("(enter 'q' at anytime to quit)")

first_name = input('First name: ')
if first_name == 'q':
break

middle_name = input("Middle name(nothing to input if you don't have): ")
if middle_name == 'q':
break

last_name = input('Last name: ')
if last_name == 'q':
break

formatede_name = get_formatted_name(first_name, last_name, middle_name)
print(f"\nHello, {formatede_name}!")
Please tell me your name: 
(enter 'q' at anytime to quit)


First name:  albert
Middle name(nothing to input if you don't have):  
Last name:  einstein


Hello, Albert Einstein!

Please tell me your name: 
(enter 'q' at anytime to quit)


First name:  john
Middle name(nothing to input if you don't have):  lee
Last name:  hooker


Hello, John Lee Hooker!

Please tell me your name: 
(enter 'q' at anytime to quit)


First name:  q

1.3 传递列表

将列表传递给函数后,函数就可对访问、修改列表。在函数中对列表所做的任何修改都是永久性的,这有助于高效的处理大量数据。

1
2
3
4
5
6
7
def greet_user(names):
for name in names:
message = "Hello, " + name.title() + '!'
print(message)

usernames = ['jack', 'tom', 'john']
greet_user(usernames)
Hello, Jack!
Hello, Tom!
Hello, John!

来看一家为用户提交的设计制作3D打印模型的公司。需要打印的设计存储在一个列表中,打印后移动到另一个列表中。下面在不适用函数的情况下模拟这个过程:

1
2
3
4
5
6
7
8
9
10
11
unprited_designs = ['iphone case', 'robot phone', 'android phone']
completed_models = []

while unprited_designs:
current_design = unprited_designs.pop()
print("Printing model: ", current_design)
completed_models.append(current_design)

print("\nThe following models have been printed:")
for completed_model in completed_models:
print(' - ', completed_model)
Printing model:  android phone
Printing model:  robot phone
Printing model:  iphone case

The following models have been printed:
 -  android phone
 -  robot phone
 -  iphone case

下面使用两个函数进行处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
unprited_designs = ['iphone case', 'robot phone', 'android phone']
completed_models = []

def print_models(unprinted_designs, completed_models):
while unprinted_designs:
current_design = unprinted_designs.pop()
print("Printing model: ", current_design)
completed_models.append(current_design)

def show_completed_models(completed_models):
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(' - ', completed_model)


print_models(unprited_designs, completed_models)
show_completed_models(completed_models)
Printing model:  android phone
Printing model:  robot phone
Printing model:  iphone case

The following models have been printed:
 -  android phone
 -  robot phone
 -  iphone case

在上面的例子中,使用两个函数可以让程序组织更为有序,而且完成大部分工作的代码都移动到两个函数中,这样让主程序更容易理解。而且,相比较于没有使用函数的版本,这个程序更容易扩展和维护。如果以后需要打印其他设计,只需要再次调用print_models()函数即可。如果需要对打印代码进行修改,只需修改这些代码一次,就能影响所有调用该函数的地方。与分别修改程序的多个地方相比,这种修改的效率更高。

这个程序还演示了这样一个理念,即每个函数都应只负责一项具体的工作。第一个函数打印每个设计,而第二个函数显示打印好的模型;这优于使用一个函数来完成两项工作。编写函数的时候,如果你发现它执行的任务太多,请尝试将这些代码划分到两个函数中。别忘了,总是可以在一个函数中调用另一个函数,这有助于将复杂的任务划分成一系列的步骤。

在上面的例子中,函数对未打印的设计列表unprinted_designs进行了修改,如果你想保留此列表,可以向函数传递列表的副本而不是原件,这样函数所做的任何修改都只影响副本。传递副本的方法很简单,就是使用切片法,即unprinted_designs[:],在调用函数时,使用以下语句:

1
print_models(unprinted_designs[:], completed_models)

1.4 函数实参进阶

1.4.1 传递任意数量的实参

有时候,你预先不知道函数需要接受多少个实参,好在Python允许函数从调用语句中收集任意数量的实参。

下面来看一个制作匹萨的函数,它需要接受很多配料,但你无法预先确定顾客需要多少配料。下面的函数中有一个形参*toppings,不管调用语句提供了多少实参,这个形参都将它们通通收入囊中。形参名*toppings中的星号*让Python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中。不管函数收到的实参有多少,这种语法都管用。

1
2
3
4
5
6
def make_pizza(*toppings):
print("\nMaking a pizza with the following toppings:")
for topping in toppings:
print(' - ', topping)

make_pizza('pepperoni', 'mushroom', 'extra cheese')
Making a pizza with the following toppings:
 -  pepperoni
 -  mushroom
 -  extra cheese

1.4.2 传递不同类型的实参

如果让函数接收不同类型的实参,必须把函数定义中接纳任意数量实参的形参放在最后。Python先匹配位置实参和关键字实参,再将剩余的实参都收集到最后一个形参中。

1
2
3
4
5
6
def make_pizza(size, *toppings):
print(f"Making a {str(size)}-inch pizza with the following toppings:")
for topping in toppings:
print(' - ', topping)

make_pizza(16, 'pepperoni', 'mushroom', 'extra cheese')
Making a 16-inch pizza with the following toppings:
 -  pepperoni
 -  mushroom
 -  extra cheese

1.4.3 使用任意数量的关键字实参

有时候需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种情况下,可将函数编写成能接受任意数量的键-值对,调用语句提供了多少就接受多少。

下面是一个创建用户简介的函数,你知道将受到有关用户的信息,但不确定会是什么样的信息。形参**user_info中的两个星号让Python创建一个名为user_info的空字典,并将收到的所有键值对都封装到这个字典中。

1
2
3
4
5
6
7
8
9
10
11
12
def build_profile(first_name, last_name, **user_info):
profile = {}
profile['first_name'] = first_name
profile['last_name'] = last_name
for key,value in user_info.items():
profile[key] = value
return profile

user_profile = build_profile('albert', 'einstein',
location = 'princeton', field = 'physics')

print(user_profile)
{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}

1.5 将函数存储在模块中

函数的优点之一是,使用它们可将代码块与主程序分离。通过给函数指定描述性名称,可让主程序更容易理解。还可以将函数存储在被称为模块的独立文件中,再将模块导入到主程序使用。通过将函数存储再独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上。还可以让众多不同的程序重复调用函数,与他人共享函数文件而不是整个程序。

1.5.1 创建并导入模块

模块是扩展名为.py的文件,包含要导入到程序中的代码。把制作匹萨的函数另存为pizza.py的文件即可。

1
2
3
import pizza
# pizza是模块名,make_pizza是函数名
pizza.make_pizza(12, 'pepperoni')
Making a 12-inch pizza with the following toppings:
 -  pepperoni

1.5.2 导入特定函数

一个模块可能不只一个函数,这时可以使用下列语法语句导入特定的函数:

from module_name import function_name

也可通过逗号分隔函数名,根据需要导入任意数量的函数:

from module_name import function_0, function_1, function_2

使用星号*可让Python导入模块中所有的函数

from module_name import *
1
2
from pizza import make_pizza
make_pizza(16, 'pepperoni', 'extra cheese')
Making a 16-inch pizza with the following toppings:
 -  pepperoni
 -  extra cheese
1
2
from pizza import *
make_pizza(16, 'pepperoni', 'extra cheese')
Making a 16-inch pizza with the following toppings:
 -  pepperoni
 -  extra cheese

1.5.3 使用as给模块或为函数指定别名

如果要导入的模块或函数名称太长或可能与程序中现有的名称冲突,可以指定简短的别名。只需在import语句中使用关键字as即可。

1
2
import pizza as p
p.make_pizza(16, 'pepperoni', 'extra cheese')
Making a 16-inch pizza with the following toppings:
 -  pepperoni
 -  extra cheese
1
2
from pizza import make_pizza as mp
mp(16, 'pepperoni', 'extra cheese')
Making a 16-inch pizza with the following toppings:
 -  pepperoni
 -  extra cheese

2. Python内置函数

为了方便大家使用,Python开发者在Python程序中已经内置了一些函数,可以直接使用。Python内置函数(3.7版本)共有69个,大致可分为数学运算类、类型转换类、容器类型及操作类、交互操作类、文件操作类、对象操作类等几大类型。

2.1 数学运算类

  • max() 返回可迭代对象中最大的元素,或者返回两个及以上实参中最大的。如果有多个最大元素,则此函数将返回第一个找到的。

  • min() 返回可迭代对象中最小的元素,或者返回两个及以上实参中最小的。如果有多个最小元素,则此函数将返回第一个找到的。

  • sum(iterable, start) 对 iterable 中的项求和后再与 start 相加,最后返回总计值。注意传入sum()函数的必须是可迭代对象,不能是实参,iterable 的项通常为数字,开始值则不允许为字符串。start 为可选项,默认为 0 。对某些用例来说,存在 sum() 的更好替代。 拼接字符串序列的更好更快方式是调用 ''.join(sequence)。 要以扩展精度对浮点值求和,请参阅 math.fsum()。 要拼接一系列可迭代对象,请考虑使用itertools.chain()。

  • len() 返回对象的长度(元素个数)。实参可以是序列(如 string、bytes、tuple、list 或 range 等)或集合(如 dictionary、set 或 frozen set 等)。

  • abs() 返回一个数的绝对值。实参可以是整数或浮点数。如果实参是一个复数,返回它的模。

  • round(number, ndigits) 返回 number 舍入到小数点后 ndigits 位精度的值。 任何整数值都可作为有效的 ndigits (正数、零或负数)。如果 ndigits 被省略或为 None,则返回最接近输入值的整数。

  • pow(x, y, z) 返回 x 的 y 次幂。z 为可选参数,如果 z 存在,则对 z 取余(比直接 pow(x, y) % z 计算更高效)。

  • divmod(a, b) 它将两个(非复数)数字作为实参,并在执行整数除法时返回一个包含商和余数的元组(a // b, a % b)

1
2
3
4
5
# 传入一个可迭代对象,取其最大元素值。
alist = [-5, -1, 0, 1, 3]
max_number = max(alist)
max_abs_number = max(alist, key=abs) # 求绝对值最大的元素
print(max_number, max_abs_number)
3 -5
1
2
3
4
5
# 传入一个可迭代对象,返回相加值
alist = [-5, -1, 0, 1, 3]
sum_number = sum(alist)
sum_number_add = sum(alist,2) # 传入可迭代对象和start,返回可迭代对象总和与start的相加值
print(sum_number, sum_number_add)
-2 0
1
2
3
from math import pi
print(pi)
print(round(pi, 2))
3.141592653589793
3.14
1
2
3
4
a = pow(2, 3)
b = 8 % 3
c = pow(2,3,3)
print(a,b,c)
8 2 2
1
2
3
4
5
a = 7
b = 3
print(a // b)
print(a % b)
print(divmod(a,b))
2
1
(2, 1)

2.2 类型转换

2.2.1 数字类型

  • int(x, base) 返回一个使用数字或字符串 x 生成的整数对象。x 有两种类型 int 和 str。若 x 为纯数字,则不能有 base 参数,否则报错,其作用为对入参 x 取整。若 x 为 str,则 base 可略可有:base 存在时,视 x 为 base 类型数字,并将其转换为 10 进制数字;若 x 不符合 base 规则,则报错,str需为整数。
  • float(x) 返回从数字或字符串 x 生成的浮点数。
  • complex(real, imag) 返回值为 real + imag*1j 的复数,或将字符串或数字转换为复数。imag为可选项,则默认值为零。
1
2
3
4
5
6
a = int(2.6)        # 取整
b = int('1001') # 不指定base,则把'1001'默认为10进制数字
c = int('1001', 2) # 指定base,表示'1001'为2进制数字
d = int('123', 8) # 指定base,表示'123'为8进制数字
e = int('0xa', 16) # 指定base,表示'0xa'为16进制数字
print(a, b, c, d, e)
2 1001 9 83 10

2.2.2 进制类型

  • bin(x) 将一个整数转变为一个前缀为“0b”的二进制字符串。

  • oct(x) 将一个整数转变为一个前缀为“0o”的八进制字符串。

  • hex(x) 将整数转换为以“0x”为前缀的小写十六进制字符串。

1
2
3
4
a = bin(9)
b = oct(83)
c = hex(10)
print(a, b, c)
0b1001 0o123 0xa

2.2.3 其他转换

  • bool(x) 返回一个布尔值,True 或者 False。数值0、空序列、空元组、空字典等值为False。

  • str(x) 返回一个对象的字符串表现形式。

  • chr(i) 返回整数所对应的Unicode字符。

  • ord(c) 返回Unicode字符对应的整数。

1
2
print(chr(97))
print(ord('a'))
a
97

2.3 容器类型及操作

2.3.1 四种容器类型

  • 列表: list() 虽然被称为函数,list 实际上是一种可变序列类型,通常用于存放同类项目的集合。

  • 元组: tuple() 虽然被称为函数,但 tuple 实际上是一个不可变的序列类型,通常用于储存异构数据的多项集

  • 字典: dict() 创建一个新的字典。dict 对象是一个字典类。

  • 集合: set([iterable])frozenset([iterable]) 返回一个新的 set 或 frozenset 对象,可以选择带有从 iterable 获取的元素。frozenset 产生一个不可变的set。

1
2
3
4
5
6
a = dict(one=1, two=2, three=3)
b = {'one': 1, 'two': 2, 'three': 3}
c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
d = dict([('two', 2), ('one', 1), ('three', 3)])
e = dict({'three': 3, 'one': 1, 'two': 2})
a == b == c == d == e
True
1
2
3
a = set(range(10))
b = frozenset(range(10))
print(a, '\n', b)
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 
 frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})

2.3.2 应用于容器的其他操作函数

  • range(start, stop, step) 虽然被称为函数,但 range 实际上是一个不可变的序列类型。step为可选参数,默认为1。该函数只能产生整数序列,不能产生浮点数。
1
2
3
print(list(range(10)))
print(tuple(range(0, 10, 2)))
print(set(range(0, -10, -2)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
(0, 2, 4, 6, 8)
{0, -8, -6, -4, -2}
  • enumerate(iterable, start=0) 返回一个枚举对象。iterable 必须是一个序列,或 iterator,或其他支持迭代的对象。 enumerate() 返回的迭代器的 __next__() 方法返回一个元组,里面包含一个计数值(从 start 开始,默认为 0)和通过迭代 iterable 获得的值。
1
2
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
1
list(enumerate(seasons, start = 1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
  • sorted(iterable, *, key=None, reverse=False) 根据 iterable 中的项返回一个新的已排序列表。具有两个可选参数,它们都必须指定为关键字参数。key 指定带有单个参数的函数,用于从 iterable 的每个元素中提取用于比较的键,默认值为 None (直接比较元素)。reverse 为一个布尔值。 如果设为 True,则每个列表元素将按反向顺序比较进行排序

  • reversed(seq) 返回一个反向的 iterator。

1
2
3
4
5
6
7
8
9
a = [5,7,6,3,4,1,2]
b = sorted(a)
c = sorted(a,reverse=True)
d = list(reversed(a))

print('a: ', a)
print('b: ', b)
print('c: ', c)
print('d: ', d)
a:  [5, 7, 6, 3, 4, 1, 2]
b:  [1, 2, 3, 4, 5, 6, 7]
c:  [7, 6, 5, 4, 3, 2, 1]
d:  [2, 1, 4, 3, 6, 7, 5]
1
2
3
4
5
6
a = ['is', 'handsome', 'a', 'boy', 'bruce']
b = sorted(a)
c = sorted(a, key=lambda x : len(x))
print(a)
print(b)
print(c)
['is', 'handsome', 'a', 'boy', 'bruce']
['a', 'boy', 'bruce', 'handsome', 'is']
['a', 'is', 'boy', 'bruce', 'handsome']
  • map(function, iterable, ...) 返回一个将 function 应用于 iterable 中每一项并输出其结果的迭代器。如果传入了额外的 iterable 参数,function 必须接受相同个数的实参并被应用于从所有可迭代对象中并行获取的项。 当有多个可迭代对象时,最短的可迭代对象耗尽则整个迭代就将结束。map()函数不改变原有的 list,而是返回一个新的 list。利用map()函数,可以把一个 list 转换为另一个 list,只需要传入转换函数。map()函数是一个非常有用的功能强大的内置函数,需要引起重视。
1
2
3
4
5
6
7
def squ(x):
return x ** 2

a = list(range(1,6))
b = list(map(squ, a))
print(a)
print(b)
[1, 2, 3, 4, 5]
[1, 4, 9, 16, 25]
  • filter(function, iterable) 用 iterable 中函数 function 返回真的那些元素,构建一个新的迭代器。iterable 可以是一个序列,一个支持迭代的容器,或一个迭代器。如果 function 是 None ,则会假设它是一个身份函数,即 iterable 中所有返回假的元素会被移除。通俗来讲,filter()函数就是使用指定方法过滤可迭代对象的元素。filter()函数是一个非常有用的功能强大的内置函数,需要引起重视。
1
2
3
4
5
6
7
def if_odd(x):
return x % 2 == 1

a = list(range(1,11))
b = list(filter(if_odd, a))
print(a)
print(b)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 3, 5, 7, 9]
  • zip(*iterables) 创建一个聚合了来自每个可迭代对象中的元素的迭代器。当所输入可迭代对象中最短的一个被耗尽时,迭代器将停止迭代。zip() 与 * 运算符相结合可以用来拆解一个列表,可简单理解为解压。
1
2
3
4
5
x = [1, 2, 3]
y = [4, 5, 6]

zipped_xy = list(zip(x, y))
print(zipped_xy)
[(1, 4), (2, 5), (3, 6)]
1
2
3
4
# 解压,默认解压出两个元组
x,y = zip(*zipped_xy)
print(x)
print(y)
(1, 2, 3)
(4, 5, 6)
  • all(iterable) 如果 iterable 的所有元素为真(或迭代器为空),返回 True
  • any(iterable) 如果 iterable 的任一元素为真则返回 True。 如果迭代器为空,返回 False。
1
2
3
#空字典
print(all({}))
print(any({}))
True
False

2.4 交互操作/文件操作/对象操作类

  • print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
    objects -- 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。
    sep -- 用来间隔多个对象,默认值是一个空格。
    end -- 用来设定以什么结尾。默认值是换行符 ,可以换成其他字符串。
    file -- 要写入的文件对象。默认值为 sys.stdout,代表了系统标准输出,也就是打印到当前屏幕。
    flush -- 输出是否被缓存通常决定于 file,但如果 flush 关键字参数为 True,流会被强制刷新。
1
2
# 打印多个对象,默认间隔为一个空格
print('iamgzc', 'wang')
iamgzc wang
1
2
# 打印多个对象,修改默认间隔
print('iamgzc', 'wang', sep = '.')
iamgzc.wang
1
2
3
# 默认结尾为换行符\n,打印结果太占用空间
for i in range(3):
print(i)
0
1
2
1
2
3
# 修改默认结尾
for i in range(3):
print(i, end = ' ')
0 1 2 
1
2
3
4
5
6
7
8
9
# 修改file参数让 print() 函数输出到特定文件中

f = open('print_test.txt','w')
print('This is a print test.', file = f)
f.close()

with open('print_test.txt') as f_obj:
contents = f_obj.read()
print(contents)
This is a print test.

在上面的例子中:

1
2
f = open('print_test.txt','w')
print('This is a print test.', file = f)

如果只执行这两行代码,运行后打开print_test.txt文件,会发现“This is a print test.”并未被写入,文件内容为空。这是因为print() 函数会把内容放到内存中,内存中的内容并不会及时刷新到文件中,只有f.close()后才将内容写进文件中。使用flush=True之后,会在print结束之后,立即将内存中的东西显示到文件上,清空缓存。可以把flush参数理解为刷新功能。

1
2
f = open('print_test2.txt','w')
print('This is a print test, too.', file = f, flush = True)

此时,不需要f.close(),打开文件print_test2.txt也可看到需要打印的内容。

1
2
3
4
5
6
7
8
9
10
# flush 参数的拓展应用
# 通过flush=True实现动态loading......效果
import time
print("Loading",end = "")

# 在Loading同一行后面每0.2秒输出1个点号,总共6个
# 如果不开启flush=True,则程序运行结果则是6x0.2秒后1次性输出Loading……
for i in range(6):
print(".",end = '',flush = True)
time.sleep(0.2)
Loading......
  • input([prompt]) 如果存在 prompt 实参,则将其写入标准输出,末尾不带换行符。接下来,该函数从输入中读取一行,将其转换为字符串(除了末尾的换行符)并返回。
1
2
s = input('please input your name:')
print(s)
please input your name: Jack


Jack
  • open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
    打开 file 并返回对应的 file object。
    file: 是一个 path-like object,表示将要打开的文件的路径(绝对路径或者当前工作目录的相对路径)。
    mode: 是一个可选字符串,用于指定打开文件的模式。默认值是 'rt' ,表示以文本模式(t)打开并读取(r)。常用的其他模式还有: 'w'--写入,如果文件存在内容会被清空。'a'--追加写入,如果文件存在内容则在末尾追加。'b'--以二进制模式打开文件。 encoding: 是用于解码或编码文件的编码的名称。这应该只在文本模式下使用。默认编码是依赖于平台的。一般可设置为encoding='utf-8'。

学习open()函数就有必要学习一些文件操作的相关指令。close()--关闭文件;read()--读取文件所有内容;readline()--以行的形式读取文件所有内容;write()--写入文件;

1
2
3
4
file = open('print_test.txt')
file_contents = file.read()
print(file_contents)
file.close()
This is a print test.
1
2
3
4
5
6
7
8
9
file = open('print_test.txt', 'a')
file.write('This is a write test.')
file.close()

file = open('print_test.txt')
lines = file.readlines()
for line in lines:
print(line.rstrip())
file.close()
This is a print test.
This is a write test.
1
2
3
4
5
6
7
8
# 使用with打开文件,with语句执行结束后内部会自动关闭并释放文件资源。

with open('print_test.txt', 'a') as file:
file.write("\nThis is a 'with' test.")

with open('print_test.txt') as file:
for line in file.readlines():
print(line.rstrip())
This is a print test.
This is a write test.
This is a 'with' test.
  • dir(object)
    如果没有实参,则返回当前本地作用域中的名称列表。如果有实参,它会尝试返回该对象的有效属性列表。
1
2
import math
print(dir(math))
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
  • help(object)
    启动内置的帮助系统(此函数主要在交互式中使用)。
1
help(math.ceil)
Help on built-in function ceil in module math:

ceil(x, /)
    Return the ceiling of x as an Integral.

    This is the smallest integer >= x.

2.5 其他

  • eval(expression, globals, locals)

实参是一个字符串,以及可选的 globals 和 locals。globals 实参必须是一个字典。locals 可以是任何映射对象。使用 globals 和 locals 字典作为全局和局部命名空间。 expression -- 表达式; globals -- 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象; locals -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。eval()函数用来执行一个字符串表达式,并返回表达式的值。还可以把字符串转化为list、tuple、dict。

1
2
3
# eval()返回表达式的值
a = eval("pow(2,3)")
print(a)
8
1
2
3
4
5
# eval()实现字符串转换成列表
str = "[1, 2, 3, 4, 5]"
alist = eval(str)
print(type(alist))
print(alist)
<class 'list'>
[1, 2, 3, 4, 5]
  • exec(object, globals, locals) 这个函数支持动态执行 Python 代码。object 必须是字符串或者代码对象。如果是字符串,那么该字符串将被解析为一系列 Python 语句并执行(除非发生语法错误)。注意:exec函数的返回值永远为None.exec()是一个十分有趣且实用的内置函数,值得重视。
    注意区分eval()函数与exec()函数的区别:eval()函数只能计算单个表达式的值,而exec()函数可以动态运行代码段;eval()函数可以有返回值,而exec()函数返回值永远为None。
1
2
3
4
# 执行简单的python代码
a = exec("pow(2,3)")
print(a) # 返回值为None
exec("print(pow(2,3))")
None
8
1
2
3
4
# 执行复杂的Python文件
file_path = "D:\Python\demo.py"
with open(file_path, 'r') as f:
exec(f.read())
Jen's favorite language are: 
    Python
    Ruby

Sarah's favorite language is: 
    C

Edward's favorite language are: 
    Ruby
    Go

Phil's favorite language are: 
    Python
    Haskell
1
2
3
4
5
# Python文件被保存为文本文件(.txt),也可以使用exec执行

file_path = "D:\Python\demo.txt"
with open(file_path, 'r') as f:
exec(f.read())
Jen's favorite language are: 
    Python
    Ruby

Sarah's favorite language is: 
    C

Edward's favorite language are: 
    Ruby
    Go

Phil's favorite language are: 
    Python
    Haskell
  • format(value, format_spec) 将 value 转换为 format_spec 控制的“格式化”表示。用法:'string{} string{}'.format(参数1,参数2) 
1
2
# 不设置指定位置,按默认顺序
"{} {}".format("hello", 'world')
'hello world'
1
2
# 设置指定位置
"{1} {0} {1} {0}".format("hello", "world")
'world hello world hello'
1
2
3
# 使用列表来存储需要格式化的数据
alist = ['Jack', 18]
print("My name is {}, I'm {} years old.".format(*alist))
My name is Jack, I'm 18 years old.
1
2
3
# 使用列表索引来进行格式化数据
alist = [18, 'Jack']
print("My name is {0[1]}, I'm {0[0]} years old.".format(alist)) # 0是必须的
My name is Jack, I'm 18 years old.
1
2
3
# 使用字典来存储需要格式化的数据
adict = {'name': 'Jack', 'age': 18}
print("My name is {name}, I'm {age} years old.".format(**adict))
My name is Jack, I'm 18 years old.
1
2
# 使用字典关键字来存储需要格式化的数据
print("My name is {name}, I'm {age} years old.".format(age=18, name ='Jack'))
My name is Jack, I'm 18 years old.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 数字格式化
from math import pi

# 保留小数点后两位
print("{:.2f}".format(pi))

# 带符号保留小数点后两位
print("{:.2f}".format(pi))

# 百分比格式
print("{:.2%}".format(pi))

# 指数记法
print("{:.2e}".format(pi*1000))
3.14
3.14
314.16%
3.14e+03
  • 在Python3.6中新引入一种字符串格式化方法,f-string,亦称为格式化字符串常量(formatted string literals)。主要目的是使格式化字符串的操作更加简便。f-string在本质上并不是字符串常量,而是一个在运行时运算求值的表达式。f-string在功能方面不逊于传统的%-formatting语句和str.format()函数,同时性能又优于二者,且使用起来也更加简洁明了,因此对于Python3.6及以后的版本,推荐使用f-string进行字符串格式化。
1
2
3
4
# 简单使用
name = 'Jack'
age = 18
print(f"My name is {name}, I'm {age} years old.")
My name is Jack, I'm 18 years old.
1
2
3
4
5
# 表达式求值与函数调用
# f-string的大括号 {} 可以填入表达式或调用函数,Python会求出其结果并填入返回的字符串内

print(f"My name is {name.upper()}.")
print(f"I'll be {age + 2} two years later.")
My name is JACK.
I'll be 20 two years later.
1
2
3
# f-string 使用字典
adict = {'name': 'Jack', 'age': 18}
print(f"My name is {adict['name']}, I'm {adict['age']} years old.")
My name is Jack, I'm 18 years old.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 数字格式化
from math import pi

# 保留小数点后两位
print(f"{pi:.2f}")

# 带符号保留小数点后两位
print(f"{pi:+.2f}")

# 百分比格式
print(f"{pi:.2%}")

# 指数记法
print(f"{pi*1000:.2e}")
3.14
+3.14
314.16%
3.14e+03