栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python基础

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python基础

目录

列表

定义列表

访问列表元素

修改列表元素

添加元素(在列表末尾)

插入元素

删除元素

列表排序

操作列表

遍历整个列表

创建数值列表

列表解析

切片

遍历切片

复制列表

元组

定义元组

遍历元组所有的值

修改元组变量

if语句

字典

访问字典

添加键值对

修改字典中的值

删除字典中的值

由类似对象组成的字典 

使用get()来访问值

遍历字典

遍历所有键值对

遍历字典中的所有键

按特定顺序遍历字典中的所有键

遍历字典中的所有值

嵌套

字典列表

在字典中存储列表

在字典中存储字典

input()函数

使用int()来获取数值输入

while循环

使用标志

使用while循环处理列表和字典

在列表之间移动元素 

删除为特定值的所有列表元素

使用用户输入来填充字典

 函数

定义函数

向函数传递信息

传递实参 

位置实参

关键字实参

 默认值

返回值

返回简单值

让实参变成可选的

返回字典

传递列表

在函数中修改列表

禁止函数修改列表

传递任意数量的实参

结合使用位置实参和任意数量实参

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

将函数存储在模块中

导入整个模块

导入特定的函数

使用as给函数指定别名

使用as给模块指定别名

导入模块中的所有函数

创建和使用类

创建Dog类

根据类创建实例

 使用类和实例

Car类

 给属性指定默认值

修改属性的值

 继承

子类的方法__init__()

给子类定义属性和方法

重写父类的方法

将实例用作属性

导入类

导入单个类

在一个模块中存储多个类 

从一个模块中导入多个类

导入整个模块

 导入模块中的所有类

在一个模块中导入另一个模块

使用别名

Python标准库

文件和异常

从文件中读取数据

读取整个文件

文件路径

逐行读取

创建一个包含文件各行内容的列表

使用文件的内容

写入文件

写入空文件

写入多行

附加到文件

异常

处理ZeroDivisionError异常 

使用try-except代码块

使用异常避免崩溃

 try-except-else代码块

处理FileNotFoundError异常

分析文本

使用多个文件

静默失败

存储数据

使用json.dump()和json.load()

保存和读取用户生成的数据

重构


列表

list=[a,b,c,d]

定义列表

访问列表元素
friuts=["apple","branana","pear"]
print(friuts[1])

修改列表元素

指定列表名和要修改的元素的索引,再指定该元素的新值。

names=["小红","小紫","小明","小蓝"]
print(names)
names[1]="小花"
print(names)

添加元素(在列表末尾)

使用append()方法

names=["小红","小紫","小明","小蓝"]
names.append("小西")
print(names)

插入元素

使用方法insert(),需要指定新元素的索引和值。

names=["小红","小紫","小明","小蓝"]
names.insert(1,"小亮")
print(names)

删除元素

知道删除的元素在列表中的位置,可使用del语句

names=["小红","小紫","小明","小蓝"]
del names[3]
print(names)

方法pop()删除列表任何位置的元素,并让你能够接着使用它。

names=["小红","小紫","小明","小蓝"]
names_pop=names.pop(2)
print(names)
print(names_pop)

区别:

如果你要从列表中删除一个元素,且不再以任何方式使用它,就使用del语句;如果你要在删除元素后还能继续使用它,就使用方法pop()。

根据值删除元素

你不知道要从列表中删除的值所处的位置。如果只知道要删除的元素的值,可使用方法remove()。

列表排序

方法sort()对列表永久排序(再也无法恢复到原来的排列顺序)

cars=["bmw","audi","toyota","subaru"]
cars.sort()
print(cars)

与字母顺序相反的顺序排列列表元素,只需向sort()方法传递参数reverse=True即可

cars=["bmw","audi","toyota","subaru"]
cars.sort(reverse=True)
print(cars)

使用函数sorted()对列表临时排序(列表元素的排列顺序并没有变)

cars=["bmw","audi","toyota","subaru"]
print(sorted(cars))
print(cars)

倒着打印列表

reverse()不是按与字母顺序相反的顺序排列列表元素,而只是反转列表元素的排列顺序

cars=["bmw","audi","toyota","subaru"]
cars.reverse()
print(cars)

方法reverse()永久性地修改列表元素的排列顺序,但可随时恢复到原来的排列顺序,只需对列表再次调用reverse()即可。

确定列表的长度:使用函数len()
cars=["bmw","audi","toyota","subaru"]
print(len(cars))

使用列表时要避免索引错误

操作列表

遍历整个列表

for  变量  in  列表名[] : 

要注意正确使用缩进

创建数值列表

range()函数

用于生成一个整数序列

如可以像下面这样使用函数range()来打印一系列数:

for value in range(1,5):
    print(value)

range(1,5)的输出从1开始、到4结束   包左不包右

调用函数range()时,也可只指定一个参数,这样它将从0开始。例如,range(6)返回数0~5。

也可以指定三个参数,如range(1,8,2) 指步长为2,返回数1,3,5,7

使用range()创建数字列表

使用函数list()将range()的结果直接转换为列表,如果将range()作为list()的参数,输出将是一个数字列表。

number=list(range(1,6))
print(number)

输出:[1, 2, 3, 4, 5]

列表解析

例题:创建一个列表,该列表包含前10个整数(1~10)的平方

squares=[]
for i in range(1,11):
    squares.append(i**2)
print(squares)

而为了使代码更简洁,做列表解析如下:

squares=[i**2 for i in range(1,11)]
print(squares)

格式:列表名=[表达式 for循环]     注:表达式是指用于生成要存储到列表中的值

切片

指定输出的索引位置 

cars=["bmw","audi","toyota","subaru"]
print(cars[1:3])  #输出索引1,2位置的元素
print(cars[:2])  #输出索引2之前(不包括2)位置的元素
print(cars[1:])  #输出索引1之后(包括1和最后)位置的元素
print(cars[0:3:2])  #第三个参数指步长,输出索引0,2位置的元素
print(cars[:])  #输出所有元素

遍历切片

遍历列表的部分元素,可在for循环中使用切片。

cars=["bmw","audi","toyota","subaru"]
for i in cars[0:2]:
    print(i)

复制列表

创建一个包含整个列表的切片,方法是同时省略起始索引和终止索引([:])

my_cars=["bmw","audi","toyota","subaru"]
friend_cars=my_cars[:]  #正确,即把my_cars的副本赋值给friend_cars
friend_cars=my_cars   #错误,必须使用切片复制列表
print(friend_cars)

元组

不可变的列表被称为元组

定义元组

和列表一样,只是使用圆括号而不是中括号标识。

如dimensions=(20,50)

因为元组是不可以修改的,所以不可被重新赋值

注:严格地说,元组是由逗号标识的,圆括号只是让元组看起来更整洁、更清晰。如果你要定义只包含一个元素的元组,必须在这个元素后面加上逗号,如: my_t=(3,)

遍历元组所有的值

同列表一样,使用for循环进行遍历

修改元组变量

虽然不能修改元组的元素,但可以给存储元组的变量赋值。即重新定义整个元组

if语句
  • if-else结构
  • if-elif结构
  • if-elif-else结构
  • if-elif-elif----结构
  • if-if-if---结构

如果只想执行一个代码块,就使用if-elif-else结构;如果要执行多个代码块,就使用一系列独立的if语句。

字典

字典是一系列键值对,每个键都与一个值相关联,你可使用键来访问相关联的值。与键相关联的值可以是数、字符串、列表乃至字典。

alien_0={'color':'green','point':7}

访问字典

 要获取与键相关联的值,可依次指定字典名和放在方括号内的键,如下所示:

alien_0={'color':'green','point':7}

print(alien_0['color'])

添加键值对

字典是一种动态结构,可随时在其中添加键值对。要添加键值对,可依次指定字典名、用方括号括起的键和相关联的值。

 alien_0['x_position']=10

alien_0['y_position']=20

先创建一个空字典,然后依次添加键值对

person={}
person['name']='小红'
person['age']=12
person['sex']='女'
person['address']='山东'
print(person)

修改字典中的值

依次指定字典名、用方括号括起的键,以及与该键相关联的新值。

person['age']=20

删除字典中的值

使用del语句将相应的键值对彻底删除。使用del语句时,必须指定字典名和要删除的键。

del person['sex']

由类似对象组成的字典 

使用字典来存储众多对象的同一种信息

标准格式:

favorite_languages = {
    'jen':'python',  #前面空四格,后面加逗号
    'sarah':'c',
    'ben':'java',
    'john':'c++',
    }
language = favorite_languages['jen'].title()
print(f"jen's favorite language is {language}")

使用get()来访问值

在指定的键不存在时返回一个默认值,从而避免出现键值的错误。

方法get()的第一个参数用于指定键,是必不可少的;第二个参数为指定的键不存在时要返回的值,是可选的,若不指定且指定的键不存在,将返回值None(表示所需值不存在的特殊值)。

alien_0={'color':'green','x_position':10,'y_position':20}
point_value=alien_0.get('point','no point value assigned')
print(point_value)

如果字典中有键'points',将获得与之相关联的值;如果没有,将获得指定的默认值。

如果指定的键有可能不存在,应考虑使用方法get(),而不要使用方括号表示法。

遍历字典

字典可用于以各种方式存储信息,因此可遍历字典的所有键值对,也可仅遍历键或值

遍历所有键值对

for循环:for 变量1,变量2   in   字典名.items():    //item()方法返回一个键值对列表。

user = {
    'username' : 'eferfi',
    'first_name' : 'enrico',
    'last_name' : 'fermi',
}
for key,value in user.items():
    print(f"nKey:{key}")
    print(f"Value:{value}")

若遍历的是由类似对象组成的字典,则两个变量名最好根据代码内容设置

遍历字典中的所有键

在不需要使用字典中的值时,使用keys()方法可得到所有键。

favorite_languages = {
    'jen':'python', 
    'sarah':'c',
    'ben':'java',
    'john':'c++',
    }
for name in favorite_languages.keys():
    print(f"调查了{name}喜欢的语言")

遍历字典时,会默认遍历所有的键。即省略key()方法和使用key()方法输出结果一样

按特定顺序遍历字典中的所有键

在for循环中对返回的键进行排序,可使用函数sorted()来获得按特定顺序排列的键列表的副本:

for name in sorted(favorite_languages.keys()):

遍历字典中的所有值

使用values()方法来返回一个值列表

for name in favorite_languages.values():

 这种做法提取字典中所有的值,而没有考虑是否重复。为剔除重复项,可以对包含重复元素的列表调用set(),因为集合中的每个元素都必须是独一无二的

for name in set(favorite_languages.values()):

注:可使用一对花括号直接创建集合,并在其中用逗号分隔元素。

languages = {'python','c','c++','c#','java'}

 集合和字典很容易混淆,因为它们都是用一对花括号定义的。当花括号内没有键值对时,定义的很可能是集合。不同于列表和字典,集合不会以特定的顺序存储元素。

嵌套

将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套。可以在列表中嵌套字典、在字典中嵌套列表甚至在字典中嵌套字典。

字典列表

创建n个字典,把n个字典放入一个列表中

alien_0={'color':'green','point':10}
alien_1={'color':'red','point':8}
alien_2={'color':'yellow','point':7}
aliens = [alien_0,alien_1,alien_2]
for alien in aliens:
    print(alien)

在字典中存储列表

创建一个字典,时的字典中的键所对的值关联列表

favorite_languages = {
    'jen':['python','java'],
    'sarah':['c','python'],
    'ben':['java','R'],
    }

 遍历:

favorite_languages = {
    'jen':['python','java'],  #前面空四格,后面加逗号
    'sarah':['c','python'],
    'ben':['java','R'],
    'john':['c#'],
    }
for name,languages in favorite_languages.items():
    if len(languages) > 1:
        print(f"{name}'s favorite languages are")
        for language in languages:
            print(language)
    else:
        print(f"{name}'s favorite language is {languages}.")

在字典中存储字典
users = {
    'aeinstein':{
        'first':'albert',
        'last':'einstein',
        'location':'princeton'
        },
    'mcurie':{
        'first':'marie',
        'last':'curie',
        'location':'paris',
        },
    }

input()函数

让程序暂停运行,等待用户输入一些文本。获取用户输入后,Python将其赋给一个变量后使用。

函数input()需要接受一个参数——要向用户显示的提示或说明,让用户知道该如何做。

number = input('请输入一个整数:')

使用int()来获取数值输入

使用函数input()时,Python将用户输入解读为字符串。

age = int(input(How old are you ?)) 

while循环

for循环用于针对集合中的每个元素都执行一个代码块,而while循环则不断运行,直到指定的条件不满足为止。 

选择结构if语句和循环结构while语句的区别:

  • if是判断一次,条件为true执行一行
  • while是判断n+1次,条件为true执行n次

可使用while循环来数数:

current_number = 1
while current_number <= 5:
    print(current_number)
    current_number+=1

4步循环法:

  1. 初始化变量
  2. 条件判断
  3. 条件执行体(循环体)
  4. 改变变量 
  • 初始化的变量和条件判断的变量和改变的变量是同一个 

break语句:立即退出while循环,不再运行循环中余下的代码,也不管条件测试的结果如何

continue语句:返回循环开头,并根据条件测试结果决定是否继续执行循环

使用标志

在要求很多条件都满足才继续运行的程序中,可定义一个变量,用于判断整个程序是否处于活动状态。这个变量称为标志(flag),充当程序的交通信号灯。可以让程序在标志为True时继续运行,并在任何事件导致标志的值为False时让程序停止运行。这样,在while语句中就只需检查一个条件:标志的当前值是否为True。然后将所有其他测试(都放在其他地方,从而让程序更整洁。

使用while循环处理列表和字典

for循环是一种遍历列表的有效方式,但不应在for循环中修改列表,否则将导致Python难以跟踪其中的元素。在遍历列表的同时对其进行修改,可使用while循环。

在列表之间移动元素 

将元素从一个列表移动到另一个列表中

例题:假设有一个列表包含新注册但还未验证的网站用户。验证这些用户后,如何将他们移到另一个已验证用户列表中呢? 

un/confirm/ied_users = ['jhon','sarah','tom']  #待验证的用户列表
/confirm/ied_users = []  #完成验证的用户列表
while un/confirm/ied_users:  #验证每个待验证的用户,直到全部验证为止
    current_user = un/confirm/ied_users.pop()
    print(f"Verifying user:{current_user}")
    /confirm/ied_users.append(current_user)   #将每个经过验证的用户移到完成验证的用户列表

print('n the following users are /confirm/ied:')  #显示所有已验证的用户
for /confirm/ied_user in /confirm/ied_users:
    print(/confirm/ied_user)

删除为特定值的所有列表元素

while 'cat' in pets:

    pets.remove('cat')

使用用户输入来填充字典

可使用while循环提示用户输入任意多的信息。

例题:创建一个调查程序,其中的循环每次执行时都提示输入被调查者的名字和回答。我们将收集的数据存储在一个字典中,以便将回答同被调查者关联起来。

responses = {}
polling_active = True  #设置一个标志,指出调查是否继续
#提示输入被调查者的名字和回答
while polling_active:
    name = input("n What's your name?n")
    response = input("Which mountains would you like to climb someday?n")
    responses[name] = response  #将回答存储在字典中
#看看是否还有人要参与调查
    repeat = input("Would you like to let another person respond? (yes/no)n")
    if repeat == 'no':
        polling_active = False
#调查结束,显示结果
        print("----Poll Result----")
        for name,response in responses.items():
            print(f"{name} would like to climb {response}")

 函数

定义函数

def 函数名:

    函数体

调用函数

向函数传递信息

即为函数添加参数

def 函数名(形参):

函数体

调用函数(实参)

传递实参 

函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。

位置实参

要求实参的顺序与形参的顺序相同

例题:指出一个宠物属于哪种动物以及它叫什么名字

#函数定义
def describe_pet(animal_type,pet_name):
    print(f"I have a {animal_type}.")
    print((f"My {animal_type}'s name is {pet_name}."))
#函数调用
describe_pet("hamster","harry")

多次调用函数:再次调用describe_pet()即可

describe_pet("hamster","harry")
describe_pet("dog","willie")

关键字实参

传递给函数的名称值对,直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆,无须考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。

如上述例题,可改为:

#函数定义
def describe_pet(animal_type,pet_name):
    print(f"I have a {animal_type}.")
    print((f"My {animal_type}'s name is {pet_name}."))
#函数调用
describe_pet(animal_type="hamster",pet_name="harry")
describe_pet(pet_name="willie",animal_type="dog")

 默认值

编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。

如上述例题,可改为:

# 函数定义
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}.")

# 函数调用
describe_pet("harry")
describe_pet("willie")

注意:在这个函数的定义中,修改了形参的排列顺序。使用默认值时,必须先在形参列表中列出没有默认值的形参,再列出有默认值的实参。这让Python依然能够正确地解读位置实参。

返回值

使用return语句将值返回到调用函数的代码行。返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。

返回简单值

调用返回值的函数时,需要提供一个变量,以便将返回的值赋给它。

def get_formatted_name(first_name, last_name):
    full_name = f"{first_name.title()} {last_name.title()}"
    return full_name


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

让实参变成可选的

可使用默认值来让实参变成可选的,形参=‘ ’(形参设置成一个空字符串)注意要把此参数放在最后。

返回字典
def build_person(first_name, last_name, age=None):
    person = {'first': first_name, 'last': last_name}
    if age:
        person['age'] = age
    return person


musician = build_person('jimi', 'hendrix', 18)
print(musician)

传递列表

例题:假设有一个用户列表,我们要问候其中的每位用户。

def greet_users(names):
    for name in names:
        msg = f"Hello,{name}"
        print(msg)
user_names = ('1', '2', '3')
greet_users(user_names)

在函数中修改列表

可以定义函数,将一个列表中的内容移到另一个列表

例题:需要打印东西,打印的设计存储在一个列表中,打印后将移到另一个列表中。

def print_list(unprint, completed):
    while unprint:
        current_print = unprint.pop()
        print(f"当前在打印的是{current_print}")
        completed.append(current_print)
    print(f"已经完成打印的是{completed}")


unprint_list = ['q', 'w', 'e', 'r']
completed_list=[]
print_list(unprint_list,completed_list)

禁止函数修改列表

为了不让第一个列表因为移到另一个列表而变空,可向函数传递列表的副本而非原件。这样,函数所做的任何修改都只影响副本,而原件丝毫不受影响。

将列表的副本传递给函数:function_name(list_name_[:])

上述例题调用函数部分可改为:

print_list(unprint_list[:],completed_list)

即切片表示法[:]创建列表的副本 

虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由,否则还是应该将原始列表传递给函数。这是因为让函数使用现成的列表可避免花时间和内存创建副本,从而提高效率。

传递任意数量的实参

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

例题:制作一个披萨,它需要接受很多配料,但无法预先确定顾客要多少种配料。

def make_pizza(*toppings):
    #概述顾客点的所有配料
    print(f"making a pizza with following toppings:")
    for topping in toppings:
        print(topping)
make_pizza('pepperoni')
make_pizza('mushrooms','green peppers','extra cheese')

形参名*toppings中的星号让Python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中。

结合使用位置实参和任意数量实参

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

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

能够接受任意数量的键值对——调用语句提供了多少就接受多少。

例题:创建用户简介,你知道将收到有关用户的信息,但不确定会是什么样的信息。

def build_profile(first, last, **user_info):
    '''创建一个字典,其中包括我们知道的用户的一切'''
    user_info['first_name'] = first
    user_info['last_name'] = last
    return user_info

user_profile = build_profile('Danni', 'zhou', city='Beijing', age=19)
print(user_profile)

将函数存储在模块中

将函数存储在称为模块的独立文件中,再将模块导入到主程序中,可隐藏程序代码的细节。import语句允许在当前运行的程序文件中使用模块中的代码。

将函数存储在独立文件中后,可与其他程序员共享这些文件而不是整个程序。知道如何导入函数还能让你使用其他程序员编写的函数库。

导入整个模块

要让函数是可导入的,得先创建模块。模块是扩展名为.py的文件,包含要导入到程序中的代码。

例题:制作披萨,顾客选择配料

首先创建只包含函数make_pizza()的模块

  • pizza.py
def make_pizza(*toppings):
    # 概述顾客点的所有配料
    print(f"making a pizza with following toppings:")
    for topping in toppings:
        print(topping)

接下来,在pizza.py所在的目录中创建一个名为making_pizzas.py的文件。这个文件导入刚创建的模块,再调用使用句点表示法make_pizza()即可。

  • making_pizzas.py
import pizza
pizza.make_pizza('pepperoni')
pizza.make_pizza('mushrooms', 'green peppers', 'extra cheese')

这些代码的输出与没有导入模块的原始程序相同。 

导入方法:只需编写一条import语句并在其中指定模块名,就可在程序中使用该模块中的所有函数。

导入特定的函数

还可以导入模块中的特定函数,这种导入方法的语法如下:

from module_name import function_name

通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数:

 from module_name import function_0,function_1,function_2

对于前面的making_pizzas.py示例,如果只想导入要使用的函数,代码将类似于下面这样:

from pizza import make_pizza
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

使用这种语法时,调用函数时无须使用句点。由于在import语句中显式地导入了函数make_pizza(),调用时只需指定其名称即可。

使用as给函数指定别名

即给函数起别名:函数的另一个名称,类似于外号。要给函数取这种特殊外号,需要在导入它时指定。

from pizza import make_pizza as mp
mp('pepperoni')
mp('mushrooms', 'green peppers', 'extra cheese')

使用as给模块指定别名

import pizza as p
p.make_pizza('pepperoni')
p.make_pizza('mushrooms', 'green peppers', 'extra cheese')

导入模块中的所有函数

使用星号(*)运算符可让Python导入模块中的所有函数:

from pizza import  *
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

 由于导入了每个函数,可通过名称来调用每个函数,而无须使用句点表示法。

然而,使用并非自己编写的大型模块时,最好不要采用这种导入方法。最佳的做法是,要么只导入需要使用的函数,要么导入整个模块并使用句点表示法。这让代码更清晰,更容易阅读和理解。、

创建和使用类

创建Dog类
class Dog:    #定义一个名为Dog的类
    """一次模拟小狗的简单尝试"""

    def __init__(self, name, age):
        """初始化属性name和age。"""
        self.name = name
        self.age = age

    def sit(self):
        """模拟小狗收到命令时蹲下。"""
        print(f"{self.name} is now sitting.")

    def roll_over(self):
        """模拟小狗收到命令时打滚。"""
        print(f"{self.name} is now roll over.")

在Python中,首字母大写的名称指的是类。

方法__init__()

类中的函数称为方法。前面所学的函数的一切都适用于方法,就目前而言,唯一的区别是调用方法的方式。该方法开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。

该方法的形参中,self形参必不可少,而且必须位于其他形参的前面。因为Python调用这个方法来创建Dog实例时,将自动传入实参self。每个与实例相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。且在创建实例时,self会自动传递。

以self为前缀的变量可供类中的所有方法使用,可以通过类的任何实例来访问。

根据类创建实例

创建一个表示特定小狗的实例:

class Dog:
    my_dog = Dog('doudou',3)
    print(f"my dog's name is {my_dog.name}")
    print(f"my dog's age is {my_dog.age}")

命名约定:通常可认为首字母大写的名称(如Dog)指的是类,而小写的名称(如my_dog)指的是根据类创建的实例。

访问属性

使用句点表示法:my_dog.name

访问方法

可以使用句点表示法来调用Dog类中定义的任何方法,如让小狗蹲下和打滚:

my_dog.sit()
my_dog.roll_over()

创建多个实例 

可按需求根据类创建任意数量的实例。下面再创建一个名为your_dog的小狗实例:

class Dog:
    my_dog = Dog('doudou',3)
    your_dog = Dog('Lucy',2)
    print(f"my dog's name is {my_dog.name}")
    print(f"my dog's age is {my_dog.age}")
    my_dog.sit()
    my_dog.roll_over()
    print(f"your dog's name is {your_dog.name}")
    print(f"your dog's age is {your_dog.age}")
    your_dog.sit()
    your_dog.roll_over()

 使用类和实例

Car类

编写一个表示汽车的类。它存储了有关汽车的信息,还有一个汇总这些信息的方法:

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_describe_car(self):
        long_time = f"{self.make} {self.model} {self.year}"
        return long_time

    def read_odometer(self):
        print(f"this car has {self.odometer_reading} miles on it.")


my_car = Car('audi', 'a6', 2019)
print(my_car.get_describe_car())
my_car.read_odometer()

 给属性指定默认值

创建实例时,有些属性无须通过形参来定义,可在方法__init__()中为其指定默认值。

例如:添加一个名为odometer_reading的属性,其初始值总是为0

self_odometer_reading = 0

修改属性的值

1.直接修改属性的值

 例如:使用句点表示法直接访问并修改odometer_reading的属性值,直接设置为23

my_car.odometer_reading = 23

2.通过方法修改属性的值

如果有方法能替你更新属性,这样就无须直接访问属性,而可将值传递给方法,由它在内部进行更新。

def update_odometer(self,mileage):
    self.odometer_reading = mileage
my_car.update_odometer(23)

3.通过方法对属性的值进行递增

有时候需要将属性值递增特定的量,而不是将其设置为全新的值。下面的方法让我们能够传递这个增量,并相应地增大里程表读数:

def increment_odometer(self,miles):
    self.odometer_reading += miles
my_car.increment_odometer(20)

 继承

如果要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。

子类的方法__init__()

在既有类的基础上编写新类时,通常要调用父类的方法__init__()。这将初始化在父类__init__()方法中定义的所有属性,从而让子类包含这些属性。

例如,下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此可在前面创建的Car类的基础上创建新类ElectricCar。这样就只需为电动汽车特有的属性和行为编写代码。

class Car:
    '''一次模拟汽车的简单尝试'''

    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_describe_car(self):
        long_time = f"{self.make} {self.model} {self.year}"
        return long_time

    def read_odometer(self):
        print(f"this car has {self.odometer_reading} miles on it.")

    def update_odometer(self, mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")

    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('China', 'aima', 2020)
print(my_tesla.get_describe_car())

父类必须包含在当前文件中,且位于子类前面。定义子类时,必须在圆括号内指定父类的名称。方法__init__()接受创建Car实例所需的信息,使用super()函数调用父类的方法__init__()。

给子类定义属性和方法

让一个类继承另一个类后,就可以添加区分子类和父类所需的新属性和新方法了。

下面来添加一个电动汽车特有的属性(电瓶),以及一个描述该属性的方法。我们将存储电瓶容量,并编写一个打印电瓶描述的方法: 

class Car:

   ---snip---

class ElectricCar(Car):
    """电动汽车的独特之处"""

    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year)
        self.battery_size = 0

    def describe_battery(self,new_battery_size):
        """打印一条描述电瓶容量的信息"""
        self.battery_size = new_battery_size
        print(f"this car has {self.battery_size} KWh battery.")


my_tesla = ElectricCar('China', 'aima', 2020)
print(my_tesla.get_describe_car())
my_tesla.describe_battery(30)

在方法添加新属性self.battery_size并设置其初始值;接着添加一个名为describe_battery()的方法,打印有关电瓶的信息。

重写父类的方法

对于父类的方法,只要它不符合子类模拟的实物的行为,都可以进行重写。为此,可在子类中定义一个与要重写的父类方法同名的方法。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

假设Car类有一个名为fill_gas_tank()的方法,它对全电动汽车来说毫无意义,因此你可能想重写它。下面演示了一种重写方式:

class ElectricCar(Car):
    ---snip---

    def fill_gas_tank(self):
        '''电动车没有油箱'''
        print("this car doesn't need a gas tank!")

现在如果有人对电动汽车调用方法fill_gas_tank(),Python将忽略Car类中的方法fill_gas_tank(),转而运行上述代码。

将实例用作属性

将类的一部分提取出来,作为一个独立的类。可以将大型类拆分成多个协同工作的小类。

例如,不断给ElectricCar类添加细节时,我们可能发现其中包含很多专门针对汽车电瓶的属性和方法。在这种情况下,可将这些属性和方法提取出来,放到一个名为Battery的类中,并将一个Battery实例作为ElectricCar类的属性:

class Car:
   ---snip---

class Battery:
    """一次模拟电动汽车电瓶的简单尝试"""

    def __init__(self, battery_size=75):
        self.battery_size = battery_size

    def describe_battery(self):

        print(f"this car has {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('China', 'aima', 2020)
print(my_tesla.get_describe_car())
my_tesla.battery.describe_battery()  #这行代码让Python在实例my_tesla中查找属性battery,
并对存储在该属性中的Battery实例调用方法describe_battery()。

导入类

将类存储在模块中,然后在主程序中导入所需的模块。

导入单个类

from car import Car 

即import语句让Python打开模块car并导入其中的Car类。

在一个模块中存储多个类 

可根据需要在一个模块中存储任意数量的类

只导入子类就可以了

从一个模块中导入多个类

从一个模块中导入多个类时,用逗号分隔了各个类。导入必要的类后,就可根据需要创建每个类的任意数量实例。

导入整个模块

导入整个模块,再使用句点表示法访问需要的类。直接导入模块名

import car

my_car = car.Car('aima','diandong',2020)

 导入模块中的所有类

from model_name import *

不推荐使用这种导入方式,因为没有明确地指出使用了模块中的哪些类,并且可能会有类名冲突,最好的方式是导入整个模块。

在一个模块中导入另一个模块

可以分别从每个模块中导入类,即相当于在一个模块中导入单个类

使用别名

使用as,和函数起别名用法一样。 

Python标准库

如模块random,在这个模块中,一个有趣的函数是randint()。它将两个整数作为参数,并随机返回一个位于这两个整数之间(含)的整数。

from random import randint

randint(1,6)

文件和异常

从文件中读取数据

每当需要分析或修改存储在文件中的信息时,读取文件都很有用。要使用文本文件中的信息,首先需要将信息读取到内存中。为此,你可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。 

读取整个文件

要读取文件,需要一个包含几行文本的文件。首先创建一个包含精确到小数点后30位的圆周率值,且在小数点后每10位处换行的pi-30wei.txt,该文件要放在本程序所在的目录。

下面的程序打开并读取这个文件,再将其内容显示到屏幕上:

with open('pi-30wei.txt') as file_object:
    contents = file_object.read()
    print(contents)

要以任何方式使用文件,哪怕仅仅是打印文件的内容,都首先需要打开文件,才能访问它。

函数open()接受一个参数:要打开的文件的名称。Python在当前执行的文件所在的目录中查找指定的文件。它返回一个表示文件的对象,表示文件及其内容的对象赋给了变量file_object。

关键字with负责打开和关闭文件,但在此处未调用close()方法,因为容易出错。Python自会在合适的时候自动将其关闭。

方法read()读取这个文件的全部内容,并将其作为一个长长的字符串赋给变量contents。这样,通过打印contents的值,就可将这个文本文件的全部内容显示出来。

read()到达文件末尾时返回一个空字符串,显示出来时就是一个空行。在函数调用print()中使用rstrip()删除字符串末尾的空白:

print(content.rstrip()) 

文件路径

要让Python打开不与程序文件位于同一个目录中的文件,需要提供文件路径,让Python到系统的特定位置去查找。 

  • 使用相对路径:到文件夹python_work下的文件夹text_files中去查找指定的.txt文件。

with open('text_files/filename.txt') as file_objict:

  • 使用绝对路径:需要完整的文件路径,可读取系统中任何地方的文件。

绝对路径通常比相对路径长,因此将其赋给一个变量,再将该变量传递给open()会有所帮助: 

file_path = '/home/other_files/text_files/_filename_.txt'

with open(file_path) as file_object:

读取文件一般要么将数据文件存储在程序文件所在的目录,要么将其存储在程序文件所在目录下的一个文件夹(如text_files)中,即尽可能少的使用绝对路径。

逐行读取

读取文件时,常常需要检查其中的每一行:可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。

要以每次一行的方式检查文件,可对文件对象使用for循环: (遍历文件对象)

filename = 'pi-30wei.txt'
with open(filename) as file_object:
for line in file_object:
    print(line.rstrip())

创建一个包含文件各行内容的列表

使用关键字with时,open()返回的文件对象只在with代码块内可用。如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表:可以立即处理文件的各个部分,也可以推迟到程序后面再处理。

下面的示例在with代码块中将文件pi-30wei.txt的各行存储在一个列表中,再在with代码块外打印:

filenme = 'pi-30wei.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
for line in lines:
    print(line.rstrip())

 方法readlines()从文件中读取每一行,并将其存储在一个列表中。

使用文件的内容

例如,使用圆周率的值

filename = 'pi-30wei.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))
  • rstrip()方法删除每行末尾的换行符
  • strip()方法删除每行左边的空格

打印大型文件时,若只想打印前一段内容,后面用省略号表示,可表示为:(打印前52位)

print(f"{pi_string}[:52]...") 

写入文件

写入空文件

要将文本写入文件,需要在调用open()时需要提供另一个实参,告诉Python你要写入打开的文件。例如:将一条简单的消息存储到文件中,而不是将其打印到屏幕上

filename = 'programming.txt'
with open(filename,'w') as file_object:
    file_object.write('I love programming.')

此时程序文件所在的目录中将会出现一个programming.txt文件

open()函数的第二个参数:读取模式('r')   写入模式('w')   附加模式('a')     读写模式('r+')如果省略了模式实参,Python将以默认的只读模式打开文件。

注意1:如果要写入的文件不存在,函数open()将自动创建它。然而,以写入模式('w')打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件的内容。

注意2:Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式。

写入多行

函数write()不会在写入的文本末尾添加换行符,因此如果两次调用write()会发现两行字符串挤在一行。

在字符串的末尾添加换行符即可。

file_object.write('I love programming.n')
file_object.write('I love creating new games.n')

附加到文件

如果要给文件添加内容,而不是覆盖原有的内容,可以以附加模式('a')打开文件。以附加模式打开文件时,Python不会在返回文件对象前清空文件的内容,而是将写入文件的行添加到文件末尾。如果指定的文件不存在,Python将为你创建一个空文件。 

异常

Python使用称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行;如果未对异常进行处理,程序将停止并显示traceback,其中包含有关异常的报告。

异常是使用try-except代码块处理的。让Python执行指定的操作,同时告诉Python发生异常时怎么办。即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。

处理ZeroDivisionError异常 

用数除以0:

print(5/0)

报错:

Traceback (most recent call last):
  File "E:python项目数据练习-文件和异常.py", line 48, in
    print(5/0)
ZeroDivisionError: division by zero

使用try-except代码块

处理可能引发的异常,告诉它如果这些代码引发了指定的异常该怎么办。

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")

将导致错误的代码行print(5/0)放在一个try代码块中。如果try代码块中的代码运行起来没有问题,Python将跳过except代码块;如果try-except代码块后面还有其他代码,程序将接着运行。

使用异常避免崩溃

发生错误时,如果程序还有工作尚未完成,妥善地处理错误就尤其重要。这种情况经常会出现在要求用户提供输入的程序中;如果程序能够妥善地处理无效输入,就能再提示用户提供有效输入,而不至于崩溃。

下面来创建一个只执行除法运算的简单计算器: 

print("Give me two numbers,I will divide them.")
print(("enter 'q' will quit."))
while True:
    first_number = input("please input first number:")
    if first_number == 'q':
        break
    second_number = input("please input second number:")
    if second_number == 'q':
        break
    answer = int(first_number) / int(second_number)
    print(answer)

该程序没有采取任何处理错误的措施,因此在执行除数为0的除法运算时,它将崩溃。应使用异常处理:

---snip---
    try:
        answer = int(first_number) / int(second_number)
        print(answer)
    except ZeroDivisionError:
        print("You can't divide by zero!")

 try-except-else代码块

try语句只包含可能出错的代码。依赖try代码块成功执行的代码都应放到else代码块中:

---snip---
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by zero!")
    else:
        print(answer)

处理FileNotFoundError异常

使用文件时,一种常见的问题是找不到文件:查找的文件可能在其他地方,文件名可能不正确,或者这个文件根本就不存在,就会出现该异常。

filename = 'alice.txt'
try:
    with open(filename,encoding='utf-8') as f:
        contents = f.read()
except FileNotFoundError:
    print(f"Sorry,the file {filename} is not exist.")

分析文本

可以分析包含整本书的文本文件

下面是对只包含童话名"Alice in Wonderland"的字符串调用方法split()的结果:

title = 'Alice in Wonderland'

title.split()

输出:['Alice', 'in', 'Wonderland']

 方法split()以空格为分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中。

下面来提取童话《Alice in Wonderland》的文本,将对整篇小说调用split(),再计算得到的列表包含多少个元素,从而确定整篇童话大致包含多少个单词。

filename = 'alice.txt'
try:
    with open(filename,encoding='utf-8') as f:
        contents = f.read()
except FileNotFoundError:
    print(f"Sorry,the file {filename} is not exist.")

else:
    #计算大致包含多少个单词
    words = contents.split()
    num_words = len(words)
    print(f"the file {filename} has about {num_words} words.")

输出:the file alice.txt has about 12 words.

使用多个文件

可以分析多本书。计算每本书大致包含多少个单词。

可以将大部分代码移到名为count_words()的函数中,更方便使用。

def count_words(filename):
    try:
        with open(filename, encoding='utf-8') as f:
            contents = f.read()
    except FileNotFoundError:
        print(f"Sorry,the file {filename} is not exist.")

    else:
        # 计算每本书大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print(f"the file {filename} has about {num_words} words.")


filenames = ['alice.txt', 'guest.txt','little_woman.txt', 'programming.txt']
for filename in filenames:
    count_words(filename)

文件little_woman.txt不存在,但这丝毫不影响该程序处理其他文件,输出为:

the file alice.txt has about 12 words.
the file guest.txt has about 5 words.
Sorry,the file little_woman.txt is not exist.
the file programming.txt has about 7 words.

  • 使用try-except代码块的优点:避免用户看到traceback,以及让程序继续分析能够找到的其他文件,进而继续执行,输出结果。

静默失败

有时候你希望程序在发生异常时保持静默,就像什么都没有发生一样继续运行。可像通常那样编写try代码块,但在except代码块中使用pass语句明确地告诉Python什么都不要做。

try:
   ---snip---
except FileNotFoundError:
    pass
else:
    ---snip---

存储数据

程序都把用户提供的信息存储在列表和字典等数据结构中 ,模块json让你能够将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。还可以使用json在Python程序之间分享数据。

使用json.dump()和json.load()

使用json.dump()来存储一组数,使用json.load()将这些数读取到内存中。

函数json.dump()接受两个实参:要存储的数据,以及可用于存储数据的文件对象。下面演示了如何使用json.dump()来存储数字列表:

import json

numbers = [2, 3, 6, 4, 7, 9, 8, 9]
filename = 'numbers.json'  #通常使用文件扩展名.json来指出文件存储的数据为JSON格式
with open(filename, 'w') as f:
    json.dump(numbers, f)

下面再编写一个程序,使用json.load()将列表读取到内存中:

import json

filename = 'numbers.json'
with open(filename) as f:  #open()默认只读模式
    numbers = json.load(f)
    print(numbers)

保存和读取用户生成的数据

用户生成的数据如果不以某种方式存储,用户的信息会在程序停止运行时丢失。下面来看一个这样的例子:提示用户首次运行程序时输入自己的名字,并在再次运行程序时记住他。(即将存储和读取两个程序合并在一起了)

import json
filename = 'username.json'
try:
    with open(filename) as f:
        usernames = json.load(f)
except FileNotFoundError:
    username = input("please input your name:")
    filename = 'username.json'
    with open(filename,'w') as f:
        json.dump(username,f)
        print(f"we'll remember you when you come back,{username}!")
else:
    print(f"Hello,{usernames}! welcome come back.")

重构

代码能够正确地运行,但通过将其划分为一系列完成具体工作的函数,还可以改进。这样的过程称为重构。重构让代码更清晰、更易于理解、更容易扩展。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/467727.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号