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 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关键字
对于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]。