python3模块与包

模块

1.概念:

Python3 模块是包含 Python 定义和语句的文件,用于组织代码、实现功能复用。模块通过 import 导入,可包含函数、类、变量等。

2.模块的分类

在python中,模块通常可以分为两大类:内置模块(目前使用的)和自定义模块

3.模块的导入方式

import 模块名

from 模块名 import 功能名

from 模块名 import *

import 模块名 as 别名

from 模块名 import 功能名 as 别名

4.使用import导入模块

在Python中,使用import关键字可以导入其他模块或库,语法如下:

import 模块名
 

导入后,通过模块名.成员名的方式调用模块中的函数、类或变量。

案例:使用import导入match模块

import math 

#求数字9的平方根 = 3
print(math.sqrt(9))

案例:使用import导入math 与 random模块

import math, random

print(math.sqrt(9))
print(random.randit(-100,100))

普及:我们在python代码中,通过import方式导入的实际上都是文件名称

5.使用from模块名import功能名

import代表导入某个或多个模块中的所有功能,但是有些情况下,我们只希望使用这个模块下的某些方法,而不需要全部导入。这个时候就建议采用from模块名import功能名

from模块名import *

这个导入方式代表导入这个模块的所有功能(等价于import模块名)

from math import *

from 模块名 import 功能名(推荐)

from math import sqrt,floor

注意:以上两种方式都可以用于导入某个模块中的某些方法,但是在调用具体方法时,我们只需要功能名()即可

功能名()

6.使用as关键字为导入模块定义别名

使用as为模块指定别名,简化调用:

import 模块名 as 别名
 

7.使用as关键字为导入功能定义别名

from 模块 import 功能名 as 功能别名

案例:

from time import sleep as sl,time as t


#调用方式

print ("您好")
sl(100)
print ("您好")

自定义模块

1.概念:

自定义模块是用户根据需求创建的Python文件,包含可重用的代码(如函数、类、变量等)。通过模块化设计,可以提高代码的可维护性和复用性。

2.自定义模块的特点

模块即文件
每个.py文件都是一个独立的模块,文件名(不含扩展名)即为模块名。例如utils.py的模块名为utils

作用域隔离
模块内部定义的变量、函数或类默认属于模块作用域,通过import导入后需通过模块名前缀访问(如utils.func())。

可复用性
模块可以被其他脚本多次导入,避免代码重复。

3.定义一个自定义模块

创建模块
新建一个Python文件(如mymodule.py),写入以下内容:

def greet(name):
    return f"Hello, {name}!"

PI = 3.14159
 

导入模块
在其他脚本中使用import语句导入:

import mymodule

print(mymodule.greet("Alice"))  # 输出: Hello, Alice!
print(mymodule.PI)              # 输出: 3.14159
 

4.导入方式

别名导入
通过as关键字简化模块名:

import mymodule as mm
print(mm.greet("Bob"))
 

选择性导入
使用from ... import直接导入特定对象:

from mymodule import greet
print(greet("Charlie"))  # 无需模块前缀
 

5.模块搜索路径

Python解释器按以下顺序查找模块:

  1. 当前目录
  2. 环境变量PYTHONPATH指定的路径
  3. 标准库目录
  4. 第三方库目录(如site-packages

可通过sys.path查看搜索路径:

import sys
print(sys.path)
 

6.自定义模块中功能测试(_ _name_ _)

在我们编写完自定义模块以后,最好在模块中对代码进行提前测试,以防有任何异常

测试需求:

01.要求我们可以直接在模块文件中对代码进行测试

02.代码测试完毕后,当导入其他功能时,自动生效

引入一个魔方变量:_ _name_ _,其保存内容介绍一个字符串类型的数据

随着运行页面的不同,其返回结果也是不同的:

1.如果_ _name_ _是在当前页面运行时,其返回的结果为_ _main_ _

2.如果_ _name_ _在第三方页面导入运行时,其返回结果为模块名称(文件名)

基于以上特性,我们可以把_ _name_ _编写在自定义模块中,

然后主导入模块文件,调用模块时不会调用模块中的测试模块

其语法如下:

if _ _name_ _ == '_ _main_ _':
#执行测试代码

示例:

自定义模块(未导入__name__)

主文件调用时:会调用模块中的测试模块

当导入__name__的时候:

自定义模块

主程序调用模块的时候不会调用模块的测试模块

_ _name_ _魔术方法除了可以在自定义模块中测试使用,还可以用于编写程序入口:

#定义一个main方法(入口文件)
def main():
 

7.多模块中功能命令冲突问题

命名冲突

当我们编写了多个模块时,可能在导入到其他页面时,会产生一个问题:全局变量、函数、类出现重名情况,我们把这个情况就称之为 “命名冲突”。

如导入 my_module2 和 my_module3,里面都封装了一个 func () 方法,其在导入以后,my_module3 中的 func () 方法就会覆盖 my_module2 中的 func () 方法。

案例:

#定义func函数
def func():
    print("my_module3中的func方法")
#定义func函数
def func():
    print("my_module4中的func方法")

主函数调用结果:

出现覆盖my_module3的问题

解决方式:用别名

8.注意不要定义与系统同名的模块

在编程中,定义与系统模块同名的模块可能导致冲突或意外行为。以下方法可帮助避免此类问题:

检查模块名称
在创建新模块前,确保其名称不与Python标准库或已安装的第三方库重复。例如,避免使用ossysmath等作为自定义模块名。

import importlib
if not importlib.util.find_spec("existing_module"):
    # 安全定义模块
 
解决办法(__file__)

使用__file__魔术变量,查看函数引用的是自定义还是系统

print(random.__file__)

9.__all__魔术变量

__all__ 是 Python 模块中的一个特殊变量,用于定义模块的公开接口。它通常出现在模块的 __init__.py 文件中,或直接定义在模块的顶层。__all__ 是一个字符串列表,明确指定了当使用 from module import * 时,哪些名称会被导出。

__all__ 的作用

__all__ 的主要作用是控制模块的公开接口,避免在使用 from module import * 时导入不必要的名称。默认情况下,from module import * 会导入所有不以下划线开头的名称,但通过 __all__ 可以精确控制导出内容。

使用方法

在模块中定义 __all__ 变量,列出需要导出的名称。例如:

# module.py
__all__ = ['public_function', 'PublicClass']

def public_function():
    pass

def _private_function():
    pass

class PublicClass:
    pass

class _PrivateClass:
    pass
 

此时,from module import * 只会导入 public_function 和 PublicClass,而不会导入以下划线开头的名称。

注意事项

__all__ 仅在使用 from module import * 时生效。如果使用显式导入(如 import module 或 from module import name),__all__ 不会影响导入行为。

package包

1.概念:

在编程中,package(包)是一种组织代码的方式,通常用于将相关的模块、类或函数分组,便于管理和复用。不同编程语言对package的实现和命名可能不同,例如:

  • Python:通过目录和__init__.py文件定义包。

创建Python package包

以下是一个简单Python包的目录结构示例:

my_package/  
│  
├── __init__.py          # 标识目录为Python包  
├── module1.py           # 模块1  
└── module2.py           # 模块2  
 

关键文件说明

  • __init__.py:可以是空文件,用于标记目录为包。可包含包的初始化代码或定义__all__变量。
  • 模块文件:包含具体的函数、类或变量

示例模块内容

# module1.py  
def greet():  
    return "Hello from module1"  
 
#在__init__.py
__all__ = ['my_module1']

使用package包

在其他Python脚本中通过import语句调用包:

from my_package import module1  
print(module1.greet())  # 输出: Hello from module1  
 

若包不在当前路径,需确保其所在目录已添加到系统路径:

import sys  
sys.path.append("/path/to/my_package")  
 

_ _name_ _与_ _main_ _

平时我们经常会看到这样的 Python 代码:

if __name__ == "__main__":
    main() 

在 Python 中,__name__ 和 __main__ 是两个与模块和脚本执行相关的特殊变量。

__name__ 和 __main__ 通常用于控制代码的执行方式,尤其是在模块既可以作为独立脚本运行,也可以被其他模块导入时。

1. __name__ 变量

__name__ 是一个内置变量,用于表示当前模块的名称。

__name__ 的值取决于模块是如何被使用的:

当模块作为主程序运行时:__name__ 的值被设置为 "__main__"

当模块被导入时:__name__ 的值被设置为模块的文件名(不包括 .py 扩展名)。

假设有一个 module.py 文件:

print(f"模块的 __name__ 值: {__name__}")

输出结果:

print(f"模块的 __name__ 值: {__name__}")

2. __main__ 的含义

__main__ 是一个特殊的字符串,用于表示当前模块是作为主程序运行的。

__main__ 通常与 __name__ 变量一起使用,以确定模块是被导入还是作为独立脚本运行。

3. 使用 if __name__ == "__main__": 的常见模式

在 Python 中,常见的做法是在模块的末尾添加以下代码块:

if __name__ == "__main__":
    # 这里的代码只有在模块作为主程序运行时才会执行
    main()

File(文件)方法

open() 方法

Python open() 方法用于打开一个文件,并返回文件对象。

在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。

注意:使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法。

open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)

open(file, mode='r')

完整的语法格式为:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

参数说明:

  • file: 必需,文件路径(相对或者绝对路径)。
  • mode: 可选,文件打开模式
  • buffering: 设置缓冲
  • encoding: 一般使用utf8
  • errors: 报错级别
  • newline: 区分换行符
  • closefd: 传入的file参数类型
  • opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。

mode 参数有:

模式描述
t文本模式 (默认)。
x写模式,新建一个文件,如果该文件已存在则会报错。
b二进制模式。
+打开一个文件进行更新(可读可写)。
U通用换行模式(Python 3 不支持)。
r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。
r+打开一个文件用于读写。文件指针将会放在文件的开头。
rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。
w打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
w+打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

默认为文本模式,如果要以二进制模式打开,加上 b 。

file 对象

file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:

序号方法及描述
1

file.close()

关闭文件。关闭后文件不能再进行读写操作。

2

file.flush()

刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。

3

file.fileno()

返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。

4

file.isatty()

如果文件连接到一个终端设备返回 True,否则返回 False。

5

file.next()

Python 3 中的 File 对象不支持 next() 方法。

返回文件下一行。

6

file.read([size])

从文件读取指定的字节数,如果未给定或为负则读取所有。

7

file.readline([size])

读取整行,包括 "\n" 字符。

8

file.readlines([sizeint])

读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。

9

file.seek(offset[, whence])

移动文件读取指针到指定位置

10

file.tell()

返回文件当前位置。

11

file.truncate([size])

从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小。

12

file.write(str)

将字符串写入文件,返回的是写入的字符长度。

13

file.writelines(sequence)

向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。

OS 文件/目录方法

os 模块是 Python 标准库中的一个重要模块,它提供了与操作系统交互的功能。

通过 os 模块,你可以执行文件操作、目录操作、环境变量管理、进程管理等任务。

os 模块是跨平台的,这意味着你可以在不同的操作系统(如 Windows、Linux、macOS)上使用相同的代码。

在使用 os 模块之前,你需要先导入它。导入 os 模块的代码如下:

import os

os 模块的常用功能

1. 获取当前工作目录

os.getcwd() 函数用于获取当前工作目录的路径。当前工作目录是 Python 脚本执行时所在的目录。

current_directory = os.getcwd()
print("当前工作目录:", current_directory)

2. 改变当前工作目录

os.chdir(path) 函数用于改变当前工作目录。path 是你想要切换到的目录路径。

os.chdir("/path/to/new/directory")
print("新的工作目录:", os.getcwd())

3. 列出目录内容

os.listdir(path) 函数用于列出指定目录中的所有文件和子目录。如果不提供 path 参数,则默认列出当前工作目录的内容。

files_and_dirs = os.listdir()
print("目录内容:", files_and_dirs)

4. 创建目录

os.mkdir(path) 函数用于创建一个新的目录。如果目录已经存在,会抛出 FileExistsError 异常。

os.mkdir("new_directory")

5. 删除目录

os.rmdir(path) 函数用于删除一个空目录。如果目录不为空,会抛出 OSError 异常。

os.rmdir("new_directory")

6. 删除文件

os.remove(path) 函数用于删除一个文件。如果文件不存在,会抛出 FileNotFoundError 异常。

os.remove("file_to_delete.txt")

7. 重命名文件或目录

os.rename(src, dst) 函数用于重命名文件或目录。src 是原始路径,dst 是新的路径。

os.rename("old_name.txt", "new_name.txt")

8. 获取环境变量

os.getenv(key) 函数用于获取指定环境变量的值。如果环境变量不存在,返回 None

home_directory = os.getenv("HOME")
print("HOME 目录:", home_directory)

9. 执行系统命令

os.system(command) 函数用于在操作系统的 shell 中执行命令。命令执行后,返回命令的退出状态。

os.system("ls -l")

os 常用方法

os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:

序号方法及描述
1

os.access(path, mode)


检验权限模式
2

os.chdir(path)


改变当前工作目录
3

os.chflags(path, flags)


设置路径的标记为数字标记。
4

os.chmod(path, mode)


更改权限
5

os.chown(path, uid, gid)


更改文件所有者
6

os.chroot(path)


改变当前进程的根目录
7

os.close(fd)


关闭文件描述符 fd
8

os.closerange(fd_low, fd_high)


关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略
9

os.dup(fd)


复制文件描述符 fd
10

os.dup2(fd, fd2)


将一个文件描述符 fd 复制到另一个 fd2
11

os.fchdir(fd)


通过文件描述符改变当前工作目录
12

os.fchmod(fd, mode)


改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。
13

os.fchown(fd, uid, gid)


修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。
14

os.fdatasync(fd)


强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。
15

os.fdopen(fd[, mode[, bufsize]])


通过文件描述符 fd 创建一个文件对象,并返回这个文件对象
16

os.fpathconf(fd, name)


返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。
17

os.fstat(fd)


返回文件描述符fd的状态,像stat()。
18

os.fstatvfs(fd)


返回包含文件描述符fd的文件的文件系统的信息,Python 3.3 相等于 statvfs()。
19

os.fsync(fd)


强制将文件描述符为fd的文件写入硬盘。
20

os.ftruncate(fd, length)


裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。
21

os.getcwd()


返回当前工作目录
22

os.getcwdb()


返回一个当前工作目录的Unicode对象
23

os.isatty(fd)


如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。
24

os.lchflags(path, flags)


设置路径的标记为数字标记,类似 chflags(),但是没有软链接
25

os.lchmod(path, mode)


修改连接文件权限
26

os.lchown(path, uid, gid)


更改文件所有者,类似 chown,但是不追踪链接。
27

os.link(src, dst)


创建硬链接,名为参数 dst,指向参数 src
28

os.listdir(path)


返回path指定的文件夹包含的文件或文件夹的名字的列表。
29

os.lseek(fd, pos, how)


设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效
30

os.lstat(path)


像stat(),但是没有软链接
31

os.major(device)


从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。
32

os.makedev(major, minor)


以major和minor设备号组成一个原始设备号
33

os.makedirs(path[, mode])


递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。
34

os.minor(device)


从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。
35

os.mkdir(path[, mode])


以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。
36

os.mkfifo(path[, mode])


创建命名管道,mode 为数字,默认为 0666 (八进制)
37

os.mknod(filename[, mode=0600, device])
创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。

38

os.open(file, flags[, mode])


打开一个文件,并且设置需要的打开选项,mode参数是可选的
39

os.openpty()


打开一个新的伪终端对。返回 pty 和 tty的文件描述符。
40

os.pathconf(path, name)


返回相关文件的系统配置信息。
41

os.pipe()


创建一个管道. 返回一对文件描述符(r, w) 分别为读和写
42

os.popen(command[, mode[, bufsize]])


从一个 command 打开一个管道
43

os.read(fd, n)


从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。
44

os.readlink(path)


返回软链接所指向的文件
45

os.remove(path)


删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。
46

os.removedirs(path)


递归删除目录。
47

os.rename(src, dst)


重命名文件或目录,从 src 到 dst
48

os.renames(old, new)


递归地对目录进行更名,也可以对文件进行更名。
49

os.rmdir(path)


删除path指定的空目录,如果目录非空,则抛出一个OSError异常。
50

os.stat(path)


获取path指定的路径的信息,功能等同于C API中的stat()系统调用。
51

os.stat_float_times([newvalue])
决定stat_result是否以float对象显示时间戳

52

os.statvfs(path)


获取指定路径的文件系统统计信息
53

os.symlink(src, dst)


创建一个软链接
54

os.tcgetpgrp(fd)


返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组
55

os.tcsetpgrp(fd, pg)


设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。
56

os.tempnam([dir[, prefix]])


Python3 中已删除。返回唯一的路径名用于创建临时文件。
57

os.tmpfile()


Python3 中已删除。返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。
58

os.tmpnam()


Python3 中已删除。为创建一个临时文件返回一个唯一的路径
59

os.ttyname(fd)


返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。
60

os.unlink(path)


删除文件路径
61

os.utime(path, times)


返回指定的path文件的访问和修改的时间。
62

os.walk(top[, topdown=True[, οnerrοr=None[, followlinks=False]]])


输出在文件夹中的文件名通过在树中游走,向上或者向下。
63

os.write(fd, str)


写入字符串到文件描述符 fd中. 返回实际写入的字符串长度
64

os.path 模块


获取文件的属性信息。
65

os.pardir()


获取当前目录的父目录,以字符串形式显示目录名。
66

os.replace()


重命名文件或目录。
67

os.startfile()


用于在 Windows 上打开一个文件或文件夹。

面向对象编程思想

1.概念:

面向对象编程(Object-Oriented Programming,OOP) 是一种以对象为核心的编程范式,通过将数据(属性)与操作数据的方法(行为)封装为独立的单元(即对象)来组织代码。其核心思想是模拟现实世界的实体与交互,提升代码的可复用性、可维护性和扩展性。

2.核心特性

封装(Encapsulation)
将数据与操作数据的方法绑定在一个类中,隐藏内部实现细节,仅暴露必要接口。外部只能通过定义的接口与对象交互,避免直接修改内部状态。例如:

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # 私有属性
    
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
    
    def get_balance(self):
        return self.__balance  # 通过方法访问私有属性
 

继承(Inheritance)
允许子类继承父类的属性和方法,实现代码复用和层次化设计。子类可扩展或覆盖父类功能。例如:

class Animal {  // 父类
    void eat() { System.out.println("Eating..."); }
}
class Dog extends Animal {  // 子类
    void bark() { System.out.println("Barking..."); }
}
 

多态(Polymorphism)
同一操作作用于不同对象时可能产生不同行为。通过方法重写(Override)或接口实现达成。例如:

class Bird:
    def fly(self):
        print("Some birds can fly.")

class Penguin(Bird):
    def fly(self):
        print("Penguins cannot fly.")  # 重写父类方法
 

关键概念

类(Class)与对象(Object)

  • 是对象的模板,定义属性和方法。
  • 对象是类的实例,拥有具体的属性和行为。
class Car {
    constructor(brand) {
        this.brand = brand;  // 属性
    }
    drive() {  // 方法
        console.log("Driving " + this.brand);
    }
}
const myCar = new Car("Toyota");  // 创建对象
 
1.对象的概念

对象,object,现实业务逻辑的一个动作实体就对应着 OOP 编程中的一个对象!

所以:01.对象使用属性(property)保存数据!

           02.对象使用方法(method)管理数据!

2.类的概念

对象如何产生?又是如何规定对象的属性和方法呢? 答:在 Python 中,采用(class)来生产对象,用类来规定对象的属性和方法!也就是说,在 Python 中,要想得到对象,必须先有类!

为什么要引入类的概念?类本来就是对现实世界的一种模拟,在现实生活中,任何一个实体都有一个类别,类就是具有相同或相似属性和动作的一组实体的集合!所以,在 Python 中,对象是指现实中的一个具体的实体,而既然现实中的实体都有一个类别,所以,OOP 中的对象也都应该有一个类! 

 一个对象的所有应该具有特征特性信息,都是由其所属的类来决定的,但是每个对象又可以具有不同的特征特性信息,比如,我自己(人类)这个对象,名字叫老王,性别男,会写代码,会教书;另一个对象(人类)可能叫赵薇,性别女,会演戏,会唱歌!

3.类的定义

类分为:经典类和新式类

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

class类名:
     代码
     ...

新式类:

class 类名():
      代码
      ...

这就是一个类,只不过里面什么都没有!其中,类名不区分大小写,遵守一般的标识符的命名规则(以字母、数字和下划线构成,并且不能以数字开头),一般为了和方法名相区分,类名的首字母一般大写!(大驼峰法)

4.类的实例化(创建对象)

类的实例化就是通过类得到对象!

类只是对象的一种规范,类本身基本上什么都做不了,必须利用类得到对象,这个过程就叫作类的实例化!

基本语法:

对象名 = 类名()

案例:实例化Person类,生成p1对象

#创建对象

p1 = Person()

#p1对象调用实例方法
p1.eat()
5.添加和获取对象属性
概念:

属性即是特征,比如:人的姓名、年龄、身高、体重...都是对象的属性。

对象属性既可以在类外面添加和获取,也能在类里面添加和获取。

类外部添加对象属性

基本语法:

对象名.属性名 = 值

快速入门:

p1.name = '老王'
p1.age = 18
class Person:
    pass

# 创建对象
person = Person()

# 添加属性
person.name = "Alice"
person.age = 25
 
获取对象属性

可以通过点运算符(.)直接访问对象的属性。如果属性不存在,会引发AttributeError异常。

print(person.name)  # 输出: Alice
print(person.age)   # 输出: 25
 
使用getattr()setattr()

Python提供了内置函数getattr()setattr()来动态获取和设置对象属性。

# 使用setattr添加属性
setattr(person, "gender", "Female")

# 使用getattr获取属性
gender = getattr(person, "gender")
print(gender)  # 输出: Female
 
处理不存在的属性

getattr()可以设置默认值,当属性不存在时返回默认值,避免抛出异常。

address = getattr(person, "address", "Unknown")
print(address)  # 输出: Unknown
 
检查属性是否存在

使用hasattr()函数可以检查对象是否具有某个属性。

if hasattr(person, "name"):
    print("Name attribute exists")
 
动态

通过__dict__属性可以查看对象的所有动态属性。

print(person.__dict__)  # 输出: {'name': 'Alice', 'age': 25, 'gender': 'Female'}
 

抽象(Abstraction)
提取关键特征而忽略非必要细节,通过抽象类或接口定义规范。例如:

abstract class Shape {
    abstract double area();  // 抽象方法
}
class Circle extends Shape {
    double area() { return Math.PI * radius * radius; }  // 实现细节
}
 

3.魔术方法

1.概念:

_ _ name_ _,_ _file_ _这些都是魔术变量(拥有特殊功能的变量) 

在python中,_ _xxx_ _()函数叫做魔法方法,指的是具有特殊功能的函数。

2._ _init_ _()方法(初始化方法或构造方法)

思考:人的姓名、年龄等信息都是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?

答:可以,使用__init__()方法,其作用:实例化对象时,连带其中的参数,会一并传给__init__函数自动并执行它。__init__()函数的参数列表会在开头多出一项,它永远指代新建的那个实例对象,Python 语法要求这个参数必须要有,名称为 self。

self 的核心作用

self__init__的第一个固定参数,不需要手动传参,Python 会自动把刚创建出来的实例对象本身赋值给它;

通过self.属性名 = 传入参数,就能把数据绑定到当前对象上,让对象拥有专属属性。

代码实操示例
#1.定义一个类
class Person():
     #初始化实例对象属性
    def __init__(self,name,age):
    #赋予name属性、age属性给实例化对象本身
    #self.实例化对象属性 = 参数
    self.name = name
    self.age = age
#2.实例化对象并传入初始化属性值
p1 = Person('孙悟空',500)
#3.调用p1对象自身属性name,age
print(p1.name)
print(p1.age)
3._ _str_ _()方法

当使用 print 输出对象的时候,默认打印对象的内存地址。如果类定义了__str__方法,那么就会打印从在这个方法中 return 的数据。(另外要特别注意__str__方法返回字符串类型的数据)

使用__str__()方法的类:

# 1、定义一个类
class Car():
    # 首先定义一个__init__方法,用于初始化实例对象属性
    def __init__(self, brand, model, color):
        self.brand = brand
        self.model = model
        self.color = color

    # 定义一个__str__内置魔术方法,用于输出小汽车的相关信息
    def __str__(self):
        return f'汽车品牌:{self.brand},汽车型号:{self.model},汽车颜色:{self.color}'

# 2、实例化对象c1
c1 = Car('奔驰', 'S600', '黑色')
print(c1)
1. __str__魔术方法的作用
  • 不定义__str__:执行print(对象)时,只会输出类似<__main__.Car object at 0xxxxxxx>的内存地址信息,可读性很差;
  • 定义__str__后:打印对象时,会自动读取该方法return的字符串作为输出内容,用来展示对象的业务信息。
2. 硬性语法要求
  • __str__必须 return 字符串,不能返回数字、列表等其他数据类型,否则程序会直接报错;
  • 方法第一个参数固定为self,代表当前实例对象。
3. 这段代码的运行结果

执行print(c1),控制台输出: 汽车品牌:奔驰,汽车型号:S600,汽车颜色:黑色

4. 补充区分
  • __str__:面向用户,输出友好可读的对象描述;
  • 还有一个__repr__魔术方法,偏向开发者调试场景,二者用法相近。
4._ _del_ _()方法(删除方法或析构函数)

__init__方法与__del__方法是一对 当删除对象时(调用 del 删除对象或文件执行结束后),python 解释器也会默认调用__del__()方法。

class Person():
    # 构造函数__init__
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 析构方法__del__
    def __del__(self):
        print(f'{self}对象已经被删除')

# 实例化对象
p1 = Person('白骨精', 100)
# 删除对象p1
del p1

__del__()方法在使用过程中,比较简单,但是其在实际开发中,有何作用呢? 答:主要用于关闭文件操作、关闭数据库连接等等。

构造方法与析构方法配对关系
  • __init__构造方法,对象创建(实例化)时自动执行,负责初始化对象属性;
  • __del__析构方法,对象被销毁时自动执行,和__init__生命周期首尾对应。
 对象触发__del__的两种场景
  1. 手动执行del 对象名,主动销毁对象;
  2. 程序代码全部执行完毕,Python 垃圾回收机制自动清理该对象,自动调用__del__
 实际开发用途

__del__主要做资源收尾释放工作:

  • 关闭已经打开的文件句柄
  • 断开数据库连接、Redis 连接
  • 释放网络 socket 端口、释放占用的硬件资源 避免程序结束后资源一直被占用。
 补充注意点
  • Python 存在引用计数机制,只有当对象引用计数归零时,才会触发__del__;如果对象还被其他变量引用,即便执行一次del也不会立刻执行析构方法;
  • 不建议在__del__中写复杂业务逻辑,仅用来做资源释放即可。
总结:

提到魔术方法:① 这个方法在什么情况下被触发 ② 这个方法有什么实际的作用

__init__():初始化方法或者称之为 “构造函数”,在对象初始化时执行,其主要作用就是在对象初始化时,对对象进行初始化操作(如赋予属性)

__str__():对象字符串方法,当我们在类的外部,使用 print 方法输出对象时被触发,其主要功能就是对对象进行打印输出操作,要求方法必须使用 return 返回字符串格式的数据。

__del__():删除方法或者称之为 “析构方法”,在对象被删除时触发(调用 del 删除对象或文件执行结束后),其主要作用就是适用于关闭文件、关闭数据库连接等等。

魔术方法触发时机核心作用强制要求
__init__通过类实例化创建新对象时自动执行给对象绑定初始化属性、做创建时的初始化配置第一个参数必须为self
__str__执行print(对象)str(对象)时自动执行自定义对象打印的可读文本,替代默认内存地址输出return返回值必须是字符串
__del__对象引用计数归零(手动del删除 / 程序运行结束垃圾回收)时执行释放资源:关闭文件、数据库连接、网络连接等无返回值要求

生命周期:

  • 对象诞生:执行对象 = 类名(参数) → 自动调用__init__完成初始化
  • 对象打印:执行print(对象) → 自动调用__str__输出自定义描述
  • 对象销毁:对象不再被引用 / 程序结束 → 自动调用__del__释放占用的系统资源

4.面向对象的综合案例

案例1:

定义学员信息类,包含姓名、成绩属性,定义成绩打印方法(90分及以上显示优秀,80分及以上显示良好,70分及以上显示中等,60分及以上显示合格,60分以下显示不及格

学员对象(属性、方法)

'''案例1:定义学员信息类,包含姓名、成绩属性,定义成绩打印方法(90分及以上显示优秀,
80分及以上显示良好,70分及以上显示中等,60分及以上显示合格,60分以下显示不及格'''
class Student(object):
    #定义魔术方法,用于初始化对象属性
    def __init__(self, name, age, score):
        # 定义属性
        self.name = name
        self.age = age
        self.score = score
    #定义方法:用于打印学生的成绩信息
    def print_grade(self):
        if self.score >= 90:
            print(f'学生姓名:{self.name},成绩:{self.score},等级:优秀')
        elif self.score >= 80:
            print(f'学生姓名:{self.name},成绩:{self.score},等级:良好')
        elif self.score >= 70:
            print(f'学生姓名:{self.name},成绩:{self.score},等级:中等')
        elif self.score >= 60:
            print(f'学生姓名:{self.name},成绩:{self.score},等级:及格')
        else:
            print(f'学生姓名:{self.name},成绩:{self.score},等级:不及格')

#实例化对象
s1 = Student('小米',25,80)
s1.print_grade()

输出结果:

案例二:

案例 2:小明体重 75.0 公斤,小明每次跑步会减掉 0.50 公斤,小明每次吃东西体重增加 1 公斤。

分析:① 对象:小明 ② 属性:姓名、体重 ③ 方法:跑步、吃东西

class Person:
    # 初始化属性:姓名、初始体重
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    # 跑步方法:体重减少0.5
    def run(self):
        self.weight -= 0.5

    # 吃东西方法:体重增加1
    def eat(self):
        self.weight += 1

    # 自定义打印对象信息
    def __str__(self):
        return f"姓名:{self.name},当前体重:{self.weight}公斤"

# 实例化小明对象
xiaoming = Person("小明", 75.0)
print(xiaoming)

# 调用行为方法
xiaoming.run()
print("跑步一次后:", xiaoming)

xiaoming.eat()
print("吃东西一次后:", xiaoming)

输出结果:

5.面向对象的三大特征

面向对象有哪些特性

三种:封装性、继承性、多态性

python中的封装

在python代码中,封装有两层含义:

1.把现实世界中的主体中的属性和方法书写到类的里面的操作即为封装

class Peron():
   #封装属性
   #封装方法

2.封装可以为属性和方法添加私有权限

封装中的私有属性和私有方法

在面向对象代码中,我们可以把属性和方法分为两大类:公有(属性、方法)、私有(属性、方法)

公有属性和公有方法:无论在类的内部还是在类的外部我们都可以对属性和方法进行操作。

但是有些情况下,我们不希望在类的外部对类内部的属性和方法进行操作。我们就可以把这个属性或方法封装成私有形式。

私有属性的访问限制

设置私有属性和私有方法的方式非常简单:在属性名和方法名前面家伙是那个两个下划线_ _即可

基本语法:

class Girl():
    def __init__(self,name,age,score):
        self.name = name
        self.__age = age

xiaomi = Girl('xiaomi',21,25)
print(xiaomi.name)
print(xiaomi.__age) #报错,提示Girl对象没有_ _age属性

输出结果:

类中的私有属性和方法,不能被其子类继承

由以上代码运行可知,私有属性不能在类的外部被直接访问。但是出于种种原因,我们想在外部对私有属性进行访问,该如何操作呢?

答:我们可以定义一个统一的访问 "接口"(函数),专门用于实现私有属性的访问。

私有属性设置与访问''接口''

接口就是我们通常说的一个函数,这个函数可以实现对某些属性的访问(设置与获取) 外部可以通过特定的 "接口" 来实现对私有属性的方法。

name

__salary

    # 这个函数并不是针对所有用户开放,只会针对特定的用户(角色验证)

   管理员:root

   普通用户: lgw
def get_salary(self):
    访问私有属性

在 Python 中,一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值。

class Girl:
    def __init__(self,name,age):
        self.name=name
        self.__age=age
    # 公共方法:提供给外部的设置接口
    def set_age(self,new_age):
        self.__age=new_age

     #公共方法:提供给外部的访问接口
    def get_age(self):
        #内部访问:允许直接访问
        #外部访问:根据需求要添加限制条件
        return self.__age
gril = Girl("小美",19)
gril.set_age(20)
print(gril.get_age())

输出结果:

私有方法

私有方法的定义方式与私有属性基本一致,在方法名的前面添加两个下划线 _ _方法名()

封装性到底有何意义

1.以面向对象的编程思想进行项目开发

2.封装数据属性:明确的区分内外,控制外部对隐藏的属性的操作行为(过滤掉异常数据)

案例:数据泄露

class Girl:
    def __init__(self,name,):
        self.name=name
        #声明一个公有属性
        self.salary=18000


#实例化对象
xm1 = Girl('小美')
print(xm1.salary)
xm1.salary=20000
#财务发工资,调用salary获取工资信息
print(xm1.salary)

私有化解决:

class Girl:
    def __init__(self,name,):
        self.name=name
        #声明工资信息为私有属性
        self.__salary=18000 #公共接口 => set_xxx、get_xxx
    #定义一个set_salary
    def set_salary(self,new_salary):
        #经过角色验证,如果有工资的操作权限,才能让其继续操作(权限验证)
        #如果权限验证通过,则继续执行
        if 50000 > new_salary > 0 :
            self.__salary=new_salary
        else:
            print('错误')
    #定义一个get
    def get_salary(self):
        # 经过角色验证,如果有工资的操作权限,才能让其继续操作(权限验证)
        # 如果权限验证通过,则继续执行
        print(self.__salary)
#实例化对象
xm1 = Girl('小美')

#操作工资信息时,首先要登陆系统,初始化一个角色
xm1.salary=20000
#财务发工资,调用salary获取工资信息
print(xm1.salary)

3.私有方法封装的意义:降低程序的复杂度



class ATM():
    def __card(self):
        print('插卡')
    def __auth(self):
        print('用户认证')
    def __input(self):
        print('输入取款金额')
    def __print_bill(self):
        print('打印账单')
    def __take_money(self):
        print('取款')

    # 定义一个对外提供服务的公共方法
    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()

atm = ATM()
atm.withdraw()

输出结果:

3.设计原则

单一职责原则(SRP)
一个类应仅有一个引起变化的原因,即功能单一化。

开闭原则(OCP)
对扩展开放,对修改关闭,通过继承或组合扩展功能。

依赖倒置原则(DIP)
高层模块不应依赖低层模块,二者应依赖抽象。

4.应用场景

  • 复杂系统模块化设计(如GUI框架、游戏开发)。
  • 需要长期维护和迭代的代码库。
  • 团队协作开发,通过接口定义清晰边界。

通过合理运用OOP思想,可以构建高内聚、低耦合的软件系统,有效管理代码复杂度。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐