一些概念
- 围绕函数来设计程序的过程,叫做面向过程编程;
- 而面向对象编程,就是将数据与功能进行组合,并将其包装在被称为对象的物体内。
- 类与对象是面向对象编程的两个重要方面。一个类(
class
)能够创建新的类型(type
),对象(object
)就是类的实例(instance
). - 对象可以使用它的普通变量来存储值,这个从属于对象或类的变量叫做字段
Field
- 对象还可以使用累的某些函数来做一些操作,这种函数叫做类的方法
Method
. - 字段和方法统称类的属性
- 字段有两种类型:属于一个类的各个实例或对象的叫做实例变量
Instance Variables
,属于某一个类的叫做类变量Class Variables
self
self
用于区分类方法与普通。
在类方法中,必须有一个额外的名字来添加到参数列表的开头,但是我们不用调用这个功能时就为这个参数进行赋值,Python会
为它提供。这种特定的变量引用的是对象本身,被特定命名为self
.
于是,我们可以知道,就算我们定义一个没有参数的类方法,它也是会有一个特定的参数self
.
(关于self不理解的,可以先放一下,等把接下来的学习一下之后再回过来看就会好很多)
创建一个类和方法并使用
# 创建一个类,使用 'class + 类名'的形式
class MyFirstClass:
# 类方法
def Class_Method_Test(self):
print('我是一个类方法')
# 实例化一个对象并输出相关信息
first = MyFirstClass()
print(first)
# 调用实例方法
first.Class_Method_Test()
输出结果
<__main__.MyFirstClass object at 0x1010ea438>
我是一个类方法
Process finished with exit code 0
具体的请参考注释。
__init__方法
__init__
方法会在一个类被实例化时立即调用,请参考下面的代码
# 使用__init__方法
class MyClassDemo:
# 调用init方法,并设置name,name2两个传入参数
def __init__(self,name,name2):
# 创建新字段name和myName接收和传递参数name、name2的值
print('3')
self.name = name
self.myName = name2
def getName(self):
# 在这里使用上面所创建新字段name、myName传递过来的值
print('4')
print('The name is:',self.name)
print('Other name is:',self.myName)
# 实例化对象,调用__init__方法,并传入两个参数的值
print('1')
demo = MyClassDemo('Ultraman Zero.','Ultraman Seven.')
# 调用类的方法
print('2')
demo.getName()
输出结果
1
3
2
4
The name is: Ultraman Zero.
Other name is: Ultraman Seven.
Process finished with exit code 0
从上面的输出,可以看出程序运行的次序为:实例化一个对象 --> 调用__init__方法 --> 实例对象调用类方法。
说明请参考注释。
类变量与对象变量
字段有两种形式:类变量与对象变量
类变量是共享的,它可以被这个类的所有实例对象使用,当一个实例对象对它做出变化时,这种变化将会体现到这个类的所有实例对象中。
对象变量由类的每一个单独的实例变量拥有,一个类的实例变量对它做出改变时,其它类的实例对象不会发生变化。对象变量不是共享的,每个对象都有属于它自己的字段的副本。
请参考下面的例子
class Reboot:
""" 创建一个类变量,用于计算数量 """
Population = 0;
"""
创建机器人的接口
每次创建一个机器人的实例对象,Population的值就会+1
"""
def __init__(self,name):
self.rebootName = name
print(self.rebootName,' is Initialazing......')
Reboot.Population += 1
# 每次销毁一个机器人,Population的数量就会-1
def reboot_die(self):
print(self.rebootName,' is being destorying....')
Reboot.Population -= 1
print('Now Reboot population = ',Reboot.Population)
if Reboot.Population < 1:
print('We have no Reboot.')
else:
print('We still have {:d} Reboots'.format(Reboot.Population))
def say_hi(self):
print("Hello,I'm {}".format(self.rebootName))
# 使用装饰器Decorator来将方法标记为类方法
# 使用装饰器等价于调用 how_manay=classmethod(how_manay)
@classmethod
def how_manay(cls):
print("We have {:d} reboots".format(cls.Population))
reboot0 = Reboot('Yiwa')
reboot0.say_hi()
print('\n')
reboot1 = Reboot('Yiwa1')
reboot1.say_hi()
print('\n')
reboot0.reboot_die()
Reboot.how_manay()
- 说明,如上代码,我们除了可以使用
Reboot.Population
之外,还可以使用self.__class_.Population
,因为每个对象都通过self.__class_.Population
来引用它的类。 - 还有,我们只能通过
self
来引用同一对象的变量和方法。这种叫做属性引用。 - 在Python中,所有类成员,包括数据成员都是公开的,所有方法都是虚拟的。
- 我们还可以通过在数据成员名称前面加"
__
"双下划线前缀,这是Python
会使用命名调整来使其成为一个私有变量。因此,我们需要遵循一个约定,所有在类或对象之中使用的变量,其命名应以下划线开头,其它所有非此格式的变量都是公开的,并且能被其它任何类或对象使用。 除了双下划线这点,Python
并不会强制这样做。
继承一个类
面向对象的一个优点就是代码重用(Reuse
)。重用的一种实现方式就是通过继承机制(Inheritance
)。继承是在类之间实现类型(Type
)与子类型(Subtype
)的工具。
请看下面的例子
# base class
class SchoolManager:
# 共有的属性 name age
def __init__(self,name,age):
self.userName = name
self.userAge = age
def tellMe(self):
print("Initialztion manaher:{},age:{}".format(self.userName,self.userAge))
# subclass
class Teacher(SchoolManager):
# salary 子类私有属性
def __init__(self,name,age,salary):
SchoolManager.__init__(self,name,age)
self.userSalary = salary
print("Iniyialzation teacher,name:{},age:{}.salary:{}".format(self.userName,self.userAge,self.userSalary))
def tellMe(self):
# 这时候会调用一次基类的初始化方法
SchoolManager.tellMe(self)
print("{} salary is {}".format(self.userName,self.userAge))
# subclass
class Student(SchoolManager):
# grade子类私有属性
def __init__(self,name,age,grade):
SchoolManager.__init__(self,name,age)
self.userGrade = grade
print("Initialzation student,name:{},age:{},grade:{}".format(self.userName,self.userAge,self.userGrade))
def tellMe(self):
# 这时候会调用一次基类的初始化方法
SchoolManager.tellMe(self)
print("{} grade is {}".format(self.userName,self.userGrade))
teacher = Teacher("mR.XXOO",18,45000)
student = Student("Tom",25,99)
print("\n")
member = [teacher,student]
for m in member:
m.tellMe()
print("\n")
输出结果
Iniyialzation teacher,name:mR.XXOO,age:18.salary:45000
Initialzation student,name:Tom,age:25,grade:99
Initialztion manaher:mR.XXOO,age:18
mR.XXOO salary is 18
Initialztion manaher:Tom,age:25
Tom grade is 99
Process finished with exit code 0
如上,我们对SchoolManager
做出改变时,这种改变会反映到所有子类中,但是对Teacher
或Student
这两个子类中的一个做出改变时都不会影响到其它子类。另外,Teacher
和Student
可以被看做SchoolManager
的对象加以引用。这被称为多态(Polymorphism
)
我们重用父类中的代码,不需要在其它子类中重复这些代码。但是,当我们使用独立类型时,才可以重复使用这些代码。
当继承元组中有多个类时,称为多继承或多重继承,如class Teacher(SchoolManager,UserOperation):
。