快捷目录
- 简介
- Python安装
- IDE
- 注释
- 单行注释
- 类注释
- 方法注释
- 基本数据类型
- 字符串
- 创建字符串
- 字符串查找
- 字符串长度
- 索引
- 特定字符串
- 判断某字符串是否在该字符串里
- 计算子字符串在字符串中出现的次数
- 字符串操作
- 删除某特定尾字符
- 字符串类型转换
- 字符串类型转换为其他类型
- 其他类型转换成字符串类型
- 正则表达式
- 引入模块
- match
- search
- sub
- 变量
- 私有变量
- 变量赋值
- 类变量
- 局部变量
- 全局变量
- 实例变量
- 删除变量
- 面向对象
- 类
- 创建类
- 构造方法
- 类的方法
- 实例化对象
- 访问属性
- 包
- 引用类
- from .... import ....
- import ....
- 继承
- 调用
- 重写父类方法
- 继承实现接口
- 反射
- 判断属性或方法是否存在
- 添加/设置属性
- 获取属性或方法
- 删除属性或方法
- 文件操作
- Open
- with关键字
- close
- read
- readline
- readlines
- write
- OS
- 引入
- 删除文件
- 判断是否存在该文件
- 创建文件夹
- 获取某文件的绝对路径
- 检索目录下的文件
- 改变当前工作目录到指定的路径
- shutil
- 引入
- 移动文件
- 复制文件
- 相对路径解决办法
- 默认
- 动态获取绝对路径
- 动态切换当前工作目录
简介
Python 是一种解释型、面向对象、动态数据类型的高级程序设计语言。Python 由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。像 Perl 语言一样, Python 源代码同样遵循 GPL(GNU General Public License) 协议。
官方宣布,2020 年 1 月 1 日, 停止 Python 2 的更新。Python 2.7 被确定为最后一个 Python 2.x 版本。
笔者使用的是python3.8,该博文并不适合完全零基础的读者,并且不会将所有的python基础全部展示出来,该博客旨在解决一些python的关键用法,python零基础请移步以下网址:
Python安装
安装python有两种方式
- 直接安装python环境,网址:Download Python | Python.org
- 安装conda环境,搭建虚拟python环境,推荐这个办法搭建python环境,可使用不同python环境进行编程,具体搜笔者的另外一个博客,Anaconda
IDE
- pycharm(笔者正在使用的ide)
- vscode
注释
- 注释不是越多越好。对于一目了然的代码,不需要添加注释。
- 对于复杂的操作,应该在操作开始前写上相应的注释。
- 对于不是一目了然的代码,应该在代码之后添加注释。
- 绝对不要描述代码。一般阅读代码的人都了解Python的语法,只是不知道代码要干什么
单行注释
描述某个变量(某行代码)的作用
第一种写法:
# 注释
ui = 1
第二种写法:
ui = 1 # 注释
突出某段代码的重要性
# ==================
# 请勿删除该变量!!!!
# ==================
ui = 1
类注释
描述某个类的作用
格式如下:
"""类用处"""
使用实例:
class test:
"""类用处"""
pass
方法注释
描述某个方法的作用
DocStrings 文档字符串使用惯例:它的首行简述函数功能,第二行空行,第三行为函数的具体描述。
格式如下(reST风格):
"""
方法的用处
:param parm: 形参的用处
:return: 返回的数据
"""
这是现在流行的一种风格,reST风格,Sphinx的御用格式,比较紧凑。
- param为说明传入的形参
- return为说明返回的数据
使用实例:
def test(self,parm01,parm02):
"""
方法的用处
:param parm01: 形参的用处01
:param parm02: 形参的用处02
:return: 返回的数据
"""
pass
基本数据类型
Python3 中有六个标准的数据类型:
- Number(数字)
- String(字符串)
- List(列表)
- Tuple(元组)
- Set(集合)
- Dictionary(字典)
Python3 的六个标准数据类型中:
- **不可变数据(3 个):**Number(数字)、String(字符串)、Tuple(元组);
- **可变数据(3 个):**List(列表)、Dictionary(字典)、Set(集合)。
字符串
创建字符串
字符串是 Python 中最常用的数据类型。我们可以使用引号('
或"
)来创建字符串。
创建字符串很简单,只要为变量分配一个值即可。例如:
String1 = 'Hello World!'
String2 = "Hello python"
字符串查找
字符串长度
调用len
,该方法不仅仅用在字符串,也可以统计列表,元组的长度
name = "helloworld"
len(name)
索引
对标java的indexOf(int ch,int fromindex)
,索引是通过字符串下标返回该下标的字符
str[0:1]
其中str为变量,0是头下标,1是尾下标
特定字符串
调用find函数,返回首字母在匹配字符串的下标
name.find("World")
判断某字符串是否在该字符串里
用in
关键字,若存在则返回True
name = "helloworld"
print("world" in name)
计算子字符串在字符串中出现的次数
调用count
方法
name = "helloworld"
count = name.count("l",0,len(name))
print(count)
字符串操作
删除某特定尾字符
调用rstrip
,如果方法不传参则默认删除空格符
name = "helloworld;"
print(name)
count = name.rstrip(';')
print(count)
字符串类型转换
字符串类型转换为其他类型
int类型(整数类型)
str = '1'
int(str)
str = 'a'
int(str) # 强转
float类型(浮点类型)
str = '0.05'
float(str)
这里提一下浮点类型的四舍五入,可以调用round函数计算
number = 5.454245435
round(number,3)
number为传入的浮点类型,3位保留3位数
其他类型转换成字符串类型
number = 1
str(number)
正则表达式
正则表达式是一个特殊的字符序列,它能帮助人们方便的检查一个字符串是否与某种模式匹配。
可用RegExr: 学习、构建 和 测试 正则表达式 Test RegEx (regexr-cn.com)生成正则表达式
引入模块
import re
match
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none
re.match(pattern, string, flags=0)
形参作用如下(按传入顺序):
- pattern:匹配的正则表达式
- string:要匹配的字符串
- flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re
name = "helloworld"
matcher = re.match("hello",name)
print(matcher)
匹配完成后,可用span
方法在起始位置匹配
matcher.span()
search
扫描整个字符串并返回第一个成功的匹配
re.search(pattern, string, flags=0)
形参作用如下(按传入顺序):
- pattern:匹配的正则表达式
- string:要匹配的字符串
- flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re
name = "helloworld"
matcher = re.search("hello",name)
print(matcher)
匹配完成后,可用group
方法在返回匹配的字
matcher.group()
sub
替换字符串中的匹配项
re.sub(pattern, repl, string, count=0, flags=0)
形参作用如下(按传入顺序):
- pattern:匹配的正则表达式
- repl : 替换的字符串,也可以是一个函数
- string:要匹配的字符串
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配
- flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re
name = "helloworld"
print(name)
name = re.sub("hello","bello",name)
print(name)
变量
私有变量
不与其他共享,自己独享,如函数和方法的局部变量,实例变量
写的时候,在变量左边加两个下斜杆(_)即可
例如:
__a = 1
__b = "1"
变量赋值
单个变量赋值
i = 1000 # int型
j = 1000.0 # float型
name = "tom" # 字符串型
print(i)
print(j)
print(name)
多个变量赋值
- 给多个变量同时赋值,变量的值相同:
a = b = c = 1
- 为多个变量指定多个值:
a, b, c = 1, 2, "tom"
类变量
class内,不在class的任何方法内,使用类变量时,将类实例化后调用
class test:
a = "123"
__b = 1
def test01(self):
print(self.a) # 方法调用类变量
@classmethod
def test02(cls):
print(cls.__b) # 静态方法调用类变量
局部变量
函数内、class的方法(类方法、静态方法、实例方法)内,且变量前面没有修饰
def test01(self):
a = 1 # 局部变量
全局变量
全局变量供全局共享,全局类和函数均可访问,达到同步作用。同时还可以被外部文件访问。
全局变量使用的时候,需要用global显示声明。
一般情况下,如果函数直接调用全局变量,不做更新的话,一般没有问题,但如果有重新赋值,又没有在函数内部使用 global声明的话, 就相当于在内部创建了一个同名的局部变量,局部变量优先级要高于全局变量。
def myfunc():
global x
x = "fantastic"
实例变量
class的构造方法内,使用self修饰
def __init__(self):
self.a = 1 # 实力变量
删除变量
调用del
,可删除变量
name = "helloworld"
print(name)
del(name)
print(name)
面向对象
类
用来描述具有相同的属性和方法的对象的集合。
创建类
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾:
class Test01:
"""创建类"""
a = "1" # 类变量
构造方法
当创建了这个类的实例时就会调用该方法
def __init__(self):
pass
类的方法
类方法
def test01(self):
pass
私有方法
def __test01(self):
pass
抽象方法(不需要实例化对象直接调用,像调用类变量,例如:Test01.test01()
)
@classmethod
def test01(cls):
pass
实例化对象
实例化类其他编程语言中一般用关键字 new,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式。
test01 = Test01() # 创建一个名为test01对象
test02 = Test01() # 创建一个名为test02对象
访问属性
访问方法
test01.test01() # 调用类方法
调用类变量
test01.a
包
在模块中,有一个__init__.py
的文件,这个文件说明该文件夹为一个包,该文件夹的名字为包名
__init__.py
可以指定某个包下导入的类,例如,在Utils
包中的__init__
文件写入:
from .DataTimeUtils import DataTimeUtils
from .YAMLReader import YAMLReader
__all__ = ["DataTimeUtils",
"YAMLReader",]
在其他类中导入时使用from Utils import *
即可导入__init__
文件中指定的所有类
from Utils import *
print(DataTimeUtils.getDay(0))
也可以指定某一个特定的类
from Utils import DataTimeUtils
print(DataTimeUtils.getDay(0))
该办法可以让导入更加容易,并且一定程度封闭该包下的类,但是该方法实测过会损耗性能
__init__.py
默认不写时,可导入该包下的类,用from Utils.DataTimeUtils import DataTimeUtils
即可
引用类
from … import …
引用类时,使用from Test.Test02 import Test02
,具体是from 包名.类名 import 类名
,调用时,直接实例化即可,例:
from Utils.DataTimeUtils import DataTimeUtils
dtu = DataTimeUtils()
dtu.getDay(0)
当一个py文件中没有类时(面向过程编程),使用from Test.Test02 import function
,具体是from 包名.py文件名 import 方法名
,想要使用该方法时,直接调用即可,例:
from Test.Test02 import function
function()
import …
引用类时,使用import Utils.DataTimeUtils
,具体是import 包名.模块名(py文件名)
,调用时,需要完整写出包名.模块名.类名()
去实例化一个类,例:
import Utils.DataTimeUtils
dtu = Utils.DataTimeUtils.DataTimeUtils()
day = dtu.getDay(0)
当一个py文件中没有类时(面向过程编程),使用import Test02
,具体是import 包名.模块名(py文件名)
,想要使用该模块中的方法时,使用模块名.方法名()
即可调用该方法,例:
import Test02
Test02.function()
继承
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
语法:
class base:
"""父类"""
pass
class Test01(base):
"""子类"""
pass
一个类可以继承多个类,称为多继承,使用时尽量单继承
语法:
class base01:
"""父类1"""
pass
class base02:
"""父类2"""
pass
class Test01(base01,base02):
"""子类"""
pass
调用
子类可以调用父类的方法与类变量,并且可以调用祖先(父类的父类)的方法与类变量
class base:
a = "1"
def base_test01(self):
print("test")
class Test01(base):
def test01(self):
print(self.a)
print(self.base_test01())
重写父类方法
子类可以重写父类的方法
class base:
a = "1"
def base_test01(self):
print("test")
class Test01(base):
def base_test01(self):
print("test01")
继承实现接口
在python中,是没有interface
的,实现接口,可以使用abc
模块实现,例
import abc
class base(metaclass = abc.ABCMeta):
@abc.abstractmethod
def base_test01(self):
pass
class Test01(base):
def base_test01(self):
print("test")
@abc.abstractmethod
定义该方法为抽象方法,metaclass = abc.ABCMeta
定义该类为抽象基类
若继承的接口类没有实现base_test01
,则报错:
TypeError: Can't instantiate abstract class Test01 with abstract methods base_test01
在继承抽象类的过程中,应该尽量避免多继承;而在继承接口的时候,反而鼓励多继承接口。
在抽象类中,可以对一些抽象方法做出基础实现;而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现。
反射
反射(Reflection) 允许运行中的 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性和方法。反射的具体作用如下:
- 反射让开发人员可以通过外部类的全路径名创建对象,并使用这些类,实现一些扩展的功能。
- 反射让开发人员可以枚举出类的全部成员,包括构造函数、属性、方法。以帮助开发者写出正确的代码。
- 测试时可以利用反射 API 访问类的私有成员,以保证测试代码覆盖率。
也就是说,利用反射,我们可以获取以下程序:
- Class 对象
- 类中的所有字段
- 类中的所有构造方法
- 类中的所有非构造方法
反射看起来像是破坏了封装性,但是反射是可以作为一个工具,用来帮助程序员实现本不可能实现的功能(perform operations which would otherwise be impossible)。很多程序架构,尤其是三方框架,无法保证自己的封装是完美的。如果没有反射,对于外部类的私有成员,我们将一筹莫展,所以我们有了反射这一后门,为程序设计提供了更大的灵活性。工具本身并没有错,关键在于如何正确地使用。
新建一个类,该类为测试python反射的对象:
class Student:
id = 1
name = "123"
def havePencil(self):
print("He has a pencil")
判断属性或方法是否存在
调用内置函数,返回值为bool(若存在则返回True):
hasattr(object,'attrName')
形参说明:
-
object
:对象,可以是实例化对象 -
attrName
:字符串,用于判断对象是否存在该属性或者方法
例子:
from Student import Student
# student = Student()
has_bool = hasattr(Student,"id") # 是否存在该属性
has_bool = hasattr(Student,"havePencil") # 是否存在该方法
print(has_bool)
添加/设置属性
调用内置函数:
setattr(object,'attrName',value)
形参说明:
-
object
:对象,可以是实例化对象 -
attrName
:字符串,对象的属性 -
value
:对象属性的值
object中,传入的对象是具体的实例化对象,则改变的是该对象的属性,否则会改变整体的对象属性
例子:
from Student import Student
student1 = Student()
student2 = Student()
print(student2.id)
setattr(student2,'id',2) # 改变student2对象中的id属性
print(student2.id)
print(student1.id)
setattr(Student,'id',3) # 改变全部Student对象中的id属性
print(student1.id)
print(student2.id)
获取属性或方法
调用内置函数:
getattr(object,'attrName')
形参说明:
-
object
:对象,可以是实例化对象 -
attrName
:字符串,用于获取该对象的属性或者方法
例子:
from types import FunctionType
from Student import Student
id = getattr(Student, "id") # 获取对象的属性
print(id)
havePencil = getattr(Student, "havePencil") # 获取对象的方法,返回FunctionType类型
print(havePencil(Student())) # 调用时加()并传入对象
print(type(havePencil) is FunctionType)
删除属性或方法
调用内置函数:
delattr(object,'attrName')
形参说明:
-
object
:对象,可以是实例化对象 -
attrName
:字符串,用于删除该对象的属性或者方法
例子:
from Student import Student
student1 = Student()
print(student1.id)
delattr(student2,'id') # 删除student1对象中的id属性
print(student1.id)
文件操作
Open
如果想用python读取文件,第一步要用open函数打开文件。open()是python的内置函数,它会返回一个文件对象,这个文件对象拥有read、readline、write、close等方法。
open函数有两个参数:
open('file','mode')
其中,file为需要打开的文件路径,mode为打开文件的模式,如只读、追加、写入等
mode常用的模式:
- r:表示文件只能读取
- w:表示文件只能写入,若文件不存在会创建一个
- a:表示打开文件,在原有内容的基础上追加内容,在末尾写入
- w+:表示可以对文件进行读写双重操作
mode参数可以省略不填,默认模式为r;mode参数还可以指定以什么样的编码方式读写文本,默认情况下open是以文本形式打开文件的,比如上面的四种mode模式。
当你需要以字节(二进制)形式读写文件时,只需要在mode参数中追加’b’即可:
- rb:以二进制格式打开一个文件,用于只读
- wb:以二进制格式打开一个文件,用于只写
- ab:以二进制格式打开一个文件,用于追加
- wb+:以二进制格式打开一个文件,用于读写
with关键字
在打开文件时,很多人通常直接用open(‘file’)。在文件读写时可以使用 with
关键字。优点是当子句体结束后文件会正确关闭,即使在某个时刻引发了异常。
with open('workfile') as f:
for i in range(0,3):
read_data = f.write("test")
f.closed
close
打开文件并处理完毕后,需要关闭文件,这里用到close方法。
f.close() 用来关闭文件并立即释放它使用的所有系统资源。如果没有显式地关闭文件,Python的垃圾回收器最终将销毁该对象并关闭打开的文件,但这个文件可能会保持打开状态一段时间。
应该要养成使用close()的习惯。使用方法很简单:
f = open(file) # 打开文件
f.close() # 关闭文件
read
当使用open函数打开文件后,就可以使用该文件对象的各种方法了,read就是其中一种。
read()会读取一些数据并将其作为字符串(在文本模式下)或字节对象(在二进制模式下)返回。
read方法有一个参数:
f.read(size) # f为文件对象
参数size(可选)为数字,表示从已打开文件中读取的字节计数,默认情况下为读取全部。
假设有一个文件sample1.txt,内容如下:
This is python big data analysis!
现在读取该文件:
with open('sample1.txt') as f:
content = f.read()
print(content)
f.close()
readline
readline方法从文件中读取整行,包括换行符’\n’。
换行符(\n)留在字符串的末尾,如果文件不以换行符结尾,则在文件的最后一行省略,这使得返回值明确无误。
如果 f.readline() 返回一个空的字符串,则表示已经到达了文件末尾,而空行使用 ‘\n’ 表示,该字符串只包含一个换行符。
f.readline()有一个参数:
f.readline(size)
参数size表示从文件读取的字节数。
假设有一个文件sample2.txt,共三行,内容如下:
hello,my friends!
This is python big data analysis,
let's study.
用readline函数读取该文件:
with open('a.txt') as f:
print(f.readline())
print(f.readline(5))
f.close()
readline方法会记住上一个readline函数读取的位置,接着读取下一行。
readlines
readlines方法和readline方法长得像,但功能不一样,前面说过readline方法只读取一行,readlines方法则是读取所有行,返回的是所有行组成的列表。
readlines方法没有参数,使用更加简单。依旧以sample2.txt为例:
with open('a.txt') as f:
print(f.readlines())
f.close()
write
write方法顾名思义,就是将字符串写入到文件里。
它只有一个参数:
f.write([str]) # f为文件对象
参数[str]代表要写入的字符串
使用起来也很简单,比如将下面字符串(注意里面的转行符’\n’)
'hello,my friends!\nthis is python big data analysis'
写入到文件sample3.txt里。
with open('sample3.txt','w') as f:
f.write('hello,my friends!\nthis is python big data analysis')
f.close()
OS
引入
import os
删除文件
os.remove(path) # path是文件的路径,如果这个路径是一个文件夹,则会抛出OSError的错误,这时需用用rmdir()来删除
os.rmdir(path) # path是文件夹路径,注意文件夹需要时空的才能被删除
os.unlink('F:\新建文本文档.txt') # unlink的功能和remove一样是删除一个文件,但是删除一个删除一个正在使用的文件会报错。
判断是否存在该文件
使用os.path.exists
判断某个文件是否存在
is_exists = os.path.exists("test.png")
print(is_exists)
创建文件夹
os.mkdir('d:\hello') # 在一级目录中创建
os.makedirs('d:\hello\world\123') # 创建多级目录
获取某文件的绝对路径
abs_path = os.path.abspath("test.png") # 返回test.png的绝对路径
py_abs_path = os.path.abspath(os.path.dirname(__file__)) # 返回当前py文件下的绝对路径
print(abs_path)
print(py_abs_path)
检索目录下的文件
path = 'd:\hello'
# 遍历指定目录下所有文件和子文件夹文件
for root,dirs,files in os.walk(path):
print(files)
- root:根目录
- dirs:根目录包含的子文件夹
- files:根目录包含的子文件
改变当前工作目录到指定的路径
os.chdir(path)
shutil
引入
import shutil
移动文件
shutil.move(src = "./test.txt",dst = "./test") # src为源文件,dst为要移动过去的目标文件夹
复制文件
shutil.copy(src="./test/test.txt",dst="./") # src为源文件,dst为要复制过去的目标文件夹
相对路径解决办法
python操作文件的时候,相对路径是把运行的当前的.py文件作为基准的
假设当前的目录为:
- Test
- test.py
- image
- test.png
- main.py
当运行main.py
操作test.png
这个文件的时候,相对路径则是./image/test.png
但是,当运行test.py
操作test.png
这个文件的时候,相对路径则是../image/test.png
因为这个,可能在编写代码,进行代码单元测试时可能正常,结果到运行整个项目的时候,就报错了,但是发现错误时,需要将代码里的所有的路径全部改一遍,如果代码量多,则增加工作量,显然不是明智之举。而在开发的时候,由于思维惯性,不可避免会发生这种错误。以下提供解决办法
默认
在开发的时候根据启动类,调整开发思维,将所有的相对路径以启动类为基准进行编写
该方法强烈不推荐,对某个模块进行测试的时候会非常麻烦
动态获取绝对路径
思路:
- 在父类中获取改py文件的绝对路径
- 通过字符串搜索项目所在根目录,返回路径
- 将路径定义为类变量(或全局变量),子类应用即可
import os
abs_path = os.path.abspath(os.path.dirname(__file__)) # 返回当前py文件下的绝对路径
root_path = abs_path[0:abs_path.find("Test")] # 返回根目录
print(root_path) # 子类用self.root_path即可
动态切换当前工作目录
思路
- 动态获取当前绝对路径
abs_path
- 每个类调用
os.chdir(abs_path)
,动态切换当前工作目录到该路径中
abs_path = os.path.abspath(os.path.dirname(__file__))
os.chdir(abs_path)