try...except 结构
try...except 结构,用于防止被动掉坑。例如,输入b的值时,手抖了一下,除数不能为0,程序就会报错。有了这个异常处理机制,当出现了类似的情况时,就会执行对应情况的代码,防止报错。
try: a=int(input('请输入第一个数')) b=int(input('请输入第二个数')) c=a/b print('结果为',c) except ZeroDivisionError: print('除数不能为0') except ValueError: print('请输入正确的数字') print('程序结束')
try.....except...else结构 二选一执行的
try: a=int(input('请输入第一个数')) b=int(input('请输入第二个数')) c=a/b except BaseException as e: print('出错了',e) #这个e会告诉你出了什么错 else: print('计算结果为:',c)
try..except...else...finally结构
finally无论发生什么都会执行,通常用来释放try中申请的资源
try: a=int(input('请输入第一个数')) b=int(input('请输入第二个数')) c=a/b except BaseException as e: print('出错了',e) #这个e会告诉你出了什么错 else: print('计算结果为:',c) finally: print('thanks for using')
常见的异常类型
ZeroDivisionError 除数为0
IndexError 序列中没有这个索引
KeyError 映射中没有这个键
NameError 未声明的对象
SyntaxError 语法错误
ValueError 传入无效参数
面向过程&面向对象
比方说,我想吃番茄炒鸡蛋。我用面向过程的方法:第一步,菜市场买鸡蛋和番茄;第二步,洗干净;第三步,锅热倒油,下入鸡蛋;第四步,鸡蛋添起来,放入西红柿;。。。。。。
如果使用面向对象:打开美团APP点一个。然后厨师会帮你做,你不需要去执行上述步骤。
类:
类是多个类似事物组成的群体的统称。能够快速整理和理解和判断事物的性质。
类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。
定义一个类,Student 就是类名。注意规范:首字母大写。
在类之内定义的叫做方法!在类之外定义的叫做函数!直接写在类里的变量,称为类属性
def _ init _()为初始化方法
class Student: native_place='武汉' #直接写在类里的变量,称为类属性。 def __init__(self,name,age): self.name=name # self.name实例属性,进行了一个赋值的操作,将局部变量的name的值赋值给实体属性 self.age=age #2实例方法 def eat(self): #默认传入自身的对象 print(***生在吃饭...') #3静态方法使用@staticmethod修饰 @staticmethod def method(): print('我是用了staticmethod进行修饰,所以我是静态方法') #4类方法使用@classmethod修饰 @classmethod def cm(cls): print('我是类方法,使用classmethod修饰') def drink(): print('喝水')
创建一个Student类的实例对象。再打印它的类型和地址。
stu1=Student('张三',20) print('stu1t',id(stu1)) #2252700856528 十六进制后0x0000020C7F6F30D0 print('stu1',type(stu1)) #这些是 实例对象 的内存地址 print('stu1',stu1) #<__main__.Student object at 0x0000020C7F6F30D0>
打印类对象的类型和地址。
print('Student',id(Student)) print('Student',type(Student)) #这个是类对象的地址,类对象里面有一个类指针指向实例对象 print('Student',Student)
在实例对象中有一个类指针指向创造它的类对象,当类对象创建完成之后,就可以使用这个类的实例属性,以及这个类的相关方法。
类对象的使用方法:
方法一:实例对象名.方法名的方式调用类对象中的方法
方法二:*类名.方法名(对象名) *的方式调用类对象中的方法
stu1.eat() Student.eat(stu1) # 类名.方法名(对象名) print(stu1.age) print(stu1.name)
类属性的使用
创建两个实例对象,stu1、stu2。使用:类对象.类属性的方式调用。例如:print(Student.native_place)
stu1=Student('张三',20) stu2=Student('李四',30) print(stu1.native_place) print(stu2.native_place) #当改变了类属性之后: Student.native_place='广州' print(stu1.native_place) #两个都是修改后的结果 print(stu2.native_place) #两个结果一样
类方法的调用:
当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
类方法一般和类属性配合使用
Student.cm()
静态方法的调用:
当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
Student.method()
动态绑定属性和方法
1.绑定动态属性。
先创建一个类对象,其中包含初始化方法_ init _()和实例方法eat(),再创建两个实例对象stu1、stu2。
class Student: def __init__(self,name,age): self.name=name#将局部变量的值赋值给实例变量 self.age=age def eat(self): print(self.name+'在吃饭') stu1=Student('张三',20) stu2=Student('李四',22)
为stu2动态绑定属性gender,再调用动态属性。对于没有绑定动态属性的stu1,是不能调用动态属性的!
具体的内存图如图所示:
stu2.gender='女' print(stu1.name,stu1.age) print(stu2.name,stu2.age,stu2.gender)
2.动态绑定方法/函数
def show(): print('定义在类之外,称为函数') stu1.show=show #动态绑定方法 stu1.show() #调用动态绑定的方法
面向对象的三大特征
1.封装:提高程序的安全性
将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体细节,从而隔离了复杂度。(参考类对象的两种使用方法)
在Python中没有专门的修饰符用于属性私有,如果该属性不希望在类对象外部被访问,前面使用两个“_”。
class Student: def __init__(self,name,age): self.name=name self.__age=age #年龄不希望在类的外部被使用,所以用了两个下划线 def show(self): print(self.name,self.__age) stu=Student('张三',20) print(stu.name) #print(stu.__age) #报错了,程序不希望这样使用,不过可以通过下面的方法来实现 stu.show() #在类的外面使用name和age
虽然被两个下划线修饰的age不能这样访问,但还是有其他的办法访问。要凭程序员的自觉性,看到两个下划线最好不要访问。所谓的“防君子,不妨小人”
print(dir(stu)) print(stu._Student__age) #20 还是可以访问,但是要凭自觉,最好不要访问
2.继承:提高代码的复用性
object类是所有类的父类,因此所有类都有object类和属性和方法。
内置函数dir()可以查看指定对象所有属性。
class Person(object): #person继承object类 def __init__(self,name,age): self.name=name self.age=age def info(self): print(self.name,self.age) #定义一个子类 class Student(Person): #Student继承Person类 def __init__(self,name,age,stu_no): super().__init__(name,age) #用于调用父类的init方法,把name,age传入 self.stu_no=stu_no #定义另一个子类 class Teacher(Person): def __init__(self,name,age,teachofyears): super().__init__(name,age) self.teachofyears=teachofyears stu=Student('张三',20,'1001') teacher=Teacher('李四',34,10) stu.info() teacher.info()
2—1.方法重写
stu.info()、teacher.info()调用的是Person类里面的,无法输出学生的学号和老师的教龄。通过方法重写可以改变输出。
class Person(object):#person继承object类 def __init__(self,name,age): self.name=name self.age=age def info(self): print(self.name,self.age) #定义一个子类 class Student(Person): def __init__(self,name,age,stu_no): super().__init__(name,age) self.stu_no=stu_no def info(self): super(Student, self).info() print(self.stu_no) #因为只能输出name和age,不能执行stu-no,所以要重写这个方法 class Teacher(Person): def __init__(self,name,age,teachofyears): super().__init__(name,age) self.teachofyears=teachofyears def info(self): super(Teacher, self).info() #对原来的方法体不满意,就可以重新写 print('教龄',self.teachofyears)
内置函数dir()可以查看指定对象所有属性.
object有一个_str()_方法,用于返回一个对于“对象的描述”,即对象的内存地址,对应于内置函数str()经常用于print()方法,帮助我们查看对象信息。
class Student: pass stu=Student() print(dir(stu)) #可以查看对应的属性和方法,全部都是从父类object继承过来的 #对象的描述 print(stu) #输出一个对象的内存地址 <__main__.Student object at 0x000001A064C47460> print(id(stu)) #输出对象的内存地址,十进制的形式
当然父类的方法也可以重写,重写 _ str() _
class Student: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return '我的名字是{0},今年{1}岁了'.format(self.name,self.age) stu=Student('张三',20) print(dir(stu)) print(stu) #没有输出他的类型,而是结果 :我的名字是张三,今年20岁了 print(type(stu)) #<class '__main__.Student'>
3.多态:提供程序的扩展性和可维护性
简单地说,多态就是“具有多种形态”,它指的是:即便不知道一个变量所引用的对象到低是什么类型,任然可以通过这个变量调用方法,在运行过程中根据变量所引用的对象的类型,动态决定调用哪个对象中的方法。
class Animal(object): def eat(self): print('动物会吃') class Cat(Animal): def eat(self): print('猫吃鱼') class Dog(Animal): def eat(self): print('狗吃屎') class People(object): def eat(self): print('人吃五谷杂粮') #定义一个函数 def fun(obj): obj.eat() fun(Cat()) fun(Dog()) #cat和dog有自己重写的方法,所以调用自己的 fun(Animal()) print('----------------------') fun(People()) #动态语言,在创建的时候动态地绑定属性,动态的绑定方法 #不用关心people是谁的子类,只用关心people是否由eat的行为