0316-0322面向对象编程
1.面向过程、对象概念
# python中两大范式:1.面向过程 2.面向对象
'''两者都不是新的技术,而是做事的思维方式'''
# 面向过程的核心是过程:即按先后次序来做,也就是机械式的思维方式,如把大象放冰箱步骤
优点:复杂问题简单化,进而流程化 | 缺点:扩展性差 |使用场景:对扩展性要求不高的地方
# 面向对象的核心是对象:在python中一切皆对象
1.在程序中对象就是盛放'数据属性'和'功能'的容器,即变量和函数
2.在生活中对象就是'特征'与'技能'的结合体,如学生选课系统
优点:扩展性强 | 缺点:学习难度大 | 使用场景:对扩展性要求不高的地方
# 对象的底层原理:以学生选课系统为例
# version 1.0 实现一个学生选课功能
stu_name = 'yma'
stu_age = '19'
stu_gender = 'female'
stu_courses = []
def choose_course(stu_name,stu_courses,course):
stu_courses.append(course)
print('%s选课成功%s' % (stu_name,stu_courses))
# version 1.1 实现多个学生选课成功,进行优化,将学生信息放入字典,不会混乱
stu1 = {
stu_name : 'yma'
stu_age : '19'
stu_gender : 'female'
stu_courses : []
}
def choose_course(stu_dict,course):
stu_dict['courses'] = course
print('%s选课成功%s' % (stu_dict['name'],stu_dict['courses']))
# version 1.2 不符合对象定义,进行优化使其成为对象
def choose_course(stu_dict,course):
stu_dict['courses'] = course
print('%s选课成功%s' % (stu_dict['name'],stu_dict['courses']))
stu1 = {
stu_name : 'yma'
stu_age : '19'
stu_gender : 'female'
stu_courses : []
'choose_course':choose_course
}
stu1['choose_course'](stu1,course) #调用
2.类的定义和对象的产生
# 对象:'特征'与'技能'的结合体
'''站在不同的角度,分的种类不一样'''
# 类:一系列相似特征与相似技能的结合体
# 现有类还是现有对象?
1.生活中:现有对象,再有类
2.程序中:一定是先定义类,调用类产生对象
'''专业语法来定义类
class 类名():
pass
'''
# 类名的命名
1.类名的命名遵循变量的命名规范
2.类名的首字母一般大写
3.如果类名存在多个单词,一般是大驼峰格式
#定义一个类
class Student():
school = 'SH' # 变量在类里面叫属性
country = 'China'
def choose_course(stu_dict,course): # 函数写到类里面叫方法
stu_dict['courses'].append(course)
print('%s选课成功%s' % (stu_dict['name'],stu_dict['courses']))
print(Student.__dict__) # 查看类的名称空间
'''
定义类会发生几件事?
1.定义类,会立刻执行类体代码
2.产生类的名称空间,并且把类中的属性和方法名字丢在类的名称空间中,其实就是丢在大字典里
3.把类的名称空间绑定给__dict__,如何调用:类名.__dict__
'''
小知识:类的括号如果什么都没有,可以不加括号
# 对象的产生
stu = Student() #调用类产生了对象
print(stu.__dict__) # 对象的名称空间,是空字典{} '''调用类产生对象,得到的对象就是一个空对象'''
3.定制对象自己独有的属性
class Student():
school = 'SH' # 变量在类里面叫属性
country = 'China'
def choose_course(stu_dict,course): # 函数写到类里面叫方法
stu_dict['courses'].append(course)
print('%s选课成功%s' % (stu_dict['name'],stu_dict['courses']))
stu = Student()
print(stu.__dict__) # 得到的是对象的名称空间{}
stu.__dict__['name'] = 'kevin' #往字典里增加值,定制对象自己独有的属性
stu.name = 'kevin' #杠杠开头的方法不推荐使用,推荐使用点语法,与上面等价
# 当有多位学生时,代码重复冗余,优化:将其封装成函数
def init(name,age,gender,course=[]): #stu写死了
stu.name = name
stu.age = age
stu.gender = gender
stu.courses = course
def init(stu_dict,name,age,gender,course=[]): #将stu当成参数传过来
stu_dict.name = name
stu_dict.age = age
stu_dict.gender = gender
stu_dict.courses = course
# 不想多次调用,优化
class Student():
school = 'SH' # 变量在类里面叫属性
country = 'China'
def __init__(stu_dict,name,age,gender,course=[]): #初始化方法,当类被加括号调用的时候会自动触发该函数执行
stu_dict.name = name
stu_dict.age = age
stu_dict.gender = gender
stu_dict.courses = course
def choose_course(stu_dict,course): # 函数写到类里面叫方法
stu_dict['courses'].append(course)
print('%s选课成功%s' % (stu_dict['name'],stu_dict['courses']))
'''类被调用的时候,类里面传的第一个参数时这个类产生的对象'''
stu = Student('kevin',20,'male')
'''调用类的过程就是实例化的过程,得到的结果就是一个实例'''
4.属性的查找顺序
class Student():
school = 'SH' 叫属性
country = 'China'
def __init__(stu_dict,name,age,gender,course=[]):
stu_dict.name = name
stu_dict.age = age
stu_dict.gender = gender
stu_dict.courses = course
def choose_course(stu_dict,course): 面叫方法
stu_dict['courses'].append(course)
print('%s选课成功%s' % (stu_dict['name'],stu_dict['courses']))
# 类属性的增删改查
1.查 Student.school #类名.属性名 存在返回值,不存在报错
2.增 Student.aaa = 'xxx' #类名.属性名 = 值
3.改 Student.school = 'HZ' #类名.属性名 = 值
4.删 del Student.school #del 类名.属性名
# 对象属性的增删改查
stu = Student('kevin',20,'male')
print(stu.__dict__) #对象名称空间
1.查 stu.__dict__['name'] 或者 stu.name
1.1 如果stu.__dict__['name1']会报错[KeyError],stu.name1也会报错[AttribbuteError类的对象没有该属性名]
1.2 stu.__dict__只能从对象自己的名称空间里查找,没有则报错;stu.先在对象里找,没有的话在产生这个对象的类 里找,有的话返回值,没有则报错。还支持修改,修改后存在于对象的字典中
2.增 stu.money = 'xxx' #对象名.属性名 = 值
3.改 stu.name = 'xxx' #对象名.属性名 = 值
4.删 del stu.name #del 对象名.属性名
5.练习题
# 定义一个类,产生一堆对象
# 定义一个计数器,记录一共产生了多少个对象
class Hero():
name = 'LOL'
type = 'MOBA'
count = 0
def __init__(self,champion,career):
self.champion = champion
self.career = career
Hero.count +=1
print('这位是%s,职业是%s,一共输出%s个英雄' % (champion,career,Hero.count))
a = Hero('盖伦','战士')
b = Hero('派克','刺客')
print(a.__dict__) # {'champion': '盖伦', 'career': '战士'}
print(Hero.__dict__) # {'__module__': '__main__', 'name': 'LOL', 'type': 'MOBA', 'count': 2, '__init__': <function Hero.__init__ at 0x000001A126C9DAE8>, '__dict__': <attribute '__dict__' of 'Hero' objects>, '__weakref__': <attribute '__weakref__' of 'Hero' objects>, '__doc__': None}
6.绑定方法&非绑定方法
'''1.学面向对象的时候一定要搞清楚self是谁
2.至于说,方法绑定给谁,要看具体的功能逻辑,需要谁就绑定给谁
3.我们可以通过对象self找到这个对象的类:self.__class__'''
# 1.绑定给类的方法
class Student():
@classmethod
def tell_info(cls)
print('')
Student.tell_info() # 类名.方法名()
stu = Student()
stu.tell_info() #对象名.方法名()
'''1.类来调用,会把类名当成第一个参数自动传给方法中第一个形参cls,上方内置装饰器
2.对象也能调用,但是目的不是让对象来调用的'''
# 2.绑定给对象的方法
class Student(): #普通功能,对象和类都不需要
def tell_info(self):
print('')
stu = Student()
stu.tell_info() # 即stu.tell_info(stu) 对象名.方法名()
Student.tell_info(stu) # 类名.方法名(对象名)
'''1.绑定给对象的方法由对象来调用,特殊之处在于对象会把对象自己当成第一个参数自动传给方法的第一个形参 self
2.绑定给对象的方法由类来调用,方法里面有几个参数就要传几个参数,包括self本身,目的不是让类来调用的
'''
# 3.非绑定方法:既不绑定给对象,也不绑定给类
class Student():
@staticmethod # 静态方法
def get_id():
import uuid
return uuid.uuid4()
Student.get_id()
stu = Student()
stu.get_id()
'''非绑定方法中对象和类都可以调用,并且都不用传参数'''
7.隐藏属性
# 1.哪些可以隐藏
类属性、对象属性、方法
# 2.如何隐藏?
属性名或方法名前加'__'
'''1.在类定义阶段,隐藏的名字发生了变形:_类名__名字
2.理论上,在类外部就不能使用隐藏名字了,但是非要在类外部使用也能用
3.对外不对内,在类的内部没有隐藏,就通过正常的调用方式来调用即可
'''
# 3.为什么隐藏?
由于隐藏属性对外不对内,类外部有使用隐藏属性的场景,在类的内部开放一个接口,返回类内部的隐藏属性,并且还可以对外做更好的限制
class Student():
# __country = 'CHINA' # _Student__country
__country = 'CHINA' # _Student__country
def __init__(self, name, age):
self.__name = name # _Student__name
self.age = age
def __func(self): # _Student__func
print('from func')
# def index(self):
# return self.__country # self._Student__country
def get_country(self):
return self.__country
def set_country(self, v):
if not type(v) is str:
return
Student.__country = v
stu = Student('kevin', 18)
print(stu.get_country()) # CHINA
stu.set_country('xyz')
print(stu.get_country()) # xyz
8.property装饰器
# 1.把方法伪装成属性:法一
class Student():
def bmi(self):
return self.weight/self.height **2
#实例化一个对象
stu =Student()
stu.bmi()
class Student():
@property
def bmi(self):
return self.weight/self.height **2
@bmi.setter
def bmi(self,v):
self.bmi = v
@bmi.deleter
def bmi(self):
del self.bmi
stu = Student()
stu.bmi # 不用再加括号了
stu.bmi = 'aaa'
del stu.bmi
'''三者不是必须同时存在,绝大多数只有property这一个'''
# 2.法二
class Student():
def get_bmi(self):
return self.weight/self.height **2
def set_bmi(self,v):
self.bmi = v
def del_bmi(self):
del self.bmi
bmi = property(get_bmi,set_bmi,del_bmi) #顺序有讲究:查>改>删
stu = Student()
stu.bmi
9.面向对象三大特征
# 1.封装
将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用
# 2.继承
1.什么是继承?
继承就是新建类的一种方式,新建出来的类被称为子类或者派生类,被继承的类称为父类或者基 类,子类可以继承父类的所有属性和方法
2.为什么要用继承?
类:解决了对象与对象之间的代码冗余问题;继承:解决了类与类之间的代码冗余问题
3.怎么使用继承?
经典类:没有继承object类的子子孙孙类都是经典类
新式类:继承了object类的子子孙孙类都是新式类
'''只有在python2中才区分经典类和新式类,在python3中,全部都是新式类'''
class Parent1():
pass
class Parent2():
pass
class Sub(Parent1,Parent2): # 子类可以使用父类的所有属性和方法,父类不可以使用子类的
pass
'''py中支持多继承'''
4.单继承下的属性查找[单继承:括号中的类名只能写一个]
class Foo():
def f1(self):
print('from Foo.f1')
def f2(self):
print('from Foo.f2')
self.f1()
class Bar(Foo):
def f1(self):
print('from Bar.f1')
# 实例化一个对象
obj = Bar()
obj.f2() # from Foo.f2 from Bar.f1
#########################################################
class Foo():
def __f1(self):
print('from Foo.f1')
def f2(self):
print('from Foo.f2')
self.__f1() # self_Foo__f1()
class Bar(Foo):
def __f1(self):
print('from Bar.f1')
# 实例化一个对象
obj = Bar()
obj.f2() # from Foo.f2 from Foo.f1
'''单继承的属性查找顺序:
1.先从对象自己的名称空间中查找
2.找不到再从产生这个对象的类中查找
3.类中找不到再去继承的父类中查找
4.一直找到没有父类为止,再找不到就报错了'''
5.多继承下的属性查找
# 5.1 非菱形结构:查找时,按括号中从左到右的顺序依次查找到各父类分支的尽头直到找到
# 5.2 菱形结构:被继承的多个类最终都会汇聚到一个点上。经典类与新式类有不同MRO,分别对 应属性的2种查找方式:深度优先、广度优先
1.经典类:深度优先,第一个分支就直接到最终的父类,只查一次(没有object类)py2
2.新式类:广度优先,最后一个分支才查找最终的父类,只查一次(有object类)py3
'''实际工作中,能用单继承实现的就尽量不要使用多继承'''
class G(object):
# def test(self):
# print('from G')
pass
class E(G):
# def test(self):
# print('from E')
pass
class F(G):
# def test(self):
# print('from F')
pass
class B(E):
# def test(self):
# print('from B')
pass
class C(F):
# def test(self):
# print('from C')
pass
class D(G):
# def test(self):
# print('from D')
pass
class A(B, C, D):
# def test(self):
# print('from A')
pass
obj = A()
obj.test() # A-B-E-C-F-D-G-Object-报错
6.super关键字和MRO列表
class People():
school = 'SH'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Student(People):
def __init__(self, name, age, gender, course=None):
if course is None:
course = []
# People(name, age, gender)
# 1.指名道姓的调用方法
# People.__init__(self, name, age, gender) 这样的调用方式,其实是不依赖于继承的
2.'''super(Student, self) 返回的是一个特殊对象'''py2的写法,py3不需要参数
super(Student, self).__init__(name, age, gender) # 不能说继承的就是父类,不严谨
3.
super().__init__(name, age, gender)
self.courses = course
def choose_course(self):
pass
########################################################
class A:
def test(self):
super().test()
class B:
def test(self):
print('from B')
class C(B, A):
pass
c = C()
c.test()
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
# [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
print(C.mro()) # 查看C类的mro列表
'''查看一个类的mro列表, 看一个类的mro列表,要从起始类开始看,底层C3线性算法
输出mro列表:类名.mro();类名.__mro__'''
# 3.多态和多态性[鸭子类型]
多态:面向对象的三大特征之一,一种事物的多种形态
'''父类中如何限制子类中的方法名,父类中定义的方法名,在子类中一定要有,哪怕是空'''
import abc # abstract class 抽象类
# 抽象类的特点:只能被继承了,不能被实例化,父类可以强制限制子类的行为
class Animal(metaclass=abc.ABCMeta): # 这个类就变成了抽象类
@abc.abstractmethod
def speak(self): # 类里面的方法就变成了抽象方法
pass # 不写具体的功能
'''用处:防止你漏写某种功能'''
'''抽象类的这种写法,python不建议写,py崇尚的是鸭子类型的写法'''
鸭子类型:一种动态编程风格,不用关心对象是什么类型,不使用type或者isinstance查出类型,只关心行为[方法和属性],可以用抽象基类来补充。允许我们再调用方法时,只要对象拥有这个方法,我们就可以当成参数传过去,而无需关心类型
class People():
def speak(self):
pass
class Pig():
def speak(self):
pass
class Dog():
def speak(self):
pass
obj = People()
obj1 = Pig()
obj2 = Dog()
'''约定俗成,不强制'''
'''多态带来的特性:再不考虑对象具体的类型下,直接调用对应的方法或者属性'''
10.组合[掌握]
# 什么是组合?
组合就是一个对象拥有一个属性,该属性的值是另外一个对象
class Foo():
def __init__(self,m):
self.m = m
class Bar():
def __init__(self,n):
self.n = n
obj = Foo(10)
obj1 = Bar(20)
obj.x = obj1
'''这就是组合,此时的obj对象已经变成了超级对象,通过一个对象可以得到另外一个对象的值'''
obj.x.n
# 继承是满足什么是什么的关系才用,组合是满足什么有什么的关系
class People():
school = 'SH'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Course():
def __init__(self, name, period, price):
self.name = name
self.period = period
self.price = price
python=Course('python', '6mon', 30000)
linux=Course('linux', '5mon', 20000)
# print(python.name)
# print(python.price)
# print(python.period)
# print(linux.name)
# print(linux.price)
class Admin(People):
pass
class Student(People, Course):
def __init__(self, name, age, gender, course=None):
if course is None:
course = []
# python2中得写法
# super(Student, self).__init__(name, age, gender) # 不能说继承的就是父类,不严谨
# python3中得写法
super().__init__(name, age, gender)
self.courses = course
def choose_course(self):
pass
stu = Student('kevin',20, 'female')
stu.courses.append(python.name)
# stu.course = python
stu.courses.append(linux.name)
print(stu.courses)
# [python对象,linux对象]
# for course_obj in stu.courses:
# print(course_obj.name)
for course in stu.courses:
print(course)
class Teacher(People):
def __init__(self, name, age, gender, level):
super().__init__(name, age, gender)
self.level = level
def score(self):
pass
# stu = Student('kevin', 20, 'male')
tea = Teacher('ly', 10, 'male',10)
tea.course = python
print(tea.course.name)
print(tea.course.period)
print(tea.course.price)
11.魔术方法[魔法]
'''如何让学习魔法:仅需记住各个魔法的触发条件即可!'''
# 面向对象的内置方法就是魔术方法,即魔法
# 1.__init__
初始化方法,调用类的时候自动触发,里面有一个self参数,用来接收对象的
# 2.__str__ :打印或者输出对象的时候自动触发的方法,必须有返回值且为str,并且将其作为打印结果,否则抛出异常
# __repr__ :打印或者输出对象的时候自动触发的方法,必须有返回值且为str,并且将其作为打印结果,否则抛出异常
'''当__str__ __repr__同时存在的时候,前者优先级高于后者,且后者不再执行'''
class Student():
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return self.name
def __repr__(self):
return 'aaa'
stu = Student('kevin',20)
print(str(stu)) # kevin
print(repr(stu)) # aaa
print(stu) # kevin
# 3.__del__:1.删除对象的时候自动触发的方法 2.当程序全部执行完毕也会自动触发
class Student():
def __init__(self,name,age):
self.name = name
self.age = age
def __del__(self):
print('aaa')
stu = Student('kevin',20)
del stu # aaa
# 4.isinstance() :1.判断某个数据值是不是某个数据类型 2.判断一个对象是否是一个类的对象
# issubclass() :判断一个类是不是某一个类的子类
print(isinstance('abc',str)) # True
print(isinstance(stu,Student))
print(issubclass(Student,object)) # True
# 5.__doc__ :通过打印或者输出该类里的注释,该属性无法继承给子类
class Foo():
'''这是注释!'''
pass
class Bar(Foo):
pass
print(Foo.__doc__) # 这是注释!
print(Bar.__doc__) # None
# 6.__enter__ :
# __exit__ :
'''with open语句是上下文管理协议,特点是会自动关闭文件'''
class Open:
def __init__(self,name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
'''__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行'''
print('with中代码块执行完毕时执行我啊')
return True # 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
with Open('a.txt') as f:
print('=====>执行代码块')
# print(f,f.name)
# 面试题:with上下文管理器:
1.with可以进行上下文管理,最常见的就是打开文件with open,特点是自动打开关闭文件
2.只要出现with语句就会自动触发__enter__内置方法,然后继续执行with代码块里面的代码,执行完毕后会再次__exit__魔术方法
3.如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
# 7.__setattr__ :对象名.属性名 = 值,对象的属性不存在会自动触发该方法,key为属性名,value为属性值
# __delattr__ : del 对象名.属性名时自动触发
# __getattr__ : 对象名.属性名时,对象的属性不存在会自动触发该方法,item为不存在的属性名
class Foo:
x=1
def __init__(self,y):
self.y=y
def __getattr__(self, item):
print('----> from getattr:你找的属性不存在') #print(obj.z)=>None
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item)
obj = Foo(20)
# 8.__setitem__: 对象名[属性名]改值时会自动触发,key为属性名,value为值
# __getitem__: 对象名[属性名]取值时会自动触发
# __delitem__: del 对象名.[属性名]时自动触发
class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self, item): # item = 属性名
print(self.__dict__[item])
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item)
f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)
# 9.__call__ : 对象加括号会自动触发执行,后续课程flask框架源码的时候,__call__方法就是入口
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
12.反射
# 在py中,反射指的是'通过字符串来操作对象的属性'
涉及到四个内置函数的使用
1. getattr()
2. setattr()
3. delattr()
4. hasattr()
class Student():
school = 'SH'
def __init__(self,name):
aelf.name
def func(self):
print('from Student.func')
stu = Student('kevin')
1. getattr(obj,name,default=None)
res=getattr(stu, 'name') # kevin
res=getattr(stu, 'name1') # 当获取的属性不存在的时候,会报错
res=getattr(stu, 'name1', 666) # 如果给了第三个参数,当属性不存在的时候,第三个参数就是默认值
res = getattr(stu, 'func') # 如果是方法名,得到的结果就是方法的内存地址,要想执行,就要结果加括号
print(res) #内存地址
res() # from Student.func
2. setattr(x,y,v) # x.y = v
setattr(stu, 'x', '123') # 给对象增加属性, 属性名不存在的时候,增加属性
setattr(stu, 'name', '123') # 给对象增加属性,属性名存在的时候,修改属性
print(stu.__dict__) #{'x':'123','name':'123'}
3. delattr(x,y) #del x.y
delattr(stu, 'name')
print(stu.__dict__) #{}
4. hasattr(*args,**kwargs)
res=hasattr(stu, 'name1') #对象里是否有该属性
print(res) #False
'''补充,写模块'''
import time
time.sleep(3)
time=getattr(time, 'sleep')(3)
print(time) #<built-in function sleep> 内置函数
time(3) # time.time(3)
time = __import__('time') # 等同于import time
time.sleep(3)
random = __import__('random') # 等同于import random
res=random.randint(1, 9)
print(res)
# 反射的案例
class FtpServer:
def serve_forever(self):
while True:
inp = input('input your cmd>>: ').strip() # get a.txt
cmd, file = inp.split() # get a.txt
if hasattr(self, cmd): # 根据用户输入的cmd,判断对象self有无对应的方法属性
func = getattr(self, cmd) # 根据字符串cmd,获取对象self对应的方法属性
func(file)
def get(self, file):
print('Downloading %s...' % file)
def put(self, file):
print('Uploading %s...' % file)
server = FtpServer()
server.serve_forever()
13.异常
1. 什么是异常?
错误发生的信号,如果不对此异常做处理,异常后面的代码无法执行
2. 处理异常的完整语法结构
try:
pass
except 类型:
pass
else:
pass
finally:
pass
3. 主动抛出异常raise
#import abc
#class Animal(metaclass=abc.ABCMeta):
#@abc.abstractmethod
#def speak(self):
#pass
class Animal():
def speak(self):
raise Exception('必须实现speak方法') #父类限制子类经常用的方法
class People(Animal):
def speak(self):
pass
obj=People()
obj.speak()
4.自定义异常
class MyException(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self):
return self.msg
try:
raise MyException('类型错误')
except MyException as e:
print(e)
5. 断言:条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况
assert 1==2 #表达式一定为True
print(123) #抛错
d = {'username1':'kevin', 'age':20}
assert 'username' in d
print('21134243')
标签:__,name,0322,self,stu,面向对象编程,print,0316,def
From: https://www.cnblogs.com/10086upup/p/17241345.html