一.面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法:类中定义的函数。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
注意:
类的名称,首字母最好使用大写字母,例如:StudentHomework
类的基本作用:封装
类的内部不能调用,和使用方法
二.创建一个类
在类里面的函数,没有形参时,需要在括号中加入self,同时函数调用类中的变量,也需要添加self,例如print(self.name)
class Student():
name = ''
age = 0
def print_file(self):
print('name:' + self.name) # 调用类里面的方法,参数需要加上self
print('age:' + str(self.age))
student = Student() # 实例化
student.print_file() # 调用类里面的方法
输出结果
name:
age:0
注:
1.执行类,需要将类实例化,例如student = Student()
2.不可以在类中,直接调用函数
3.不建议将类,和执行代码放在同一个模块下
三.调用类
在其他模块中调用类,例如from class_study import Student,同样在其他模块执行时,也需要实例化
from class_study import Student # 调用类
student = Student()
student.print_file()
输出结果
name:
age:0
name:
age:0
四.构造函数__init__
常识
# 类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起 # 类相当于模板,里面可以有很多不同的对象
# python魔法方法:__init__( )方法,被称为构造方法。__init__()方法的魔力体现在只要实例化一个对象,这个方法就会在对象被创建时自动调用。实例化对象时是可以传入参数的,这些参数会自动传入__init__()方法中,可以通过重写这个方法来自定义对象的初始化操作。
1.一个类里面,可存在多个对象
代码段
class Student():
name = ''
age = 0
def do_homework(self):
print('homework')
student1 = Student()
student2 = Student()
student3 = Student()
# 打印内存地址
print(id(student1))
print(id(student2)) # 查看内存地址
print(id(student3))
输出结果:虽然输出结果是一样,但是内存地址不一样
1528568316032
1528568316256
1528568317936
2.使用构造函数,定义不同的对象
代码段
class Student():
name = ''
age = 0
def __init__(self,name,age): # __init__构造函数
print("student")
return None # 增加return也只能返回None,否则为报错
# 行为 与 特征
def do_homework(self):
print('homework')
student1 = Student('joy',18) # 如果不使用构造函数__init__,括号中传入实参就会报错
输出结果:
student
注意:
函数中不加return,返回结果为None
类被实例化后,构造函数会自动执行,无需再次调用
class Student():
name = ''
age = 0
def __init__(self): # __init__构造函数
print("student")
student1 = Student()
a = student1.__init__() # 没有return,返回结果为 None
print(a)
输出结果
student # 加了构造函数,python会自己调用构造函数
student
None
五.类变量和实例变量
实例变量,需要在变量前面增加self
使用__dict__方法,查看类或者实例下面有哪些变量,
# 构造函数
class StudentTables():
# 类变量
name = '章鱼哥'
age = 0
def __init__(self,name,age):
# 实例变量,需要在变量前面增加self
self.name = name
self.age = age
def do_homework(self):
print('homework')
# 类被实例化后,构造函数 __init__会自动执行,无需再次调用 #
student01 = StudentTables('江小妮',19)
student02 = StudentTables('王尼玛',28)
# 打印实例变量
print(student01.name)
print(student02.name)
# 打印类变量
print(StudentTables.name)
# 查看类下面的变量
print('类下面的变量:',student01.__dict__)
# 查看实例下的变量
print('实例下面的变量:',StudentTables.__dict__)
结果
小妮
王尼玛
章鱼哥
类下面的变量: {'name': '江小妮', 'age': 19}
实例下面的变量: {'__module__': '__main__', 'name': '章鱼哥', 'age': 0, '__init__': <function StudentTables.__init__ at 0x10f286830>, 'do_homework': <function StudentTables.do_homework at 0x10f2868c0>, '__dict__': <attribute '__dict__' of 'StudentTables' objects>, '__weakref__': <attribute '__weakref__' of 'StudentTables' objects>, '__doc__': None}
六.在实例方法中,访问类变量
在方法中打印类变量的两种方式
class ClassVariable():
sum01 = 88
def __init__(self):
# 在方法中打印类变量的两种方式
# 1.使用类名,直接调用
print(ClassVariable.sum01)
# 2.使用__class__方法调用
print(self.__class__.sum01)
classvariable = ClassVariable()
结果
88
88
七.类方法
@classmethod必须位于方法上面一行
第一个cls必须有;cls指的就是“类对象”本身
调用类方法格式:类名.类方法名(参数列表)。 参数列表中,不需要也不能给cls传值
类方法中访问实例属性和实例方法会导致错误
子类继承父类方法时,传入cls是子类对象,而非父类对象
class Archives():
sum01 = 0
# 构造函数实例方法
def __init__(self,name,age):
self.name = name
self.age = age
# 实例方法
def do_homework(self):
print('实例方法操作类变量1:',Archives.sum01)
print('实例方法操作类变量2:',self.__class__.sum01)
# 类方法,需要增加装饰器classmethod
@classmethod
def plus_sum01(cls):
cls.sum01 += 1
print('类方法操作类变量:',cls.sum01)
archives = Archives('章鱼哥',18)
# 在实例方法中访问类变量
archives.do_homework()
# 调用类方法的两种方式
Archives.plus_sum01()
archives.plus_sum01()
结果
实例方法操作类变量1: 0
实例方法操作类变量2: 0
类方法操作类变量: 1
类方法操作类变量: 2
八.静态方法
Python中允许定义与“类对象”无关的方法,称为“静态方法”。
“静态方法”和在模块中定义普通函数没有区别,只不过“静态方法”放到了“类的名字空间里面”,需要通过“类调用”。
静态方法通过装饰器@staticmethod来定义,格式如下:
# 静态方法
class StaticStudy():
sum01 = 22
def the_sum(self,i):
self.e = i
print(self.e)
@classmethod
def the_file(cls):
cls.size = '3M'
print(cls.size)
@staticmethod
def add(x,y):
total = x*y
print(total)
# 在静态方法中打印类变量
print(StaticStudy.sum01)
staticstudy = StaticStudy()
# 调用实例方法
# staticstudy.the_sum(2222)
# # 调用类方法
# staticstudy.the_file()
# 调用静态方法
staticstudy.add(8,8)
StaticStudy.add(9,9)
64
22
81
22
九.成员可见性
私有方法,在类的外部不能直接调用
私有方法,需要在方法名前面增加“__“
私有方法,只能在类的内部使用
# 私有方法,在类的外部不能直接调用
class Member01 ():
name = '章鱼哥'
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
# 私有方法,需要在方法名前面增加“__“
def __marking(self,score):
if score < 0:
return '分数不正确'
self.score = score
print(self.name + '同学本次考试分数为:'+ str(self.score))
member01 = Member01('章鱼哥',19)
# 直接调用私有方法,执行时会报错 'Member01' object has no attribute 'marking'
result = member01.marking(-1)
print(result)
结果
AttributeError: 'Member01' object has no attribute 'marking'
私有变量,外部打印会直接报错
私有变量,需要在变量名前面增加“__”
私有变量,在外部赋值,会动态新增一个变量,例如:_Member02__score
私有变量,只能通过类的内部调用
class Member02 ():
name = '章鱼哥'
age = 0
def __init__(self,name,age):
self.name = name
self.age = age
def marking(self,score):
if score < 0:
return '分数不正确'
# 私有变量同样也需要在变量名前增加“__”
self.__score = score
print(self.name + '同学本次考试分数为:'+ str(self.__score))
member02 = Member02('章鱼哥',19)
member02.marking(88)
# 注意:这种方式不是将变量赋值,而是动态增加了一个变量
member02.__score = 33
# 私有变量,外部打印会直接报错
''' member03 = Member02('陈大米',19)
print(member03.__score) '''
# 使用__dict__方法查看实例方法下的变量,结果会增加__score的变量
print(member02.__dict__)
结果
章鱼哥同学本次考试分数为:88
{'name': '章鱼哥', 'age': 19, '_Member02__score': 88, '__score': 33}
十.继承
1.继承
父类执行代码
class Human():
sum = 0
def __init__(self,name,age):
self.name = name
self.age = age
def get_name(self):
print('陈大方')
def do_homework(self):
print('This is a parent method')
继承父类需要使用import导入,并在子类中传入父类名。
继承多个父类时,在()中增加多个父类名称,例如:class StudentArchives(Human,Student):
from class_study06 import Human
# 调用父级类变量、实例变量、实例方法
class StudentArchives(Human):
def do_homework(self):
print("English Homework")
studentarchives = StudentArchives('章鱼哥',18)
2.调用
调用父级类变量、实例变量、实例方法
from class_study06 import Human
# 调用父级类变量、实例变量、实例方法
class StudentArchives(Human):
def do_homework(self):
print("English Homework")
studentarchives = StudentArchives('章鱼哥',18)
# 调用父级类变量的两种方式
print(studentarchives.sum)
print(StudentArchives.sum)
# 调用父级实例变量
print(studentarchives.name)
# 调用父级实例方法
studentarchives.get_name()
结果
0
0
章鱼哥
陈大方
3.调用父级实例变量
在实例方法中,初始化赋值父级实例变量,未初始化会导致报错
# 在实例方法中,初始化赋值父级实例变量
class StudentArchives(Human):
def __init__(self,school,name,age):
self.school = school
# 调用父级实例变量,并初始化需要使用__init__方法,形参需要加上self
Human.__init__(self,name,age)
studentarchives = StudentArchives('希望小学','章鱼哥',18)
print(studentarchives.school)
print(studentarchives.name)
print(studentarchives.age)
结果
希望小学
章鱼哥
18
4.调用父级实例方法
使用super关键字调用父级实例方法,初始化赋值父级实例变量
class StudentArchives(Human):
def __init__(self,school,name,age):
self.school = school
# 使用super关键字调用父级实例方法,初始化赋值父级实例变量
super(StudentArchives,self).__init__(name,age)
def do_homework(self):
super(StudentArchives,self).do_homework()
print('english homework')
studentarchives = StudentArchives('希望小学','章鱼哥',18)
print(studentarchives.name)
studentarchives.do_homework()
结果
章鱼哥
This is a parent method
english homework