Python3基础-面向对象编程
类的定义与实例化
语法格式如下:
class ClassName: <statement-1> . . . <statement-N>
类:用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
对象: 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
实例
class student: info_stu = "打印学生的信息" #公开变量 内部类或外部类使用 student.info_stu 访问 empcount = 0 #公开变量 内部类或外部类使用 student.empCount 访问 #该方法汇总对象产生之后自动执行,专门为对象进行初始化操作,可以有任意倒霉,但一定不能返回非None的值 def __init__(self,name,sex,age): self.name= name self.sex = sex self.age = age student.empcount += 1 #self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。 def info(self): print("我是info函数") return "姓名:%s, 性别:%s,年龄:%s"%(self.name,self.sex,self.age) def displaycount(self): print("Total empcount %d"%student.empcount) #实例化类 stu1 = student('susu','女','19') #每实例化一个student类就得到一个学生对象 #调用类的过程成为将类实例化,拿到的返回值就是程序中的对象,或称为一个实例 #访问类的属性和方法 print("student 类的属性 info_stu为:",stu1.info_stu) print("student 类的方法 info为:",stu1.info())
self 代表类的实例,而非类
class test: def test1(self): print(self) print(self.__class__) #print(test.__dict__) t=test() print(t) t.test1() """ 以上执行结果为 <__main__.test object at 0x03890F30> <__main__.test object at 0x03890F30> <class '__main__.test'> """
self 代表的是类的实例,代表当前对象的地址,而 self.__class__ 则指向类。
self 不是 python 关键字,我们把他换成 pselef 也是可以正常执行的
class test: def test1(pself): print(pself) print(pself.__class__) t=test() t.test1() """ 以上执行结果为 <__main__.test object at 0x005B0F90> <class '__main__.test'> """
类对象
类对象支持两种操作:属性引用和实例化
类体的代码在类定义阶段执行,因而会产生新的名称空间用来存放类中定义的名字,可以打印student.__dict__ 来查看这个容器盛放的东西
print(student.__dict__) {'__module__': '__main__', 'info_stu': '打印学生的信息', '__init__': <function student.__init__ at 0x01C15810>, 'info': <function student.info at 0x01C15858>, '__dict__': <attribute '__dict__' of 'student' objects>, '__weakref__': <attribute '__weakref__' of 'student' objects>, '__doc__': None}
stu1=student('susu','女','19'),调用类会产生一个空对象stu1,然后将stu1连同调用类时括号内的参数一起传给student.__init__('susu','女','19') 会产生对象的名称空间,同样可以用__dict__查看
print("stu1.__dict__",stu1.__dict__) print("stu1:",stu1) """ 执行结果 stu1.__dict__ {'name': 'susu', 'sex': '女', 'age': '19'} stu1: <__main__.student object at 0x037E0130> """
属性访问
类属性与对象属性
类的属性:在类中定义的名字,都是类的属性
类的属性,分为两种:
1、数据属性:就是变量
2、函数属性:就是函数,在面向对象称为方法
注意:类和对象均用 . 来访问自己的属性
类属性
print(student.info_stu) #student.__dict__['info_stu'] print(student.info) #student.__dict__['info']
执行结果如下:
打印学生的信息 <function student.info at 0x00A55858>
对象属性
print("student 类的属性 info_stu为:",stu1.info_stu) # stu1.__dict__['name'] print("student 类的方法 info为:",stu1.info) #stu1.__dict__['info']
执行结果如下:
student 类的属性 info_stu为: 打印学生的信息 student 类的方法 info为: <bound method student.info of <__main__.student object at 0x00930F10>>
内置属性
print(student.__name__) #打印类名 print(student.__doc__) #打印类的文档字符串 print(student.__bases__) #类的所有福利构成元素(包含了一个由所有父类组成的元祖) print(student.__dict__) #类的属性(包含一个字典,由类的数据属性组成) print(student.__module__) #类定义所在的模块 (类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod) print(student.__class__) #类型
=======================================================================================================================================================
实例
class student: '学生的信息' info_stu = "打印学生的信息" empcount = 0 def __init__(self,name,sex,age): self.name= name self.sex = sex self.age = age student.empcount += 1 #self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。 def info(self): print("姓名:%s, 性别:%s,年龄:%s"%(self.name,self.sex,self.age)) def displaycount(self): print("Total empcount %d"%student.empcount) #创建student 类的第一个对象 stu1 = student('susu','女','19') #创建student 类的第二个对象 stu2 = student('sush','男','29') stu1.displaycount() stu2.displaycount() stu1.info() stu2.info() print("Total empcount :",student.empcount)
以上执行代码执行输出结果
Total empcount 2 Total empcount 2 姓名:susu, 性别:女,年龄:19 姓名:sush, 性别:男,年龄:29 Total empcount : 2
添加、删除,修改类的属性
stu1.grade = 3 #添加一个‘grade ’的属性 stu1.grade =4 #修改‘grade ’的属性 print(hasattr(stu1, 'grade')) #存在‘grade’属性返回True print(getattr(stu1, 'grade')) #获取 ‘grade’的值 print(setattr(stu1, 'mark',77)) #添加属性‘mark’ 值为77 print(getattr(stu1, 'mark')) #获取 ‘mark’的值 print(delattr(stu1, 'mark')) #删除属性 del stu1.grade print(hasattr(stu1, 'grade')) #存在‘grade’属性返回True
#在实例新增属性后,并不会同步到类属性里面 class student: country='china' def __init__(self,name): self.name = name def play_ball(self,ball): print('%s 正在打 %s'%(self.name,ball)) p1=student('susu') print(p1.country) p1.country = '日本' print(p1.__dict__) print(student.__dict__) print('类的属性---》',student.country) print('实例的属性---》',p1.country) """ 执行结果如下: china {'name': 'susu', 'country': '日本'} {'__module__': '__main__', 'country': 'china', '__init__': <function student.__init__ at 0x007E5978>, 'play_ball': <function student.play_ball at 0x007E59C0>, '__dict__': <attribute '__dict__' of 'student' objects>, '__weakref__': <attribute '__weakref__' of 'student' objects>, '__doc__': None} 类的属性---》 china 实例的属性---》 日本 """
属性查找顺序与绑定方法
1、对象的名称空间里只存放着对象独有的属性,而对象们相似的属性是存放于类中
2、对象在访问出现时,会优先从对象本身的__dict__中查找;未找到,则去类的__dict__中查找
1、类中的定义的变量是类的数据属性,是共享给所有对象用的,指向相同的内存地址
#创建student 类的第一个对象 stu1 = student('susu','女','19') #创建student 类的第二个对象 stu2 = student('sush','男','29') #id 都一样 print(id(student.empcount)) #265839808 print(id(stu1.empcount)) #265839808 print(id(stu2.empcount)) #265839808
2、类中定义的函数是类的函数属性,类可以使用
#创建student 类的第一个对象
stu1 = student('susu','女','19')
#创建student 类的第二个对象
stu2 = student('sush','男','29')
#类的属性 student.info(stu1) #输出姓名:susu, 性别:女,年龄:19 student.info(stu2) #输出 姓名:sush, 性别:男,年龄:29
类属性、实例属性与外部变量的作用域
country = 'china' class student: def __init__(self,name): self.name = name print('--->',country) #输出外部变量country的值 def play_ball(self,ball): print('%s 正在打 %s'%(self.name,ball)) p1=student('susu')
以上代码执行结果如下:
---> china
修改外部变量country的值 --情况1
country = 'china' class student: print('未修改的country', country) country = '日本' print('修改后的country',country) def __init__(self,name): self.name = name #print('--->',country) def play_ball(self,ball): print('%s 正在打 %s'%(self.name,ball)) p1=student('susu') print(student.__dict__) print(student.country)
以上执行结果如下:
未修改的country china 修改后的country 日本 {'__module__': '__main__', 'country': '日本', '__init__': <function student.__init__ at 0x008859C0>, 'play_ball': <function student.play_ball at 0x00885A08>, '__dict__': <attribute '__dict__' of 'student' objects>, '__weakref__': <attribute '__weakref__' of 'student' objects>, '__doc__': None} 日本
修改外部变量country的值 --情况2
country = 'china' class student: def __init__(self,name,country): self.name = name print("__init__未修改的:", country) #输出的是 china self.country = '日本' def play_ball(self): print("未修改的:",country) #可输出的是china country = 1 #print("修改后的:", country) p1=student('susu','china') print("p1.country",p1.country) #输出的是 日本 print(country) #输出的是 china print(p1.play_ball())
以上代码执行结果会出现报错:
Traceback (most recent call last): File "D:/pyAuto/pythonDay/pythonbase/classtest.py", line 151, in <module> print(p1.play_ball()) File "D:/pyAuto/pythonDay/pythonbase/classtest.py", line 143, in play_ball print("未修改的:",country) #可输出的是china UnboundLocalError: local variable 'country' referenced before assignment
python中出现了没有声明的变量 , py是通过如下简单的规则找出变量的范围 :如果函数内部有对变量的赋值 ,则该变量被认为是本地的,此时可以正常修改。但是若变量不定义在函数内部,且没有进行变量范围的声明(去调用外部变量),程序在函数内部找不到相应变量,所以会出现未定义变量的错误提示消息
修改如下:
country = 'china' class student: def __init__(self,name,country): self.name = name print("__init__未修改的:", country) #输出的是 china self.country = '日本' def play_ball(self): global country print("未修改的:",country) #输出的是china country = 1 print("修改后的:", country) #输出的是1 p1=student('susu','china') print("p1.country",p1.country) #输出的是 日本 print(country) #输出的是 china p1.play_ball() print(country) #输出的是 1
修改外部变量country的值 --情况3
country = 'china' class student: country = '日本' def __init__(self,name): self.name = name print("__init__未修改的:", country) #输出的是 china p1=student('susu') print("p1.country",p1.country) #输出的是 日本、 """ 以上代码执行结果如下 __init__未修改的: china p1.country 日本 """ #======要想在?__init__里面输出类属性 contry country = 'china' class student: country = '日本' def __init__(self,name): self.name = name print("__init__未修改的:", country) #输出的是 china print("__init__未修改的:", student.country) # 输出的是 日本 p1=student('susu') print("p1.country",p1.country) #输出的是 日本 """ __init__未修改的: china __init__未修改的: 日本 p1.country 日本 """