函数
一.创建和调用
1.定义
执行特定任务以完成特定功能的一段代码
优点:复用代码、隐藏实现细节、提高可维护性、提高可读性便于调试
2.创建
def 函数名(参数):
"""显示简单的问候语"""
函数内容
def calc(a,b):
c=a+b
return c
result=calc(20,30)
print(result)#50
3.实参(‘alice in wonderland’)、形参(bookname)
def favorite_book(bookname):
print("one of my favorite books is"+bookname.title()+"!")
favorite_book('alice in wonderland')
二.参数传递
1.位置实参
实参顺序与形参顺序相同
def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet('hamster', 'harry')#I have a hamster.
#My hamster's name is Harry.
2.关键字实参:指出给哪个形参即可
每个实参都由变量名和值组成,还可使用列表和字典
def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet(pet_name='harry',animal_type='hamster' )#I have a hamster.
#My hamster's name is Harry.
3.形参可以有默认值
def describe_pet(pet_name, animal_type='dog'):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet('willie')#I have a dog.
#My dog's name is Willie.
4.内存分析
def fun(arg1,arg2):
print('arg1',arg1)
print('arg2',arg2)
arg1=100
arg2.append(10)
print('arg1', arg1)
print('arg2', arg2)
n1=11
n2=[22,33,44]
print('n1', n1)#n1 11
print('n2', n2)#n2 [22, 33, 44]
fun(n1,n2)#实参名称可以跟形参名称不一致
#arg1 11
#arg2 [22, 33, 44]
#arg1 100
#arg2 [22, 33, 44, 10]
print('n1', n1)#n1 11
print('n2', n2)#n2 [22, 33, 10]
# 在函数的调用过程中进行参数传递
# 如果是不可变对象,在函数体的修改中不会影响实参的值 arg1的修改不会影响n1的值
# 如果是可变对象,在函数体的修改中会影响实参的值 arg2的修改不会影响n2的值
三.返回值:return
如果函数没有返回值,return可以省略不写
如果有一个返回值,返回原类型
如果有多个返回值,返回元组
1.实参可选
指定一个默认值——空字符串
def get_formatted_name(first_name, last_name, middle_name=''):
"""返回整洁的姓名"""
if middle_name:
full_name = first_name+' '+middle_name+' '+last_name
else:
full_name = first_name+' '+last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)#Jimi Hendrix
musician = get_formatted_name('john', 'hooker', 'lee')
print(musician)#John Lee Hooker
2.返回字典
def build_person(first_name, last_name, age=''):
"""返回一个字典,其中包含有关一个人的信息"""
person = {'first': first_name, 'last': last_name}
if age:
person['age'] = age
return person
musician = build_person('jimi', 'hendrix', age=27)
print(musician)#{'first': 'jimi', 'last': 'hendrix', 'age': 27}
3.返回元组
def fun1(num):
odd=[]
even=[]
for i in num:
if i%2:
odd.append(i)
else:
even.append(i)
return odd,even
print(fun1([10,29,34,23,44,53,55]))#([29, 23, 53, 55], [10, 34, 44])
四.传递列表
1.在函数中修改列表
pop 像弹出栈顶,永久修改
def print_models(unprinted_designs,completed_models):
"""
模拟打印每个设计,直到没有未打印的设计为止
打印每个设计后,都将其移到列表completed_models中
"""
while unprinted_designs:
current_design = unprinted_designs.pop()
#模拟根据设计制作3D打印模型的过程
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)
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
completed_models = []
print_models(unprinted_designs,completed_models)
show_completed_models(completed_models)
2.禁止函数修改列表
传副本 [:],要消耗时间和内存
print_models(unprinted_designs [:],completed_models)
五.参数定义
1.个数可变的位置参数 只能是一个
①定义函数时,无法实现确定位置实参的个数,使用可变的位置参数
②使用*定义个数可变的位置参数
③结果为一个元组
def fun2(*args):
print(args)
fun2(10)#(10,)
fun2(10,30,50)#(10, 30, 50)
2.个数可变的关键字形参 只能是一个
①定义函数时,无法实现确定关键字实参的个数,使用可变的关键字形参
②使用**定义个数可变的关键字形参
③结果为一个集合
def fun3(**args):
print(args)
fun3(a=10)#{'a': 10}
fun3(a=10,b=30,c=50)#{'a': 10, 'b': 30, 'c': 50}
3.既有1又有2,1放在2前可以
4.函数的参数总结
def fun4(a,b,c):
print(a)
print(b)
print(c)
#①
lst=[11,22,33]
fun4(*lst)#在函数调用时,将列表每个元素转换为位置实参
#②
dic={'a':111,'b':222,'c':333}
fun4(**dic)#在函数调用时,将字典中的键值对都转换为关键字实参
#③
def fun5(a,b,*,c,d):#c、d只能采用关键字实参传递
print(a,b,c,d)
fun5(10,20,d=30,c=40)
六.将函数存储在模块中:import
1.导入整个模块
pizza.py
def make_pizza(size, *toppings):
"""概述要制作的比萨"""
print("\nMaking a "+str(size)+
"-inch pizza with the following toppings:")
for topping in toppings:
print("- "+topping)
making_pizzas.py
使用:模块名.函数名
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
2.导入特定函数
from 模块名 import 函数名1,函数名2,函数名3(变量、类也可)
调用:函数名(实参)
3.导入所有函数
from 模块名 import *
调用:函数名(实参)
*不建议使用,很可能导入的函数与项目中的名称相同 *
4.使用as给函数指定别名
from 模块名 import 函数名 as 别名
调用:别名(实参)
5.使用as给模块指定别名
import 模块名 as 别名
调用:别名.函数名(实参)
类
一.创建类和使用类
class Dog():
"""一次模拟小狗的简单尝试"""
def __init__(self, name, age):
"""初始化属性name和age"""
self.name = name
self.age = age
def sit(self):
"""模拟小狗被命令时蹲下"""
print(self.name.title()+" is now sitting.")
def roll_over(self):
"""模拟小狗被命令时打滚"""
print(self.name.title()+" rolled over!")
1.class 类名():
注意:类名首字母大写;括号为空代表从空白创建这个类
2.init(self,形参1,形参2)
①类每创建一个新实例,python都会自动运行它
②Python调用这个__init__()方法来创建Dog实例时,将自动传入实参self。每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。每创建一个新实例,只需要给后两个形参提供值
③可通过实例访问的变量称为属性
3.创建实例
my_dog = Dog('willie', 6)
print("My dog's name is "+my_dog.name.title()+".")
print("My dog is "+str(my_dog.age)+" years old.")
my_dog.sit()
my_dog.roll_over()
二.使用类和实例
1.给属性指定默认值
在方法__init__内对某个属性指定初始值后,就无须提供形参
self.odometer_reading = 0
class Car():
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year)+' '+self.make+' '+self.model
return long_name.title()
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print("This car has "+str(self.odometer_reading)+" miles on it.")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
2.修改属性的值
①直接修改
my_new_car.odometer_reading=23
my_new_car.read_odometer()
②通过方法修改属性的值
class Car():
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year)+' '+self.make+' '+self.model
return long_name.title()
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print("This car has "+str(self.odometer_reading)+" miles on it.")
def update_odometer(self,mileage):
"""将里程表读数设置为特定的值"""
self.odometer_reading=mileage
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()
③通过方法对属性的值进行递增
class Car():
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year)+' '+self.make+' '+self.model
return long_name.title()
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print("This car has "+str(self.odometer_reading)+" miles on it.")
def update_odometer(self,mileage):
"""将里程表读数设置为特定的值"""
self.odometer_reading=mileage
def increment_odometer(self,miles)
"""将里程表读数增加指定的量"""
self.odometer_reading+=miles
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23500)
my_new_car.read_odometer()
my_new_car.increment_odometer(100)
my_new_car.read_odometer()
三.继承
另一个现成类的特殊版本。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。
1.子类方法__init__()
①定义子类必须在括号内指定父类名称
②super()函数将父类和子类关联起来
class Car():
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year)+' '+self.make+' '+self.model
return long_name.title()
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print("This car has "+str(self.odometer_reading)+" miles on it.")
def update_odometer(self,mileage):
"""将里程表读数设置为特定的值"""
self.odometer_reading=mileage
def increment_odometer(self,miles)
"""将里程表读数增加指定的量"""
self.odometer_reading+=miles
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
2.给子类定义属性和方法
class ElectricCar(Car):
"""
电动汽车的独特之处
初始化父类的属性,再初始化电动汽车特有的属性
"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
self.battery_size=70
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print("This car has a "+str(self.battery_size)+"-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
3.重写父类方法
在子类重写
4.将实例用做属性
分出来 class Battery():
实例 self.battery = Battery()
调用方法 my_tesla.battery.describe_battery()
class Car():
--snip--
class Battery():
"""一次模拟电动汽车电瓶的简单尝试"""
def __init__(self, battery_size=70):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print("This car has a "+str(self.battery_size)+"-kWh battery.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类的属性,再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
四.导入类
导入一个或多个类:from 文件名 import 类名1,类名2
导入整个模块:from 文件名
导入模块中的所有类:from 文件名 import * 不建议用
五.python标准库
创建字典并记录其中的键—值对的添加顺序,可使用模块collections中的OrderedDict类
六.类编码风格
类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
对于每个类,都应紧跟在类定义后面包含一个文档字符串
文件和异常
一.从文件读取数据
1.读整个文件
①函数open()返回一个表示文件的对象,Python将这个对象存储在我们将在后面使用的变量中。
②关键字with在不再需要访问文件后将其关闭
with语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件正确的关闭,以此来达到释放资源的目的
③使用read()方法读取文件的全部内容
④read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。要删除末尾的空行,可在print语句中使用rstrip()
⑤变量filename表示的并非实际文件——它只是一个让Python知道到哪里去查找文件的字符串
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents.rstrip())
2.文件路径
①找相对路径 √
比如:文本文件(.txt)在程序文件(.py)的下一级
with open('text_files\filename.txt') as file_object:
②找绝对路径
file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:
3.逐行读取
每行的末尾都有一个看不见的换行符,而print语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一个来自print语句。要消除这些多余的空白行,可在print语句中使用rstrip()
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())
4.创建一个包含文件各行内容的列表
方法readlines()从文件中读取每一行,并将其存储在一个列表中;接下来,该列表被存储到变量lines中;在with代码块外,我们依然可以使用这个变量
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
5.使用文件的内容
获得圆周率的字符串
filename = 'pi_30_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string+= line.strip()
print(pi_string)
print(len(pi_string))
6.包含一百万为的大型文件
打印到小数点后50位
filename = 'pi_million_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string+= line.strip()
print(pi_string[:52]+"...")
print(len(pi_string))
二.写入文件
1.写入空文件
open(文件名,'w)
w:以写入模式打开这个文件 创建刷新
r: 以读取模式打开这个文件 默认
a:以附加模式打开这个文件 创建追加
b:以二进制方式打开文件,不能单独使用,可以rb,wb
r+:以读取和写入模式打开这个文件
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
这个程序没有终端输出
注:Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式
2.写入多行
函数write()不会在你写入的文本末尾添加换行符,所以每一个字符串末尾加\n
3.附加到文件
filename = 'programming.txt'
with open(filename, 'a') as file_object:
file_object.write("I also love finding meaning in large datasets.\n")
file_object.write("I love creating apps that can run in a browser.\n")
三.异常
异常:是一个特殊对象,来管理程序执行期间发生的错误
1.处理ZeroDivisionError异常
异常是使用try-except-else代码块处理的。try-except-else代码块的工作原理大致如下:Python尝试执行try代码块中的代码;只有可能引发异常的代码才需要放在try语句中。有时候,有一些仅在try代码块成功执行时才需要运行的代码;这些代码应放在else代码块中。except代码块告诉Python,如果它尝试运行try代码块中的代码时引发了指定的异常,该怎么办。
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
try: ❶
answer = int(first_number) / int(second_number)
except ZeroDivisionError: ❷
print("You can't divide by 0!")
else: ❸
print(answer)
2.处理FileNotFoundError异常
方法split()以空格为分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中
filename = 'alice.txt'
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "Sorry, the file "+filename+" does not exist."
print(msg)
else:
# 计算文件大致包含多少个单词
words = contents.split() ❶
num_words = len(words) ❷
print("The file "+filename+" has about "+str(num_words)+" words.")
如果希望发生FileNotFoundError异常时一声不吭:
pass语句还充当了占位符,它提醒你在程序的某个地方什么都没有做,并且以后也许要在这里做些什么
except FileNotFoundError:
pass
四.存储数据
用模块json来存储
补:JSON(JavaScript Object Notation)格式最初是为JavaScript开发的,但随后成了一种常见格式,被包括Python在内的众多语言采用
1.json.dump()存储 json.load()读取
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'
with open(filename, 'w') as f_obj:
json.dump(numbers, f_obj)
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
2.保存和读取用户生成的数据
remember_me.py
import json
# 如果以前存储了用户名,就加载它
# 否则,就提示用户输入用户名并存储它
filename = 'username.json'
try:
with open(filename) as f_obj: ❶
username = json.load(f_obj) ❷
except FileNotFoundError: ❸
username = input("What is your name? ") ❹
with open(filename, 'w') as f_obj: ❺
json.dump(username, f_obj)
print("We'll remember you when you come back, "+username+"!")
else:
print("Welcome back, "+username+"!")