第六章:面向对象之OOP(第一部分)
1 面向对象的概述(Object Oriented,OO)
1.1 名词解释
OO(Object Oriented):面向对象
OOA(Object Oriented Analysis):面向对象的分析
OOD(Object Oriented Design):面向对象的设计
OOI(Object Oriented Implementation):面向对象的实现
OOP(Object Oriented Programming):面向对象的编程
OOA—OOD—OOI:面向对象的实现过程
1.2 类和对象的概念
类:
- 抽象概念,代表具有共性的某些事物的一个集合
- 定义类的时候要用关键字class
- 类中要包含两个内容
- 表明事物特征—属性(变量)
- 表明事物功能或者动作—成员方法(函数)
对象:
- 具体概念,代表单个个体的具体事物
1.3 类的基本实现
类的命名和声明:
- 约定俗成采用大驼峰(每个单词的首字母大写)来命名类,避开关键字以及和系统命名相似的命名
- 使用关键字 class来声明类
- 类由属性和方法构成,其他不允许出现
- 成员属性可以直接使用变量赋值,没有则用"None"
class MyStudent():
pass
注:命名类时,pass必须有,没有则报错
实例化类:
- 格式,变量 = 类名()
访问对象成员:
- 使用点操作,格式:obj.属性名(成员方法)
检查类和对象的所有成员(两个英文字符下的下划线)
- 检查对象所有成员,格式:obj.__dict__
- 检查类所有成员,格式:类名.__dict__
类的基本实现实例:
#声明第一个空类
class Student():
pass
#声明第二个类,学习Python的学生
class PythonStudent():
name = "None"
age = "19"
def homework(self): #此处self自动添加,类似Jaba和C中的this
print("I must do homework")
xiaoming = PythonStudent() #此处实例化一个对象
print(xiaoming.name)
print(xiaoming.age)
xiaoming.homework()
#检查类中的成员
print(PythonStudent.__dict__)
#检查对象中的成员
print(xiaoming.__dict__)
#此处打印出来为一个空的{},因为Python中如果对象中的成员变量没有改变属性的情况下,默认和实例化对象的类指向同一块内存,不会再次开辟空间
#用函数id即可鉴别类PythonStudent()中的成员变量和对象xiaoming中的成员变量是否是同一个
print(PythonStudent.name)
print(id(PythonStudent.name))
print("*" * 20)
print(xiaoming.name)
print(id(xiaoming.name))
#如果对象中的成员变量发生改变,则Python将会另开一片存储空间
print("*" * 20) #分割线
xiaoming.name = "xiaoming"
xiaoming.age = "16"
print(xiaoming.name)
print(id(xiaoming.name))
print(xiaoming.__dict__) #此处再次检查对象xiaoming中的成员,不再是空集
结果:
None
19
I must do homework
{'__module__': '__main__', 'name': 'None', 'age': '19', 'homework': <function PythonStudent.homework at 0x0000000002843488>, '__dict__': <attribute '__dict__' of 'PythonStudent' objects>, '__weakref__': <attribute '__weakref__' of 'PythonStudent' objects>, '__doc__': None}
{} #此处对象xiaoming和类实例PythonStudent指向同一块内存,不再单独开辟空间(可以这样理解)
None
5670648
********************
None
5670648 #用函数id判断对象xiaoming中的变量和类PythonStudent中的变量是同一个
********************
xiaoming #此处对象xiaoming中的变量发生了变化,对象xiaoming中的变量则不再指向类PythonStudent中的变量
42323888
{'name': 'xiaoming', 'age': '16'}
由上例对类和对象中的成员分析总结:
- 成员可以存储在类中,也可以存储在对象中
- 使用类创建对象的时候,类中的成员不会放进对象中,而是创建一个空的对象,但是对象指向类中的成员
- 通过对象对类中的成员进行修改或者增添时,会存储在对象中而不会修改类中的成员
1.4 关于self
- self在对象的方法中表示当前对象本身(不是很理解这句话,但是觉得很重要就copy下来了 ),如果通过对象调用类中的成员方法(成员函数),则对象会自动传入该方法(函数)中的第一个参数
- self不是关键字,只是一个用于接受变量的普通参数,理论上可以用任何普通变量代替
- 含有self的成员方法(函数)称为非绑定的类方法,类和对象都能访问,不含self的称为绑定的类方法,只能通过类来访问
- 使用类访问绑定的方法时,如果绑定类的方法中需要访问类中的成员,可以用__class__.成员名来访问
关于self的实例1:
class Student():
name = "dana"
age = "19"
def chinese(self):
self.name = "xiaoming"
self.age = 19
print(self.name)
print(self.age)
def english(f): #此处不用系统默认的self,用s代替self
f.name = "xiaohong"
f.age = 20
print(f.name)
print(f.age)
def usa():
print(__class__.name) #绑定类的方法需要访问类的成员时,可以用__class__.成员名来访问
print(__class__.age)
s = Student()
s.chinese() #使用对象调用类中的方法时,对象自动传入方法中的第一个参数
Student.chinese(s) #使用类调用类中的方法
print("*" * 20)
s.english() #用f替换了self之后,可以有同样的效果
print("*" * 20) #分割线
Student.usa() #使用类访问绑定类的方法
结果:
xiaoming
19
xiaoming
19
********************
xiaohong
20
********************
dana
19
关于self的实例2:(鸭子模型)
class A():
name = "xiaoming"
age = 19
def __init__(self): #此处为构造函数,每次实例化自动调用,后文会详解
self.name = "aaa"
self.age = 18
def say(self):
print(self.name)
print(self.age)
class B():
name = "xiaohong"
age = 21
a = A() #此处实例化,自动调用构造函数
a.say() #因此调用方法say时,输出为"aaa"和 18
A.say(a) #此处self被a替换
A.say(A) #同理,此处可将A传入做参数
A.say(B) #此时传入类B,因为B中含有相同的name和age属性,因此不会报错
结果:
aaa
18
aaa
18
xiaoming
19
xiaohong
21