python学习——类,文件和异常

 

创建类

创建一个小狗的类

class Dog():
    def __int__(self, name, age):
        self.name = name
        self.age = age

    def sit(self):
        print(self.name.title() + " is now sitting")

    def roll_over(self):
        print(self.name.title() + " rolled over!")

这里我们定义了一个Dog类,python中首字母大写的名称指的是类

 

根据类来创建实例叫做实例化。

首先会执行一个程序生成的默认的方法__new__()(用于创建对象,一般不需要重定义)

__int__(self,name,age)相当于构造函数,每当创建一个对象的时候会自动执行,用来初始化对象

self参数实际上就是对象本身的引用,相当于C++里的this指针,我们在调用类方法的时候不需要管它,它会自动传递实例的引用

我们可以直接在类内初始化一个值,只需要在初始化函数里添加相应的语句即可。

与C++不同的是,Dog是类对象,用Dog创建出来的东西是类实例,类实例可以用的方法是实例方法,所有实例共享的方法是类方法

所有实例所共享的属性叫做类属性

构造函数的要点如下

  1. 名称固定,必须为__int__() 这里是两道下划线
  2. 第一个参数固定,必须为self。 self指的是刚刚创建好的实例对象
  3. 构造函数通常用来初始化实例对象属性
  4. 通过类名(参数列表)来调用构造函数。调用后,将创建好的对象返回给相应的变量
  5. 例如 s = Dog("哈士奇",5)
  6. __init__()方法是初始化创建好的对象
  7. __new__方法是用于创建对象,一般无需重定义该方法

所有类方法的第一个参数必须是self

实例属性要点如下

1.实例属性一般在__init__()方法中定义,初始化

2.在本类的其他实例方法中,也是通过self进行访问

3.创建实例对象后,通过实例对象访问实例属性

如 

a = Dog("哈士奇",5)
a.age = 10#将哈士奇的年龄改为10岁

实例方法

实例方法是从属于实例对象的方法,实例方法的定义格式如下

def 方法名(self,形参列表)
     函数体

方法的调用格式如下

对象.方法名(参数列表)

要点如下

  1. 第一个参数必须为self
  2. 调用实例方法时,不需要也不能给self传参,self由解释器自动传参

函数与方法的区别

  • 1.都是用来完成一个功能的语句块,本质一样
  • 2.方法调用时,通过对象来调用,方法从属于特定实例对象
  • 3.直观上看,方法定义时需要传递self,函数不需要

 

实例对象的方法调用实质

a.sit 相当于 Dog.sit(a)

其他操作

  1. dir(obj)可以获得对象的所有属性和方法
  2. obj.__dict__对象的属性字典 就是将一个对象的各个属性以及它的值以字典的形式打印出来
  3. pass空语句
  4. isinstrance(对象,类型)判断对象是不是指定类型

 

修改类中属性的值

1.通过实例进行修改

a.age=10//直接通过实例来修改狗狗的年龄

2.通过类方法进行设置

def changeAge(self,aimAge):
    self.age=aimAge

将这个方法添加到类中,并调用这个方法即可修改年龄

规范

类名首字母大写

类方法使用小写字母,且单词之间使用_分隔

类方法之间空一行来分隔

类之间使用两个空行来分隔

类对象

class Student:
    pass
print(type(Student))
print(id(Student))

'''
<class 'type'>
2922809951984
'''

这个type是python中的摸具类,所有的类都是以他为摸具创建的

可以输出Student的地址,说明Student是一个对象,即类的模板也是个一个对象

类属性

类属性是属于类对象的属性,也称为类变量,由于,类属性从属于类对象,可以被所有实例对象共享

类属性相当于C++中的静态成员变量

class Student:
#在方法外面的是类属性,它被所有Student类的对象所共享
    company = "SXT"
    count = 0
    def __init__(self,name,score):
        self.name = name    #实例属性
        self.score = score
        Student.count+=1
    def say_score(self):  #实例方法
        print("我的公司是",Student.company)
        print(self.name,"的分数是:",self.score)
s1 = Student("张三",80) #s1是实例对象,自动调用__init__()方法
s1.say_score()
print("一共创建了{0}个对象".format(Student.count))

内存分析

可以看到类属性并没有在对象的内存中

类方法

类方法是从属于类对象的方法,类方法通过装饰器@classmethod来定义,格式如下

@classmethod
def 类方法名(cls ,参数列表)#cls指的是类对象
    函数体
  1. @classmethod 必须位于方法上面一行
  2. 第一个cls必须有,cls指的就是类对象本身
  3. 调用类方法格式:“类名.类方法名(参数列表)” 参数列表中,不需要也不能给cls传值
  4. 类方法中访问实例属性和实例方法会导致错误(不知道访问的是哪一个对象)
  5. 子类继承父类方法时,传入cls是子类对象,而非父类对象

举个简单的例子

class Student:
    company = "SXT"
    @classmethod
    def printCompany(cls):
        print(cls.company)
Student.printCompany()

注意类方法是不存在于该类对象的内存中的

 

静态方法

python中允许定义与类对象无关的方法,称为静态方法

静态方法和在模块中定义的普通函数没有任何区别,只不过静态方法放到了类中,需要通过类调用

静态方法语法如下

@staticmethod
def 静态方法名(形参列表)
    函数体

要点如下

  1. @staticmethod必须位于方法上面一行
  2. 调用静态方法的格式:“类名.静态方法名(参数列表)”
  3. 静态方法中访问实例属性和实例方法会导致错误
class Student:
    company = "SXT"
    @staticmethod
    def add(a,b):
        print("{0}+{1}={2}".format(a,b,a+b))
Student.add(1,2)

 

析构函数和垃圾回收机制

__del__方法称为析构方法,用于实现对象被销毁时所需进行的操作,比如释放对象占用的资源

python实现自动的垃圾回收,当对象没有被引用时(引用计数为0),由垃圾回收器调用__del__方法

也可以通过del语句删除对象,从而保证调用__del__方法

系统会自动提供__del__方法,一般不需要自定义析构方法

class Person:
    def __del__(self):
        print("销毁对象:{0}".format(self))
p1 = Person()
p2 = Person()
del p2
print("程序结束")


'''
销毁对象:<__main__.Person object at 0x000001A7BE2956A0>
程序结束
销毁对象:<__main__.Person object at 0x000001A7BE281730>
'''

 

__call__方法

在python中,函数其实时一个对象,可以通过函数名(参数列表)调用函数,我们一个把一个类实例变成一个可调用对象,即通过类实例名(参数列表)来调用某个函数

class fun:
    def __call__(self, str,salary):
        print(str,"你的工资是",salary)
aa = fun()
aa("张三",3000)

'''
张三 你的工资是 3000

'''

方法重载

在其他语言中, 可以定义多个重名的方法, 只要保证方法签名唯一即可; 方法签名包含3个部分: 方法名, 参数数量, 参数类型

Python中, 方法的参数没有声明类型(调用时确定参数的类型), 参数的数量也可以由可变参数控制; 因此, Python中是没有方法重载的; 定义一个方法即可有多重调用方法, 相当于实现了其他语言中的方法的重载;

如果我们在类体中定义了多个重名的方法, 只有最后一个有效;

建议: 不要使用重名的方法, Python中方法没有重载;

方法的动态性

Python是动态语言, 我们可以动态的为类添加新的方法, 或者动态的修改类的已有的方法;


#Python中没有方法的重载,定义多个同名方法,只有最后一个有效

class Person:

    def say_hi(self):
        print('hello')

 
    def say_hi(self,name):
        print("{0},hello".format(name))


p1 = Person()
p1.say_hi('张三') #张三,hello
# p1.say_hi() #不带参数,报错say_hi() missing 1 required positional argument: 'name'

 

#测试方法的动态性,一切都是对象,方法也是对象

class Test:

    def work(self):
        print("努力上班")

def play_game(s):
    print("{0}在玩游戏".format(s))

def work2(s):
    print("好好学习")

 

Test.play = play_game;#把paly_game方法添加到类里面去,把实例方法变成类方法
s = Test()
s.work()
s.play() #上面已经把play赋值为函数play_game
Test.work = work2
s.work()


输出:

 

D:\wwwroot\pyiteam\venv\Scripts\python.exe D:/wwwroot/pyiteam/mypro_obj/mypy02.py
张三,hello
努力上班
<__main__.Test object at 0x0141C3D0>在玩游戏
好好学习


Process finished with exit code 0

 

@property 装饰器

@property可以将一个方法的调用方式变成“属性调用”。

在我们定义数据库字段类的时候,往往需要对其中的类属性做一些限制,一般用get和set方法来写,那在python中,我们该怎么做能够少写代码,又能优雅的实现想要的限制,减少错误的发生呢,这时候就需要我们的@property闪亮登场啦,巴拉巴拉能量……..

用代码来举例子更容易理解,比如一个学生成绩表定义成这样
 

class Student(object):

    def get_score(self):
        return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

我们调用的时候需要这么调用:

>>> s = Student()
>>> s.set_score(60) # ok!
>>> s.get_score()
60
>>> s.set_score(9999)
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

但是为了方便,节省时间,我们不想写s.set_score(9999)啊,直接写s.score = 9999不是更快么,加了方法做限制不能让调用的时候变麻烦啊,@property快来帮忙….

class Student(object):

    @property//相当于getter
    def score(self):
        return self._score

    @score.setter//相当于setter
    def score(self,value):
        if not isinstance(value, int):
            raise ValueError('分数必须是整数才行呐')
        if value < 0 or value > 100:
            raise ValueError('分数必须0-100之间')
        self._score = value

看上面代码可知,把get方法变为属性只需要加上@property装饰器即可,此时@property本身又会创建另外一个装饰器@score.setter,负责把set方法变成给属性赋值,这么做完后,我们调用起来既可控又方便

>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

类的继承

如果在类定义中没有指定父类,则默认父类是object类,也就是说,object是所有类的父类,里面定义了一些所有类的共有的默认实现,比如:new().

定义子类时,必须在其构造函数中调用父类的构造函数。调用格式如下:
父类名.__init__(self,参数列表)

class Car():
#汽车类
    def __int__(self,make,model,year):
        self.make=make
        self.model=model
        self.year=year
        self.odometer_reading=0#初始化里程为0
    def get_descriptive_name(self):
        long_name=str(self.year+' '+self.make+' '+self.model)
        return long_name.title()
    def read_odometer(self,mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading=mileage
        else:
            print("你不能这样做")

#电动汽车类
class ElectricCar(Car):
    def __init__(self,make,model,year):
        super().__init__(make,model,year)#这条代码是初始化父类所有属性
        self.battery_size=70#电动车特有电瓶属性

 

内存分析

 

注意事项:创建子类时,父类必须在前面,而且必须在子类括号里指明父类的名称

super()是一个特殊函数,它可以将子类和父类关联起来,可以调用父类的__init__()方法,使子类中包含父类的所有属性

只要子类方法里的方法与父类方法同名,python就只会执行子类里的方法

 

 

 

类成员的继承和重写

1、成员继承:子类继承了父类除构造方法之外的所有成员。
2、方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类中的方法,也称为重写。

 

查看类的继承层次结构

通过类的方法 mro() 或者类的属性 mor 可以输出这个类的继承层次结构。
查看类的继承层次结构

class A:pass
class B(A):pass
class C(B):pass

print(C.mro())

结果如下

[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

object根类

object类是所有类的父类,因此所有的类都有object类的属性和方法。

例如我们建一个空的类

内置函数dir()可以让我们看到指定对象所有的属性。

class A:
    pass

a = A()
print(a.__dir__())

输出如下,可以看出有很多来自object类的方法 


['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

实际上我们自己定义的方法也是一种属性,只不过它是属于方法属性罢了

 

重写_str_()方法

object有一个_str_()方法,用于返回一个对于“对象描述”,对应于内置函数str()经常用于print()方法,帮助我们查看对象的信息,str()可以重写。

class Person:  #默认继承object类
    def __init__(self,name):
        self.name = name

    def __str__(self):
        return"名字是:{0}".format(self.name)
p = Person("弟弟")
print(p)

输出是

名字是:弟弟

MRO()


Python支持多继承,如果父类中有相同名字的方法,在子类没有指定父类名时,解释器将“从左向右”按顺序搜索。
MRO(Method Resolution Order):方法解析顺序。我们可以通过mro()方法获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找的。
 

class A:
    def aa(self):
        print("aa")

    def say(self):
        print("say AAA!")
class B:
    def bb(self):
        print("bb")

    def say(self):
        print("say BBB!")
class C(B,A):
    def cc(self):
        print("cc")

c = C()
print(C.mro())  #打印类的层次结构
c.say()  #解释器寻找方法是“从左到右”的方式寻找,此时会执行B中的say

结果如下

[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
say BBB!

super()获得父类定义

在子类中,如果想要获得父类的方法时,我们可以通过super()来做。
supper()代表父类的定义,不是父类对象。

class A:

    def say(self):
        print("A:",self)

class B(A):

    def say(self):
        #A.say(self)
        super().say()
        print("B:",self)

B().say()

结果如下

[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
say BBB!

多态

多态(polymorphism)是指同一个方法调用由于对象不同可能会产生不同的行为。
要点
1、多态是方法的多态,属性没有多态。
2、多态的存在有2个必要条件:继承、方法重写。

class Man:
    def eat(self):
        print("饿了,吃饭啦!")

class Chinese(Man):
    def eat(self):
        print("中国人用筷子吃饭")

class English(Man):
    def eat(self):
        print("英国人用叉子吃饭")

class Indian(Man):
    def eat(self):
        print("印度人用右手吃饭")

def manEat(m):
    if isinstance(m,Man):
        m.eat()  #多态,一个方法调用,根据对象不同调用不同的方法。
    else:
        print("不能吃饭")

manEat(Chinese())
manEat(English())

结果如下

中国人用筷子吃饭
英国人用叉子吃饭

感觉比C++简单多了

特殊方法和运算符重载

Python的运算符实际上是通过调用对象的特殊方法实现的。比如:

a = 20
b = 30
c = a+b
d = a.__add__(b)
print("c=",c)
print("d=",d)

结果如下

c= 50
d= 50

常见的特殊方法统计如下

以上方法都要加上双下划线

每个运算符实际上都对应了相应的方法,统计如下:

以上方法都要加上单下划线

测试运算符重载

class Person:
    def __init__(self,name):
        self.name = name

    def __add__(self,other):
        if isinstance(other,Person):
            return ("{0}--{1}".format(self.name,other.name))
        else:
            return "不是同类对象,不能相加"

    def __mul__(self,other):
        if isinstance(other,int):
            return  self.name*other
        else:
            return "不是同类对象不能相乘"
p1 = Person("我的")
p2 = Person("弟弟")
x = p1 + p2
print(x)

print(x*30)

结果如下

我的--弟弟
我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟我的--弟弟

特殊属性

Python对象中包含了很多双下划线开始和结束的属性。

测试一些特殊属性

class A:
    pass
class B:
    pass
class C(B,A):
    def __init__(self,nn):
        self.nn = nn

    def cc(self):
        print("cc")

c = C(3)

print(dir(c))
print(c.__dict__)
print(c.__class__)
print(C.__bases__)
print(C.mro())
print(A.__subclasses__())

结果如下

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'cc', 'nn']
{'nn': 3}
<class '__main__.C'>
(<class '__main__.B'>, <class '__main__.A'>)
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
[<class '__main__.C'>]

对象的浅拷贝和深拷贝


变量的赋值操作
只是形成两个变量,实际还是指向同一个对象。
浅拷贝
Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝。因此,源对象和拷贝对象会引用同一个对象。
深拷贝
使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象。源对象和拷贝对象所有的子对象也不同。
测试对象的浅拷贝、深拷贝

import copy
class MobilePhone:
    def __init__(self,cpu,screen):
        self.cpu = cpu
        self.screen = screen
class CPU:
    def calculate(self):
        print("12345")
        print("cpu的对象:",self)
class Screen:
    def show(self):
        print("显示一个好看的画面")
        print("screen对象:",self)


 #测试变量赋值
c1 = CPU()
c2 = c1
print(c1)

#测试浅复制
s1 = Screen()
m1 = MobilePhone(c1,s1)
m2 = copy.copy(m1)

print(m1,m1.cpu,m1.screen)
print(m2,m2.cpu,m2.screen)

#测试深复制
m3 = copy.deepcopy(m1)
print(m1,m1.cpu,m1.screen)
print(m3,m3.cpu,m3.screen)

结果

测试浅复制
<__main__.MobilePhone object at 0x000002C36CD43240> <__main__.CPU object at 0x000002C36BC74E10> <__main__.Screen object at 0x000002C36CD431D0>
<__main__.MobilePhone object at 0x000002C36CD43128> <__main__.CPU object at 0x000002C36BC74E10> <__main__.Screen object at 0x000002C36CD431D0>
测试深复制
<__main__.MobilePhone object at 0x000002C36CD43240> <__main__.CPU object at 0x000002C36BC74E10> <__main__.Screen object at 0x000002C36CD431D0>
<__main__.MobilePhone object at 0x000002C36CD435F8> <__main__.CPU object at 0x000002C36CD436A0> <__main__.Screen object at 0x000002C36CD43710>

组合

“Is-a”关系,我们可以使用“继承”,从而实现子类拥有的父类的方法和属性。“is-a”关系指的是类似这样的关系。
“has-a”关系,我们可以使用“组合”,也能实现一个类拥有另一个类的方法和属性。

#测试组合
#使用继承实现代码的复用
class A1:
    def say_a1(self):
        print("a1,a1,a1")
class B1(A1):
    pass
b1 = B1()
b1.say_a1()
#同样的效果,使用组合实现代码的复用
class A2:
    def say_a2(self):
        print("a2,a2,a2")
class B2:
    def __init__(self,a):
        self.a = a

a2 = A2()
b2 = B2(a2)
b2.a.say_a2()

结果如下:
a1,a1,a1
a2,a2,a2

测试has-a关系,使用组合

#测试has-a关系,使用组合
class MoilePhone:
    def __init__(self,cpu,screen):
        self.cpu = cpu
        self.screen = screen

class CPU:
    def calculate(self):
        print("12345")
        print("cpu对象:",self)

class Screen:
    def show(self):
        print("显示一个好看的画面")
        print("screen对象",self)

m = MoilePhone(CPU(),Screen())
m.cpu.calculate()
m.screen.show()

结果如下

12345
cpu对象: <__main__.CPU object at 0x0000017EDEA2C3C8>
显示一个好看的画面
screen对象 <__main__.Screen object at 0x0000017EDEA2C358>

设计模式_工厂模式实现

设计模式是面向对象语言特有的内容,是我们在面临某一类问题时候固定的做法。设计模式有很多种,比较流行的是:GOF(Group Of Four)23种设计模式。
工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择实现类,创建对象进行统一的管理和控制。

#测试工厂模式
class CarFactory:
    def create_car(self,brand):
        if brand == "奔驰":
            return Benz()
        elif brand == "宝马":
            return BMW()
        elif brand == "比亚迪":
            return BYD()
        else:
            return "未知品牌,无法创建"

class Benz:
    pass

class BMW:
    pass

class BYD:
    pass

factory = CarFactory()
c1 = factory.create_car("奔驰")
c2 = factory.create_car("比亚迪")
print(c1)
print(c2)

结果如下:

<__main__.Benz object at 0x000002C245C44E48>
<__main__.BYD object at 0x000002C246CD8908>

设计模式_单例模式实现


单例模式(singleton Pattern)的核心作用是确保一个类只有一个实例,并且提供一个访问该实例的全属访问点。
单例模式只生成一个实例对象,减少了对系统资源的开销。当一个对象产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产生一个"单例对象",然后永久驻留内存中,从而极大的降低开销。
 

#测试单例模式
class MySingleton:

    __obj = None  #类属性
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
           cls.__obj =object.__new__(cls)

        return cls.__obj

    def __init__(self,name):
        if MySingleton.__init_flag:
            print("init......")
            self.name = name
            MySingleton.__init_flag = False

a = MySingleton("aa")
b = MySingleton("bb")
print(a)
print(b)
c = MySingleton("cc")
print(c)

结果如下

init......
<__main__.MySingleton object at 0x00000290F4EDBE80>
<__main__.MySingleton object at 0x00000290F4EDBE80>
<__main__.MySingleton object at 0x00000290F4EDBE80>

可以将工厂模式和单例模式组合起来,即只有一个工厂

# 测试工厂模式和单例模式
class CarFactory:
    __obj = None  # 类属性
    __init_flag = True
    def create_car(self, brand):
        if brand == "奔驰":
                return Benz()
        elif brand == "宝马":
                return BMW()
        elif brand == "比亚迪":
                return BYD()
        else:
                return "未知品牌,无法创建"

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj =object.__new__(cls)
        return cls.__obj
    def __init__(self):
        if CarFactory.__init_flag:
            print("CarFactoryinit......")
            CarFactory.__init_flag = False

    class Benz:
        pass

    class BMW:
        pass

    class BYD:
        pass

a = CarFactory()
b = CarFactory()
print(a)
print(b)

结果如下

CarFactoryinit......
<__main__.CarFactory object at 0x0000027423547DC0>
<__main__.CarFactory object at 0x0000027423547DC0>

导入类

导入类和导入模块的方法是一样的

1.import 文件名

可使用该文件中的所有类 以及函数,但是注意,用类来定义实例时候要加文件名.类名

2.from 文件名 import 类名

直接使用类名来定义实例即可

3. import 文件名 as 改后的名字

4.from 文件名 import 类名 as 改后的名字

 

文件和异常

 

从文件中读取数据

 

#aa.txt
123
456
789

在当前目录下创建一个aa.txt的文件

with open("aa.txt") as fp:
    c=fp.read()
    print(c)

open函数参数为要打开文件的文件名,返回一个表示该文件的对象,用as 将其存储在fp中

后续对fp的操作就相当于对相应的文件进行操作,read方法是从文件头读到文件尾,返回一个字符串,当读到文件尾部的时候,返回一个空字符串

输出结果为:

我们可以使用rstrip方法来删除这个空白

rstrip:用来去除结尾字符、空白符(包括\n、\r、\t、' ',即:换行、回车、制表符、空格)

with open("aa.txt") as fp:
    c=fp.read()
    print(c.rstrip())

文件路径

如果要读取的文件不在当前目录内,而是在当前目录的文件内,需要提供文件路径

 

windows下是这样的

逐行读取 

with open("aa.txt") as fp:
    for i in fp:
        print(i)


会发现输出变成这样了
123

456

789


为什么会有这么多空行呢

因为文件中每行有一个换行符,再加上print也会输出一个换行符。可以通过rstrip方法来消除文件行换行符

 

with open("aa.txt") as fp:
    for i in fp:
        print(i.rstrip())

创建一个包含文件各行内容的列表

with open("aa.txt") as fp:
    c=fp.readlines()
print(c)

输出结果是
['123\n', '456\n', '789\n']
可以使用rstrip来消除'\n'

json.uload函数

可以将json格式文件中数据以字符串的形式读取出来

import json
fp = open('aa.txt','r')
a = json.load(fp)
print(a)

写入文件

with open('aa.txt','w') as fp:
    fp.write("123456")

将‘123456’写入aa.txt文件

注意w是指只写的方式打开文件,r的只读方式打开文件,r+是可读可写的方式打开文件,a是以接着上次的写,w是清空文件,之后再写。python默认方式是只读。

如果想写入多行的话,需要加上换行符

也可以使用库中的json.dump()函数

与write方法不同的时,json.dump()函数可以将写入文件的数据

自动转换为str类型。

列表和字典无法通过write存储到文件中,因此要使用json.dump()将字典转换为一种叫json格式来存储它

json.dump(x,y) x是要存的数据,y是文件对象

import json
a={'a':1,'b':2}
with open('aa.txt','w') as fp:
    json.dump(a,fp)

'''
aa.txt
{"a": 1, "b": 2}
'''

异常

程序在运行时,如果Python 解释器遇到到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常

程序停止执行并且提示错误信息这个动作,我们通常称之为:抛出(raise)异常

程序开发时,很难将所有的特殊情况都处理的面面俱到,通过异常捕获可以针对突发事件做集中的处理,从而保证程序的稳定性和健壮性

捕获异常

在程序开发中,如果对某些代码的执行不能确定是否正确,可以增加try(尝试)来捕获异常

捕获异常最简单的语法格式:

try:
   尝试执行的代码
except:
   出现错误后的处理

try 下面编写要尝试的代码。

except 如果不是,下面编写尝试失败的代码

 

处理ZeroDivisionError异常

print(5/0)

这一条代码,python会报错

使用try-except

try:
    print(5/0)
except ZeroDivisionError:
    print("error")

意思是执行try中的语句,然后如果出错,就会执行except中的内容

 

在程序执行时,可能会遇到不同类型的异常,并且需要针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了

语法如下:

try:
  #尝试执行的代码
except 错误类型1:

except 错误类型2:

except Exception as result:
   print("未知错误 %s"% result)

举个例子

try:
    num = int(input("请输入整数:"))
    print(8/num)
except ValueError:
    print("请输入正确的整数")
except ZeroDivisionError:
    print("除 0 错误")

捕获未知错误

在开发时,要预判到所有可能出现的错误,还是有一定难度的

如果希望程序无论出现任何错误,都不会因为Python解释器抛出异常而被终止,可以再增加一个exucept

语法如下

except Exception as result:
   print("未知的错误 %s"%s result)

else 代码块

try:
  print(3/2)
except ZeroDivisionError:
  print("error")
else:
  print("no error")

如果try里的代码成功执行了,则执行else里的内容。

finally代码块

无论执行成功与否,都会执行finally代码块里的代码

 

完整代码展示

try:
  print(8/a)
except ZeroDivisionError:
  print("error")
except Exception as result:
   print("未知错误 %s"% result)
else:
   print("执行成功")
finally:
   print("无论执行是否成功,都会执行的代码")

输出结果

未知错误 name 'a' is not defined
无论执行是否成功,都会执行的代码

 

抛出hraise异常

在开发中,除了代码执行出错Python解释器会抛出异常之外

还可以根据应用程序特有的业务需求主动抛出异常

示例

提示用户输入密码,如果长度少于 8,抛出异常

 

注意

当前函数只负责提示用户输入密码,如果密码长度不正确,需要其他的函数进行额外处理

因此可以抛出异常,由其他需要处理的函数捕获异常

4抛出异常

Python中提供了一个Exception异常类

在开发时,如果满足特定业务需求时,希望抛出异常,可以:

创建一个Exception的对象

使用raise关键字抛出异常对象

def input_password():
   pwd = input("请输入密码:")
   if len(pwd) >= 8:
      return pwd
   e = Exception("密码长度不够")

   raise e

try:
   user_pwd = input_password()
   print(use_pwd)
except Exception as result:
   print("发现错误:%s"%result)

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章