Python 学习笔记
文件处理
文件的读取与写入
open()函数,用来读取或写入文件,用法为
stream=open('文件路径','操作方式')
可以对这个流进行文件内容的操作
更多操作模式如下
stream.readline()
返回的是文件里一行的内容,且在使用后,文件的开始位置会变为下一行的起始位置,当无行可读时,返回None
由于读取的是行,所以会把行末尾的换行符也读入,显示出来便是print出来多了一个空行,但是最后一行没有
stream.read()
返回全部内容
stream.readlines()
返回每一行的内容形成一个列表并返回
stream.write(str)
向文件中写入,写入后指针位置位于字符串尾
stream.write(list)
向文件中依次写入list内的内容
文件夹操作
os.remove(path)
删除文件
os.rmdir(path)
删除文件夹,但文件夹必须为空
os.listdir(path)
返回一个由该文件夹内所有文件名组成的列表
os.chdir(path)
切换当前目录
os.getcwd(path)
返回当前目录
os.splitext(path)
将文件路径名和文件的类型分割开来,返回值是一个元组
os.split(path)
将文件路径和文件名(含后缀)分割开来,返回值是一个元组
附上手写的文件夹复制代码
import os
def copydir(src,target):
filelist=os.listdir(src)
for file in filelist:
path=os.path.join(src,file)
if os.path.isdir(path):
path1=os.path.join(src,file)
path2=os.path.join(target,file)
if os.path.isdir(path2):
pass
else:
os.mkdir(path2)
copydir(path1,path2)
else:
with open(path,'rb') as stream:
container=stream.read()
path1=os.path.join(target,file)
with open(path1,'wb') as wstream:
wstream.write(container)
异常处理
try...except
语句
当try语句内出现异常错误时,except会自动接受异常并执行except内的语句
可以使用多条except语句接受不同的异常类型
注意:except语句按照从上到下顺序接受异常,且只接受一次,所以表示所有异常的Exception类要放在最后
try...except...else
语句
当无异常抛出时,便会执行else语句下的内容
try...except...finally
语句
无论是否有异常抛出,即使有崩溃产生,finally中的语句一定会执行,如果有返回值则会覆盖掉之前的返回值
raise语句
raise可以抛出一个自定义的异常,类型以及异常的具体内容自己定
使用方法为raise ExceptionName(str)
try:
a = input("输入一个数:")
#判断用户输入的是否为数字
if(not a.isdigit()):
raise ValueError("a 必须是数字")
except ValueError as e:
print("引发异常:",repr(e))
# repr() 返回将对象直接转化为的字符串
在没有引发过异常的程序使用无参的 raise 语句时,它默认引发的是 RuntimeError 异常
当之前已经使用过一个raise时,使用无参的 raise 语句默认引发和上一个相同的异常,但有多个的异常时默认引发的还是 RuntimeError 异常
生成器
可以通过类似列表推导式的方法,迭代出一系列的值,同时相对于直接的列表节约了大量空间
格式为
generator=(x for x in range(10))
和列表推导式的唯一区别就是[]
变成了()
使用时可以通过generator.__next()__
或者next(generator)
来迭代出下一个值
当超出迭代器的范围时,再次调用会爆出StopIteration的错误
生成器的另一种方法是利用函数
def gen():
i = 0
while i<5:
temp = yield i
print(temp)
i+=1
当函数含有yield
关键字时,该函数代表的就是一个生成器,使用方法为f=gen()
,对这个f可以使用上述的一系列操作
yield
的作用是返回值的同时在此处暂停,同时当下一次调用该生成器时从这个断点继续运行
f.send(obj)
send函数的作用可以向生成器内传入一个对象,对于如同temp = yield i
的语句作用是将该对象在断点处赋值给temp并且运行下去,所以要注意的是在第一次调用生成器时不能使用send函数,正常使用f.__next__()
便相当于是f.send(None)
迭代器
可以被next()函数调用并返回下一个元素的对象都能可以称为迭代器
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
可以通过isinstance()
函数判断是否是可迭代对象,注意要先from collections import Iterable
但是可迭代的对象不一定是迭代器,可以通过iter()
使他变成一个迭代器
面向对象编程
类的创建
创建一个类的格式
class name:
属性1
属性2
函数1:
函数2:
函数方法
就是写在类里面的函数,可以通过类创建的实例对象调用,注意函数的第一个参数必须是self表示本身这个对象
在python中不支持函数名一样但是参数不相同的函数,后面一个函数会覆盖掉前面一个同名的函数
格式如下
def name(self,*args,*kwargs):
...
...
类方法,静态方法
类方法与静态方法都可以不依赖于对象使用,直接使用类名.函数
的格式调用,同时,操作的对象也只能是类的属性
类方法的格式
def class:
@classmethod
def name(cls,*args,**kwargs):
...
...
类方法的第一个参数必须是cls,表示本类,使用时函数前必须添加@classmethod
关键字
静态方法的格式
def class:
@staticmethod
def name(*args,*kwargs):
...
...
注意的是静态方法不需要self或者是cls参数,但是便也不能使用任何的类的属性和对象
魔法方法
可以类比构造函数,析构函数一类的
魔法方法的格式在开头和结尾各有两个下划线不能舍弃,名字均为定义好的
__init(self)__
构造函数,创建对象时调用
__new(cls)__
构造函数,调用的优先级比init更高,参数是cls,必须有返回值,当返回值是一个当前类的对象时,init也会随后被调用
__new()__也属于类的静态方法
__del()__
析构函数
__call()__
当使用创建的对象加括号时执行
__str()___
返回值是一个字符串,是当采用print()函数时打印出来的字符
__repr()__
功能与str类似,同时还是直接使用repr(obj)的返回值,与str的区别是repr(obj)的字符串会带上双引号
关于运算符的魔法方法,类比重载
关系运算 | 含义 |
---|---|
lt | 小于 |
gt | 大于 |
le | 小于等于 |
ge | 大于等于 |
eq | 等于 |
ne | 不等于 |
cmp | 用于sort,返回值1,-1,0,比较结果为-1的self放在前面 |
算数运算 | 含义 |
---|---|
add | 加 |
sub | 减 |
mul | 乘 |
truediv | 除 |
mod | 取模 |
pow | 乘方 |
注意这些用法基本均为__lt(self,obj)__
,记得传入另一个比较项的参数名
类属性
类属性所有创建的对象共用,实例化后的对象不可修改,只能通过类名.类属性
方式修改,如果有同名实例属性,实例对象会优先访问实例属性。
私有属性和方法
在属性前加上两个下划线便为私有属性,私有属性外界无法直接修改和访问,只能在类的方法内部使用,类比C++中的private关键字和public关键字
property关键字
对于get,set等函数去对于私有属性进行操作显得有些麻烦,为了实现看上去直接对私有属性的操作,可以使用property关键字
如
class Dog():
__age=1
def __init__(self):
self.__age=1
@property
def age(self):
return self.__age
@age.setter #名称要和上面一个一样
def age(self,age):
self.__age=age
d=Dog()
print(d.age) #直接访问__age私有参数
d.age=2
print(d.age)
要注意的时只有在定义了property函数之后才可以使用setter关键字来指定辅助函数
继承与引用
引用就是在别的类中使用一个已创建的类,正常使用即可,注意传入参数
继承的格式为
class 子类名(父类名):
def __init__(self):
super().__init__()
当需要使用到父类的构造函数时,可以使用super()函数来调用父类的构造函数,注意父类的传入参数不能缺少
当子类存在和父类相同函数名的函数时,会对父类的函数进行覆盖,也可以使用super()来调用父类的方法
多继承的语法格式
class 子类名(父类名1,父类名2...)
pass
如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用最前面的一个父类的方法,实际中应当避免这种情况
python中针对类提供了一个内置属性__mro__可以用来查看方法的搜索顺序。
使用方法
print(C.__mro__)
结果为
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
在调用方法时,按照__mro__的输出结果从左至右的顺序查找。
如果再当前类中找到方法,就直接执行,不再向下搜索。
如果没有找到,就顺序查找下一个类中是否有对应的方法,如果找到了最后一个类,依然没有找到方法,程序就会报错。
单例模式
通过某种方法,使得创建的对象共享的是一个地址,使得内存优化。
使用__new__()
class Singleton(object):
__instance=None
def __new__(cls):
if cls.__instance is None:
cls.__instance = super(Singleton, cls).__new__(cls)
return cls.__instance
obj1 = Singleton()
obj2 = Singleton()
使用装饰器
def singleton(cls):
instances = {}
def getinstance(*args,**kwargs):
if cls not in instances:
instances[cls] = cls(*args,**kwargs)
return instances[cls]
return getinstance
@singleton
class MyClass:
a = 1
c1 = MyClass()
c2 = MyClass()
print(c1 == c2)
# 装饰器 singleton返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]。
原创文章,作者:745907710,如若转载,请注明出处:https://blog.ytso.com/278514.html