Python 基础入门笔记(四)———— 文件 *** 作、面向对象、异常、模块包

Python 基础入门笔记(四)———— 文件 *** 作、面向对象、异常、模块包,第1张

Python 基础入门笔记(四)———— 文件 *** 作、面向对象、异常、模块包

文章目录

一、文件 *** 作

1.1 文件的基本 *** 作

1.1.1 打开1.1.2 打开文件模式1.1.3 文件对象方法

1.1.3.1 写1.1.3.2 读1.1.2.3 seek() 1.1.4 关闭 1.2 文件备份1.3 文件和文件夹 *** 作

1.3.1 文件/文件夹重命名1.3.2 删除文件1.3.3 创建文件夹1.3.4 删除文件夹1.3.5 获取当前目录1.3.6 改变默认目录1.3.7 获取目录列表 二、面向对象基础

2.1 面向对象的实现方法

2.1.1 定义类2.1.2 创建对象2.1.3 self 2.2 添加和获取对象属性2.3 魔法方法

2.3.1 __init__()2.3.2 __str__()2.3.3 __del__() 三、面向对象继承

3.1 旧式类与新式类3.2 单继承3.3 多继承3.4 子类重写父类同名方法和属性3.5 子类调用父类同名方法和属性3.6 多层继承3.7 super()调用父类方法3.8 私有权限 三、面向对象其他

3.1 面向对象三大特征3.2 多态3.3 类属性和实例属性

3.3.1 类属性3.3.2 实例属性 3.4 类方法和静态方法

3.4.1 类方法3.4.2 静态方法 四、异常

4.1 异常语法4.2 自定义异常 五、模块和包

5.1 导入模块

5.1.1 导入方式5.1.2 定义别名 5.2 自定义模块5.3 模块定位顺序5.4 all 列表5.5 包

5.5.1 导包方式5.5.2 注意事项


一、文件 *** 作 1.1 文件的基本 *** 作 1.1.1 打开

打开文件 *** 作步骤:

    打开文件读写等 *** 作关闭文件

用 open 函数,打开已经存在的文件,或者创建一个新文件,语法: open(name, mode)

name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。mode:设置打开文件的模式(访问模式):只读、写入、追加等。 1.1.2 打开文件模式 模式描述r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。r+打开一个文件用于读写。文件指针将会放在文件的开头。rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。w打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。wb以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。w+打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。wb+以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。a打开一个文件用于追加。如果该文件已存在、文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

注意:

基本模式有:r w a,其他的模式是在其基础上泛生而来。模式中带有 b,代表二进制。模式中带有 +,代表可读可写。

示例1:

# r: 如果文件不存在,则报错:不支持写入 *** 作,表示只读
f = open('test.txt', 'r')
# f = open('test1.txt', 'r')  # 文件不存在,报错
# f.write('aa')  # 报错
con = f.read()
print(con)
f.close()

# w:只写,如果文件不存在,新建文件:执行写入,会覆盖原有内容
f = open('text1.txt', 'w')
f.write('bbb')
f.close()

# a:追加,如果文件不存在,新建文件:在原有内容基础上,追加新内容
f = open('test.txt', 'a')
f.write('lalala')
f.close()

# 访问模式参数可以省略,如果省略表示访问模式为 r
f = open('text.txt')
f.close()

示例2:

# w+:没有该文件会新建;w 特点,文件指针在开头,用新内容覆盖原内容
# 如果只读不写,文件内容会空
f = open('test.txt', 'w+')
f.write("haha")  # 此时文件新内容覆盖原内容,文件指针在末尾
con = f.read()  # 因此接着读,将不会读出内容
print(con)
f.close()

1.1.3 文件对象方法 1.1.3.1 写

语法: 文件对象.write( '内容')

# 1. 打开文件
f = open('test.txt', 'w')
# 2.文件写入
f.write('hello world')
# 3. 关闭文件
f.close()

注意:

    w 和 a 模式:如果文件不存在则创建该文件如果文件存在,w 模式先清空再写入,a 模式直接末尾追加。r 模式:如果文件不存在则报错。

1.1.3.2 读

设 test.txt 文件中内容如下:

read()

语法: 文件对象.read( num)
num 表示要从文件中读取的数据的长度(单位是字节),如果没有传入 num,那么就表示读取文件中所有的数据。

f = open('test.txt', 'r')
# 换行符 n 会有字节占位
# read 不写参数表示读取所有
print(f.read())
print(f.read(4))  # 此时文件的指针在末尾, 所以不会读取任何数据
f.close()

结果如下:

readlines()

readlines 可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。

f = open('test.txt', 'r')
con = f.readlines()
print(con)  # ['aaan', 'bbbn', 'ccc']
f.close()

readline()
readline 每次打印一行数据,文件指针会后移。

f = open('test.txt', 'r')
con = f.readline()
print(f'第⼀⾏:{con}')
con = f.readline()
print(f'第二⾏:{con}')
con = f.readline()
print(f'第三⾏:{con}')
f.close()

结果如下:


1.1.2.3 seek()

作用: 用来移动文件指针

语法: 文件对象.seek(偏移量,起始位置)

起始位置: 0:文件开头 1:当前位置  2:文件结尾

f = open('test.txt', 'r+')
f.seek(2, 0)  # 开头偏移两个字符
con = f.read()
print(con)
f.close()

结果如下:


1.1.4 关闭

文件对象.close()


1.2 文件备份

备份文件步骤:

    接收用户输入的文件名规划备份文件名备份文件写入数据

代码如下:

# 1. 用户输入目标文件名字 
old_name = input('请输入要备份的文件名:')

# 2. 规划备份文件的名字
# 2.1 提取目标文件后缀
index = old_name.rfind('.')  # 从右侧找 '.',如:sound.txt.mp3  是 mp3 文件类型

if index > 0: # 限制文件格式为 “xxx.后缀” 才可备份 
    postfix = old_name[index:]

# 2.2 组织备份文件名, xx[备份]后缀
new_name = old_name[:index] + '[备份]' + postfix

# 3. 备份文件写入数据(数据和原文件一样)
# 3.1 打开 原文件 和 备份文件
old_f = open(old_name, 'rb')  # 以二进制打开
new_f = open(new_name, 'wb')

# 3.2 原文件读取,备份文件写入
# 如果不确定目标文件大小,循环读取写入,当读取出来的数据没有了则终止循环
while True:
    con = old_f.read(1024)
    if len(con) == 0:
        break
    new_f.write(con)

# 3.2 关闭文件
old_f.close()
new_f.close()

1.3 文件和文件夹 *** 作

在 Python 中文件和文件夹的 *** 作要借助 os 模块里面的相关功能。

导入 os 模块:import os

1.3.1 文件/文件夹重命名

os.rename(目标文件名,新文件名)

1.3.2 删除文件

os.remove(目标文件名)

1.3.3 创建文件夹

os.mkdir(文件夹名字)

1.3.4 删除文件夹

os.rmdir(文件夹名字)

1.3.5 获取当前目录

os.getcwd()

1.3.6 改变默认目录

os.chdir(目录)

1.3.7 获取目录列表

os.listdir(⽬目录)

应用:批量重命名

# flag = 1:把文件夹所有文件重命名 python-xxx
# flag = 2:删除python-重命名

import os

# 构造内置条件的数据
flag = 2

# 1. 找到所有文件:获取文件夹的目录列表
file_list = os.listdir()
print(file_list)

# 2. 重构名字
for i in file_list:
    if flag == 1:
        new_name = 'python-' + i
    elif flag == 2:
        num = len('python-')
        new_name = i[num:]

	# 3. 重命名
    os.rename(i, new_name)

二、面向对象基础 2.1 面向对象的实现方法 2.1.1 定义类

语法:

class 类名():
	代码
	......

注意: 类名遵循大驼峰命名习惯,即首字母大写

扩展

2.1.2 创建对象

语法: 对象名 = 类名()

注意: 创建对象的过程也叫实例化对象。

2.1.3 self

self 指的是调用该函数的对象。

示例:

# 定义洗衣机类
class Washer():
    def wash(self):
        print("洗衣服")
        print(self)

# 创建对象
haier1 = Washer()
print(haier1)  # <__main__.Washer object at 0x000001455A806D70>

# 使用实例方法
haier1.wash()  # 洗衣服
               # <__main__.Washer object at 0x000001455A806D70>
               # self 指的是调用该函数的对象
               # self 和 对象得到的结果是一致的,都是当前对象的内存中存储地址。

# 创建两个对象
haier2 = Washer()  # 不同对象存储地址不一样
print(haier2)

2.2 添加和获取对象属性

添加对象属性的方式有两种:类外面添加、类里面添加

    类外面添加和获取对象属性

    语法:对象名.属性名

    类里面添加获取对象属性

    语法:self.属性名

示例:

class Washer():
	def __init__(self):
        self.height = 300  # 类内 添加属性,一般在 __init()__ 方法中添加类内属性,即实例属性
        
    def print_info(self):
        print(f'洗衣机的宽度:{self.width}')  # 类内 获取属性

haier = Washer()
haier.width = 400  # 类外 添加属性
print(f'洗衣机的宽度:{haier.width}')  # # 类外 获取属性

haier.print_info()

2.3 魔法方法

__xx__() 的函数叫做魔法方法,指的是具有特殊功能的函数。

2.3.1 init()

__init__() 方法的作用:初始化对象,分为带参数和不带参数两种。

    不带参数:

    class Washer():
        # __init__ 初始化
        def __init__(self):
            self.width = 400
            self.height = 400
    
        def print_info(self):
            print(f'洗衣机的宽度:{self.width}')  # 洗衣机的宽度:400
            print(f'洗衣机的宽度:{self.width}')  # 洗衣机的宽度:400
    
    haier = Washer()
    haier.print_info()
    

    带参数:

    class Washer():
        # 带参数__init__ 初始化
        def __init__(self, width, height):
            self.width = width
            self.height = height
    
        def print_info(self):
            print(f'洗衣机的宽度:{self.width}')  # 洗衣机的宽度:100
            print(f'洗衣机的宽度:{self.width}')  # 洗衣机的宽度:200
    
    haier1 = Washer(100,200)
    haier1.print_info()
    
    # haier2 = Washer()  # 报错
    

注意︰

    __init__() 方法,在创建一个对象时默认被调用,不需要手动调用__init__(self) 中的 self 参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。

2.3.2 str()

当使用 print 输出对象的时候,默认打印对象的内存地址。如果类定义了__str__方法,那么就会打印从在这个方法中 return 的数据。

示例:

class Washer():
    def __str__(self):
        return '洗衣机类的解释说明'

haier1 = Washer()
print(haier1)  # 洗衣机类的解释说明

2.3.3 del()

当删除对象时,解释器也会默认调用 __del__() 方法。

class Washer():
    def __del__(self):
       print('删除')

haier = Washer()
del haier  # 删除

三、面向对象继承 3.1 旧式类与新式类

经典类或旧式类:

不由任意内置类型派生出的类,称之为经典类。

class类名:
	代码
	......

新式类:
Python中,所有类默认继承 object 类,object 类是顶级类或基类,其他子类叫做派生类。

class类名(object):
	代码
	......

3.2 单继承
# 父类 A
class A(object):
    def __init__(self):
        self.num = 1

    def info_print(self):
        print(self.num)

# 子类 B
class B(A):
    pass  # 作用是省略

result = B()
result.info_print()  # 1
print(result.num)  # 1

3.3 多继承

多继承:一个类同时继承了多个父类。

# 父类A
class A(object):
    def __init__(self):
        self.num_a = 1

    def info_print(self):
        print(f'A类:{self.num_a}')

# 父类B
class B(object):
    def __init__(self):
        self.num_a = 2

    def info_print(self):
        print(f'B类:{self.num_a}')

# 子类
class C(A, B):
    pass

cc = C()
print(cc.num_a)  # 1
cc.info_print()  # A类:1

注意:

    如果一个类继承多个父类,默认使用第一个父类的同名属性和方法单继承中,子类默认继承父类的所有属性和方法多继承中,子类继承第一个父类的所有属性和所有类的方法两种继承方式子类都可以重写父类属性和方法

如:

# 父类A
class A(object):
    def __init__(self):
        self.num_a = 1
        self.num_aa = 2

    def info_print(self):
        print(f'A类:{self.num_a}')

# 父类B
class B(object):
    def __init__(self):
        self.num_a = 3
        self.num_b = 4

    def info_print(self):
        print(f'B类:{self.num_a}')

    def info_print2(self):
        print(f'B类:{self.num_a}')

# 子类
class C(A, B):
    pass

cc = C()
 # vars(object):返回对象的属性
print(vars(cc)) # {'num_a': 1, 'num_aa': 2}
print(cc.num_a)   # 1
print(cc.num_aa)  # 2  -- 第一个父类特有的属性
# print(cc.num_b)   # 报错  -- 第二个父类特有的属性
cc.info_print()   # A类:1  
cc.info_print2()   # B类:1  -- 第二个父类特有的方法

3.4 子类重写父类同名方法和属性

如果一个类继承多个父类,子类会调用子类同名属性和方法

# 父类A
class A(object):
    def __init__(self):
        self.num = 1

    def info_print(self):
        print(f'A父类:{self.num}')

# 父类B
class B(object):
    def __init__(self):
        self.num = 2

    def info_print(self):
        print(f'B父类:{self.num}')

# 子类
class C(A, B):
    def __init__(self):
        self.num = 33

    def info_print(self):
        print(f'子类:{self.num}')


cc = C()
print(cc.num)  # 33
cc.info_print()  # 子类:33

print(C.__mro__)  # 通过__mro__方法来获取这个类的调用顺序
# (, , , )

3.5 子类调用父类同名方法和属性
# 父类 A
class A(object):
    def __init__(self):
        self.num = 11

    def info_print(self):
        print(f'A父类:{self.num}')

# 父类 B
class B(object):
    def __init__(self):
        self.num = 22

    def info_print(self):
        print(f'B父类:{self.num}')

# 子类 C
# 父类A
class A(object):
    def __init__(self):
        self.num = 11

    def info_print(self):
        print(f'A父类:{self.num}')

# 父类B
class B(object):
    def __init__(self):
        self.num = 22

    def info_print(self):
        print(f'B父类:{self.num}')

# 子类C
class C(A, B):
    def __init__(self):
        self.num = 33

    def info_print(self):
        # 加自己的初始化的原因:如果不加这个自己的初始化, num 属性值是上次调用的 init 内的 num 属性值
        self.__init__()
        print(f'子类:{self.num}')

    # 子类调用父类同名方法和属性
    def info_a_print(self):
        # 父类类名.函数()
        # 再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在 init 初始化位置,所以需要再次调用 init
        A.__init__(self)
        A.info_print(self)

    def info_b_print(self):
        B.__init__(self)
        B.info_print(self)

cc = C()
print(cc.num)  # 33

cc.info_a_print()  # A父类:11  --- 若没有 A.__init__(self),则同名属性为 子类C 属性值
cc.info_b_print()  # B父类:22  --- 若没有 A.__init__(self),则同名属性为上一个 A类 属性值
cc.info_print()  # 子类:33  --- 若没有 self.__init__(),则同名属性为上一个 B类 属性值

3.6 多层继承
# 父类 A
class A(object):
    def __init__(self):
        self.num = 11

    def info_print(self):
        print(f'A父类:{self.num}')

# 父类 B
class B(object):
    def __init__(self):
        self.num = 22

    def info_print(self):
        print(f'B父类:{self.num}')

# 子类C
class C(A, B):
    def __init__(self):
        self.num = 33

    def info_print(self):
        # 加自己的初始化的原因:如果不加这个自己的初始化, num 属性值是上次调用的 init 内的 num 属性值
        self.__init__()
        print(f'子类:{self.num}')

    # 子类调用父类同名方法和属性
    def info_a_print(self):
        # 父类类名.函数()
        # 再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在 int 初始化位置,所以需要再次调用 init
        A.__init__(self)
        A.info_print(self)

    def info_b_print(self):
        B.__init__(self)
        B.info_print(self)

class D(C):
    pass

dd = D()
dd.info_print()  # 子类:33
dd.info_a_print()  # A父类:11
dd.info_b_print()  # B父类:22

3.7 super()调用父类方法

使用super() 可以自动查找父类。调用顺序遵循 __mro__类属性的顺序。比较适合单继承使用。
super() 包括 有参数无参数 两种方式。

B类继承A类,C类继承B类,一次性调用父类的同名属性和方法,代码如下:

# 父类A
class A(object):
    def __init__(self):
        self.num = 11

    def info_print(self):
        print(f'A父类:{self.num}')

# 父类B
class B(A):
    def __init__(self):
        self.num = 22

    def info_print(self):
        print(f'B父类:{self.num}')
        # 有参数 super:super(当前类名, self).函数()
        # super(B, self).__init__()
        # super(B, self).info_print()

        # 无参数super
        super().__init__()
        super().info_print()

# 子类C
class C(B):
    def __init__(self):
        self.num = 33

    def info_print(self):
        # 加自己的初始化的原因:如果不加这个自己的初始化, num 属性值是上次调用的 init 内的 num 属性值
        self.__init__()
        print(f'子类:{self.num}')

    # 一次性调用父类的同名属性和方法
    def info_a_b_info(self):
        # 法一:
        # A.__init__(self)
        # A.info_print(self)
        # B.__init__(self)
        # B.info_print(self)

        # 法二:super()
        # 有参数 super:super(当前类名, self).函数()
        # super(C, self).__init__()
        # super(C, self).info_print()

        # 无参数super
        super().__init__()
        super().info_print()

cc = C()
cc.info_a_b_info()  # B父类:22  A父类:11

C 类同时继承 A 类与 B 类,代码如下:

# 父类A
class A(object):
    def __init__(self):
        self.num = 11

    def info_print(self):
        print(f'A父类:{self.num}')

# 父类B
class B(object):
    def __init__(self):
        self.num = 22

    def info_print(self):
        print(f'B父类:{self.num}')

# 子类C
class C(A, B):
    def __init__(self):
        self.num = 33

    def info_print(self):
        # 加自己的初始化的原因:如果不加这个自己的初始化, num 属性值是上次调用的 init 内的 num 属性值
        self.__init__()
        print(f'子类:{self.num}')

    # 一次性调用父类的同名属性和方法
    def info_a_b_info(self):

        # 无参数super
        super().__init__()
        super().info_print()

cc = C()
cc.info_a_b_info()  # A父类:11   ---默认调用第一个父类的方法

3.8 私有权限

  python中,实例属性和方法若设置为私有权限,则 该实例属性或实例方法不继承给子类,并且一般定义函数名 get_xx 用来获取私有属性,定义set_xx用来修改私有属性值。

设置私有权限的方法:在属性名和方法名前面加上两个下划线___

# 父类 A
class A(object):
    def __init__(self):
        self.num = 11
        # 定义私有属性  两道下划线
        self.__num = 22

    def info_print(self):
        print(f'A父类:{self.num}')
        self.__info_print()

    # 定义私有方法
    def __info_print(self):
        print(f'私有方法:{self.__num}')

    def get_num(self):
        return self.__num

    def set_num(self):
        self.__num = 500

# 子类 B
class B(A):
    pass

bb = B()
# print(bb.num)  # 11
# print(bb.__num)   # 报错
# bb.__info_print()  # 报错 私有方法报错,继承不了
bb.info_print()  # A父类:11 私有方法:22

print(bb.get_num())  # 22
bb.set_num()
print(bb.get_num())  # 500

三、面向对象其他 3.1 面向对象三大特征

封装:将属性和方法书写到类的里面的 *** 作即为封装,并且封装可以为属性和方法添加私有权限。继承:

单继承中,子类默认继承父类的所有属性和方法多继承中,子类继承第一个父类的所有属性和所有类的方法两种继承方式子类都可以重写父类属性和方法。 多态:传入不同的对象,产生不同的结果。


3.2 多态

定义︰ 多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的结果。

class Dog(object):
    def work(self): # 父类提供统一的⽅方法,哪怕是空方法
        print('指哪打哪...')

class ArmyDog(Dog): # 继承Dog类
    def work(self):  # ⼦子类重写⽗父类同名⽅方法
        print('追击敌人...')

class DrugDog(Dog):
    def work(self):
        print('追查毒品...')

class Person(object):
    def work_with_dog(self, dog): # 传⼊入不不同的对象,执⾏行行不不同的代码,即不不同的work函数
        dog.work()


ad = ArmyDog()
dd = DrugDog()
person = Person()
person.work_with_dog(ad)  # 追击敌人...
person.work_with_dog(dd)  # 追查毒品...

3.3 类属性和实例属性 3.3.1 类属性

设置和访问类属性
类属性就是类对象所拥有的属性,它被该类的所有实例对象 所共有类属性可以使用类对象或实例对象访问。修改类属性
类属性只能通过类对象修改,不能通过实例对象修改。 如果通过实例对象修改类属性,表示的是创建了一个实例属性。

示例:

class Dog(object):
    tooth = 10  # 类属性

dog = Dog()

# 访问
print(Dog.tooth)  # 10
print(dog.tooth)  # 10

# 修改
# 1. 通过类来修改
Dog.tooth = 20
print(Dog.tooth)  # 20

# 2. 通过对象来修改
dog.tooth = 40  # 不是修改类属性值,而是为 dog 对象添加一个属性
print(Dog.tooth)  # 20  -- 修改失败
print(dog.tooth)  # 40

3.3.2 实例属性

示例属性,也叫对象属性。其可通过类内类外都可修改和获取。

示例:

class Washer():
	def __init__(self):
        self.height = 300  # 类内 添加属性,一般在 __init()__ 方法中添加类内属性,即实例属性
        
    def print_info(self):
        print(f'洗衣机的宽度:{self.width}')  # 类内 获取属性

haier = Washer()
haier.width = 400  # 类外 添加属性
print(f'洗衣机的宽度:{haier.width}')  # # 类外 获取属性

haier.print_info()

注意: 实例属性要求每个对象为其 单独开辟一份内存空间来记录数据,而类属性为全类所共有,仅占用一份内存,更加节省内存空间。


3.4 类方法和静态方法 3.4.1 类方法

类方法特点:

第一个形参是类对象的方法

需要用装饰器 @classmethod 来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。

示例:

class Dog(object):
    __tooth = 10

    @classmethod  # 类方法:与类属性配合使用
    def get_tooth(cls):
        return cls.__tooth

dog = Dog()
result = dog.get_tooth()
print(result)  # 10

使用场景:

类方法一般和类属性配合使用。当方法中需要使用 类对象(如:访问私有类属性等)时,定义类方法


3.4.2 静态方法

静态方法特点:

需要通过装饰器 @staticmethod 来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)静态方法也能够通过 实例对象 和 类对象 去访问。

示例:

class Dog(object):
    @staticmethod
    def info_print():
        print('这是静态方法')

dog = Dog()
# 静态方法既可以使用对象访问有可以使用类访问
dog.info_print()  # 这是静态方法
Dog.info_print()  # 这是静态方法

使用场景:

当方法中 既不需要使用实例对象(如:实例对象,实例属性),也不需要使用类对象(如:类属性、类方法、创建实例等)时,定义静态方法。取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗


四、异常 4.1 异常语法

一般写法

try:
	可能发生错误的代码
except :
	如果出现异常执行的代码

捕获指定异常

try:
	可能发生错误的代码
except 异常类型:
	如果捕获到该异常类型执行的代码

捕获多个指定异常

try:
	可能发生错误的代码
except (异常类型1, 异常类型2, ...):
	如果捕获到该异常类型执行的代码

捕获异常描述信息

try:
	可能发生错误的代码
except 异常类型 as result:
	print(result)  # 打印描述信息
	如果捕获到该异常类型执行的代码

捕获所有异常

try:
	可能发生错误的代码
except Exception:
	如果捕获到该异常类型执行的代码

Exception是所有程序异常类的父类。

异常的 else

try:
	可能发生错误的代码
except 异常类型:
	如果捕获到该异常类型执行的代码
else:
	print('else是没有异常的时候执行的代码')

异常的 finally

try:
	可能发生错误的代码
except 异常类型:
	如果捕获到该异常类型执行的代码
else:
	print('else是没有异常的时候执行的代码')
finally:
	print('finally是有无异常都要执行的代码')

示例:

try:
    f = open('test.txt', 'r')
except Exception :
    f = open('test.txt', 'w')
else:
    print('没有异常执行的代码')
finally:
    f.close()

4.2 自定义异常

Python中,抛出自定义异常的语法为raise异常类对象。

示例:密码长度不足,则报异常(用户输入密码,如果输入的长度不足5位,则报错,即抛出自定义异常,并捕获该异常)。

# 自定义异常类,继承 Exception
class ShortInputError(Exception):
    def __init__(self, length, min_len):
        self.length = length
        self.min_len = min_len

    # 设置抛出异常的描述信息
    def __str__(self):
        return f'你输入的长度是{self.length},不能少于{self.min_len}个字符'

def main():
    try:
        con = input('请输入密码:')
        if len(con) < 5:
            # 抛出异常类创建对象
            raise ShortInputError(len(con), 5)
    except Exception as result:
        print(result)
    else:
        print('密码已经输入完成')

main()

运行结果:


五、模块和包

python 模块是一个 python 文件,导入模块就是导入 pthon 文件。

5.1 导入模块 5.1.1 导入方式
    import 模块名from 模块名 import 功能1, 功能2, ...from 模块名 import *

示例:

# 方式一:
# import 模块名
# import 模块名1, 模块名2, ...  (不推荐)
# 调用功能:模块名.功能名()
import math
print(math.sqrt(3))  # 开平方计算

# 方式二:
# from 模块名 import 功能1, 功能2 ...;
# 功能调用:(不需要书写模块名.功能)
from math import sqrt
print(sqrt(9))

# 方式三:
# from 模块名 import *
from math import *
print(sqrt(9))

5.1.2 定义别名

模块定义别名: import 模块名 as 别名

功能定义别名:from 模块名 import 功能 as 别名

注意: 定义别名,就不能用原来的模块和功能名字

# 模块别名
import time as tt
tt.sleep(2)
# time.sleep(2) # 报错
print('hello')

# 功能别名
from time import sleep as sl
sl(2)
print('hello')

5.2 自定义模块

自定义模块 my_module.py:

def testA(a, b):
    print(a + b)

# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行  testA(4, 4) 函数调用
# 只在自身模块时,系统变量 __name__ 是 __main__
if __name__ == '__main__':  # 用于测试 
    testA(4, 4) 

调用自定义模块:

import my_module

my_module.testA(2,3)  # 5

注意: 如果使用 from .. import ..或 from .. import * 导入多个模块的时候,且模块内有同名功能。当调用这个同名功能的时候,调用到的是 后导入的模块的功能


5.3 模块定位顺序

当导入一个模块,Python解析器对模块位置的搜索顺序是:

    当前目录如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/pythonl/

示例:

# 现假设当前目录下存在自定义模块 random ,和 python 中的 random 模块名重复,且没有自定义 randint 方法
import random
num = random.randint(0, 5) # 报错 -- 先搜索当前目录,所以导入的模块是自定义的 random 模块
print(num)

拓展:

# 数据通过引用传递,因此变量可以覆盖模块
import time
print(time)

time = 1
print(time)  # 1

5.4 all 列表

如果模块文件中有 __all__ 变量,当使用 from xxx import * 导入时,只能导入这个列表中的元素

自定义模块 my_modeule2.py:

# 定义多个功能,把某个功能添加到 __all__
__all__ = ['testA']

def testA():
    print('testA函数')

def testB():
    print('testB函数')

测试代码:

from my_module_2 import *
testA()  # testA函数
# testB()  # 报错  -- testB没有在 all 列表中

5.5 包

如果一个文件夹中含有__init__.py 文件,那么这个文件夹就称之为包。

包是模块的一个集合,将模块以文件夹的方式集中在一起。

5.5.1 导包方式

方式一:

import 包名.模块名

调用方式:包名.模块名.目标

方式二:

from 包名 import *

调用方式:模块名.目标

注意: 必须在 __init__.py 文件中添加 __all__ = [] ,控制允许导入的模块列表。


包结构:

方式一示例:

my_module1.py:

def info_print1():
    print('my_module1')

测试代码:

import mypackage.my_module1
mypackage.my_module1.info_print1()  # my_module1

方式二示例:

my_module2.py:

def info_print2():
    print('my_module2')

__init__.py:

__all__ = ['my_module1']

测试代码:

from mypackage import *  # 导入模块1、2
my_module1.info_print1()  # my_module1
my_module1.info_print2()  # my_module2

5.5.2 注意事项

方式一在不引入 all 列表的时候方法也可以正常使用,但 pycharm 不会提示。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5720679.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存