2022.11.15 本学习内容总结于莫烦python:3.函数、类、模块
https://mofanpy.com/tutorials/python-basic/interactive-python/function
1. Function 函数
我常会重复写一些功能,比如查询文件时间,查询文件名字等等.后续我只需要引用到这个功能,多省事
1.1 定义函数
def modify_name(filename):
filename += ".txt"
filename = "my_" + filename
print(filename)
modify_name("f1")
modify_name("f2")
my_f1.txt
my_f2.txt
实现了服用。这种服用形式也可以没有参数、有返回值:
- 没有参数
def my_func():
filename = "f1"
ext = ".txt"
total_name = filename + ext
print(total_name)
my_func()
f1.txt
- 有返回值
def modify_name(filename):
filename += ".txt"
filename = "my_" + filename
return filename
new_filename = modify_name("f1")
print(new_filename)
my_f1.txt
1.2 参数设置
可以输入,可以有默认;我们在覆盖默认的时候,一定要指明覆盖的哪个默认数据 a=2
def f(x, a=1, b=1, c=0):
return a*x**2 + b*x + c*1
print(f(2, a=2))
print(f(2))
10
6
1.3 全局和局部变量
def modify_name():
filename = "f1.txt"
print("local filename:", filename)
modify_name()
print("global filename:", filename) # 这里会报错
这里会报错:因为filename
外面看不见,是个局部变量;
- 解决方法一:把变量移到函数外面,变全局变量
filename = "f1.txt"
def modify_name():
print("local filename:", filename)
modify_name()
print("global filename:", filename)
- 解决方法二:用
global
,变全局变量
filename = "f1.txt"
def modify_name():
global filename # 提出申请
filename = "f2.txt"
print("local filename:", filename)
modify_name()
print("global filename:", filename)
【实例演示:汉罗塔次数实现】:https://blog.csdn.net/wistonty11/article/details/123563309
【羊老羊讲解】我们既要实现time
函数外初始化,又要实现在里面结算后带出来结果,所以将time
用global
写成了全局变量。
time = 0
def hanoi(A, B, C, n):
global time
if n == 1:
print(A, '->', C)
time += 1
else:
hanoi(A,C,B,n-1)
print(A, '->', C)
time += 1
hanoi(B,A,C,n-1)
hanoi('A','B','C',4)
print(time)
2 class 类
2.1 定义Class
只要我们有了函数之后,作为一个程序语言,也不缺啥了, 那为什么还要搞一个 类Class 出来呢?永远记住,搞出这个东西来,永远都只有一个目的,就是让用语言觉得更省事, 更方便地处理一些具体问题。
就是工程师们想要在程序中描述具体的一个物体了。 比如一只猫有哪些特征,它能做哪些动作。 工程师想出了一个在代码中设置猫所有特征和动作的办法, 这就有了 class 类的概念
class File:
def __init__(self):
self.name = "f1"
self.create_time = "today"
my_file = File()
print(my_file.name)
print(my_file.create_time)
f1
today
-
把类给实例化的时候,
File
类都会触发一次__init__
功能,所以这是一个功能,用于初始化一些设置。 -
也可以修改属性值
my_file.name = "new_name"
print(my_file.name)
new_name
【羊老羊讲解】这里my_file
是个实例,调用的时候就初始化File()
, 我们需要注意,引用的方式:实例名.属性。
eg:my_file.name = “new_name”
2.2 class 功能
- 可以像函数功能来使用。比如在 init() 里加上传入参数。
class File:
def __init__(self, name, create_time="today"):
self.name = name
self.create_time = create_time
my_file = File("my_file")
print(my_file.name)
print(my_file.create_time)
my_file
today
my_file = File("my_file")
中my_file
就是初始化类中唯一没有默认的name
- 返回值
class File:
def __init__(self, name, create_time="today"):
self.name = name
self.create_time = create_time
def get_info(self):
return self.name + "is created at " + self.create_time
my_file = File("my_file")
print(my_file.get_info())
my_fileis created at today
2.3 继承
当两个文件,有共性时,可以写一起。继承方式 :class 类二名(类一名)
class File:
def __init__(self, name, create_time="today"):
self.name = name
self.create_time = create_time
def get_info(self):
return self.name + "is created at" + self.create_time
class Video(File): # 继承了 File 的属性和功能
def __init__(self, name, window_size=(1080, 720)):
# 将共用属性的设置导入 File 父类
super().__init__(name=name, create_time="today")
self.window_size = window_size
class Text(File): # 继承了 File 的属性和功能
def __init__(self, name, language="zh-cn"):
# 将共用属性的设置导入 File 父类
super().__init__(name=name, create_time="today")
self.language = language
# 也可以在子类里复用父类功能
def get_more_info(self):
return self.get_info() + ", using language of " + self.language
如果子类B和父类A,都写了init方法,那么A的init方法就会被B覆盖。
想调用A的init方法需要用super去调用super().__init__(name=name, create_time="today")
v = Video("my_video")
t = Text("my_text")
print(v.get_info()) # 调用父类的功能
print(t.create_time) # 调用父类的属性
print(t.language) # 调用自己的属性
print(t.get_more_info()) # 调用自己加工父类的功能
my_videois created attoday
today
zh-cn
my_textis created attoday, using language of zh-cn
2.4 私有属性和功能
- _ 一个下划线开头:弱隐藏 不想让别人用 (别人在必要情况下还是可以用的)
- __ 两个下划线开头:强隐藏 不让别人用
class File:
def __init__(self):
self.name = "f1"
self.__deleted = False # 我不让别人用这个变量
self._type = "txt" # 我不想别人使用这个变量
def delete(self):
self.__force_delete()
def __force_delete(self): # 我不让别人使用这个功能
self.__deleted = True
return True
def _soft_delete(self): # 我不想让别人使用这个功能
self.__force_delete() # 我自己可以在内部随便调用
return True
f = File()
print(f._type) # 可以拿到值,但是这个类的作者不想让你直接这样拿到
print(f._soft_delete()) # 可以调用,但是这个类的作者不想让你直接调用
# 接下来的两个实验都会报错
# f.__deleted
# f.__force_delete()
2.5 特殊方法
3. Module 模块
如果一个文件写所有的代码可能成千上万行,阅读起来一点也不友善, 所以我们更长是将大项目的长代码拆开成多个模块Module 模块
file.py
文件中的代码
# file.py
def create_name():
return "new_file.txt"
3.1 引用 module
me.py
引用file.py
文件中的create_name()
# me.py
import file
print(file.create_name())
这里需要注意,我们引入文件file
,但里面是什么不知道,所以引用时:文件名.函数名:file.create_name()
- 引入这个函数时,就不需要加文件名了
create_name()
(已经知道在哪了)
#导入file所有文件
from file import *
print("2", create_name())
# 引入文件下莫某个函数
from file import create_name
print(create_name())
- 同时引入模块下多个函数
# me.py
from file import create_name, create_time
- 别名
# me.py
import file as f1
3.2 大项目的模块管理
在稍微大点的项目中,随着代码量增加,代码管理起来越来越困难。可以做个文件系统
# files/__init__.py
from .video import get_video_size # 点运行会报错的
正规的 module 中,我们常会看到一个 __init__.py
文件,这个文件其实就有点像 class 里的 def init(self), 你可以在里面写上要如何初始化你的 files 目录。也可以设定目录中个元素的关系。
-
【知识点】这里是相对路径
.video
在模块
A.B.C
中的代码,这里的C
就相当于__init__.py
;B
就相当于file
from . import D # 导入A.B.D
from … import E # 导入A.E
from …F import G # 导入A.F.G,… 和 F是连着的,中间没有空格from .video import get_video_size
就是file
文件夹内的video
中引入get_video_size()
-
这里导入文件的时候,初始化试将
get_video_size
# me.py
from files import get_video_size
print(get_video_size())
虽然不知道 files/video.py
里面什么内容,然在file初始化的时候 ,已经有了函数get_video_size()
,就可以用了
# me.py
from files import create_name # 这里会报错,因为file初始化的时候 不知道creat_name
这里会报错,因为file初始化的时候 不知道creat_name
在哪,不能直接引入函数名,应该导入的是可以看见的文件名,如下:
- 如果我们要获取到 text.py 的功能,我们得这样 import:
# me.py
import files.text
print(files.text.create_name())
# 或者这样:
from files import text
print(text.create_name())
导入文件名text
,引用的时候用text.create_name()