文章目录
- 面向对象
- 特征
- 封装
- 继承
- 多态
- 具体实现
- 创建一个类
- 继承这个类
- 类属性
- 类方法
- 静态方法
- 总结
面向对象
Python是一门既可以面向过程,又能面向对象的语言,对于面向对象的语言都有三大共同的基本特征:
- 封装
- 继承
- 多态
特征
封装
封装就是把所创建的对象的各种属性和方法都给隐藏起来,仅仅对外公开调用接口,它的目的是为了增强程序的安全性和简化编程,使用的人不需要了解具体的实现细节,只以特定的访问权限来使用类的成员。
继承
继承就是子类继承父类的特征和行为,使得子类对象能够具有父类的各种属性与方法。
举个例子,假设我们创建了一个名叫“人”的大类,它有自己的一些属性和方法,也可以理解为特征和行为,比如每个“人”的对象都能够说话,也都有胳膊有腿有身体,然后呢,我们又创建了这个类的两个子类,分别为“男人”和“女人”,这两个类是继承前边那个“人”的大类,也都能说话有身体等,但它们也会有一些自己具有的其它的特征,比如男人有一个属性是具有喉结而女人没有,而在“人”的那个大类里面我们并没有给出这个属性,其它的不在举例了,就是这么个意思。那如果是多重继承呢,比如我们又创建了一个类,这个类就单纯指我女朋友,那么她这个类肯定是继承了“女人”那个类,而间接也继承了“人”的那个大类,她也拥有自己的属性,比如喜欢我。这也就是继承中的多重继承,当然,一个类是可以无限被继承下去的。
多态
多态实际上是在继承的基础上的,它存在有三个必要条件:
- 继承
- 重写(子类继承父类后对父类方法进行重新定义)
- 父类引用指向子类对象
继承大家明白了,而重写指的是子类继承父类后对父类方法进行重新定义,比如前边的例子“人”的大类,假设它有一个属性是身高,其为一个常数175cm,而“男人”和“女人”这两个类都有自己的身高范围,假设这两个类的身高属性是一个数值范围,就不是175cm了,我们在构造这两个类的时候就需要把父类的身高属性给重写了,再往下继承到我对象的时候就得是一个确定的数值了,又把父类这个属性给重写了。
第三点举个简单例子就是如“女人”这个类,它不但是“人”的子类,也是我“对象”的父类,也就是它既充当了子类也充当了父类,这也是多态的一种表现。
具体实现
创建一个类
下面呢,我们就以刚才的例子用代码给大致实现一下,同时学习面向对象的使用方法。
#创建一个名为Person的类
class Person():
def __inin__(self,name,age):
self.name = name
self.age = age
self.height = 175
def introduce(self)
print('我叫{},我{}岁了,我的身高是{}cm。'.format(self.name,self.age,self.height))
上面的几行代码我们就创造了一个简单的类Person,其中__init__是这个类的构造方法,introduce是这个类的一个实例方法,其中的语句分别为该方法的属性,很简单可以明白,在我们每构造一个对象Person的时候,它都会有名字,年龄,以及默认的身高。
在我们每次创建一个Person对象时,首先都会调用这个类的构造方法,而构造方法中的self指代的是当前的对象,它其实没有什么别的含义,唯一的含义指的就是当前的对象,而后边的name和age为构造属性,这个也就是每一个新对象都会拥有的,也需要我们传入相应的参数,后边的实例方法introduce中的self也指的是当前的对象,这个类中不管哪的self,都是指当前的对象,这个实例方法是没有参数的,调用的时候直接介绍自己的信息,调用示例如下:
person = Person('常康宁',20) #创建一个Person对象
person.introduce() #调用此介绍方法
#输出
我叫常康宁,我20岁了,我的身高是175cm。
继承这个类
上面的代码已经有了就不再写了,直接接上即可,接下来创建“Man”和“Woman”这两个Person的子类。
class Man(Person):
def __inin__(self,name,age):
super().__init__(name,age)
self.mustache = 0.1
class Woman(Person):
def __init__(self,name,age)
super().__init__(name,age)
self.mustache = 0.001
这样我们就创建了两个Person的子类,分别为男人和女人,它们都继承了Person,代码中的super().__init__(name,age)
就是代表该构造方法中的两个参数都继承自其父类Person,这两个类不同的一点就是分别拥有自己的mustache属性,也就是胡子,男人胡子长度为0.1,女人为0.001,调用一下看看结果:
person = Man('常康宁',20) #此处的对象已经成了Man
person.introduce()
print(person.mustache)
#输出n
我叫常康宁,我20岁了,我的身高是175cm。
0.1
可以看出来,身为Person子类的Man,即使其内部没有introduce方法,其照样可以使用,毕竟它是从Person继承来的嘛,可以认为父类有的,子类都有都能用,当然如果你选的对象是Woman,则后面输出为0.001。这样我们就完成了简单的继承,当然,也可以多重继承:
class girlfriend(Woman): #构造一个新类,继承自Woman
def __init__(self,name,age):
self.height = 165
def speak(self):
print('我是常康宁的女朋友~')
这个时候的girlfriend类继承了Woman,并且专门有一个speak方法,而我们知道Woman是继承自Person的,那么Person的的属性和方法girlfriend有没有呢,答案是当然有!我们调用看看。
person = girlfriend('小美',20)
person.introduce()
person.speak()
#输出
我叫小美,我20岁了,我的身高是165cm。
我是常康宁的女朋友~
从这里我们可以看到Person中的方法girlfriend也可以调用,这也就是多重继承了。
类属性
我们前边已经有了很多属性了,每一个属性都包含在各方法里面,每个类里面都是只有那些实例方法和实例属性,却没有类属性,类属性是什么呢,简单来讲和实例属性是差不多的,但是它和类中的方法是同一级,不被包含,如我们现在在Person中添加一个类属性,对前边代码稍作修改:
class Person():
num_of_Person = 0 #此为类属性
def __inin__(self,name,age):
self.name = name
self.age = age
self.height = 175
Person.num_of_Person +=1
def introduce(self)
print('我叫{},我{}岁了,我的身高是{}cm。'.format(self.name,self.age,self.height))
这样的话我们就在源代码中加了一个类属性,它属于这个类,而不单独属于某个方法,同时在Person的构造方法中加了一行Person.num_of_Person
,则在每次调用此构造方法的时候num_of_Person的数量都会加一,其数量也就代表了有多少各Person。例如:
person1 = Man('常康宁',20)
person2 = girlfriend('小美',20)
person1.introduce()
person2.introduce()
person2.speak()
print(Person.num_of_Person)
#输出
我叫常康宁,我20岁了,我的身高是175cm。
我叫小美,我20岁了,我的身高是165cm。
我是常康宁的女朋友~
2
类方法
类方法的创建和实例方法的创建不太一样,前边我们创建类中除了构造方法以外的方法都是实例方法,结合前边的代码做一些修改给出类方法的创建格式:
class Person():
Person_list = [] #类属性
#下面是类方法的创建格式
@classmethod
def nums_of_Person(cls):
return len(cls.Person_list)
def __init__(self,name,age):
self.name = name
self.age = age
self.height = 175
Person.Person_list.append(self)
def introduce(self):
print('我叫{},我{}岁了,我的身高是{}cm。'.format(self.name,self.age,self.height))
由示例我们可以看出,类方法的创建首先需要@classmethod
的声明,然后在方法中的参数默认为cls
,这个cls指的是当前的类对象,实际上cls和self都差不多,它们也可以不用这个名字,只不过大家默认如此,方便各个同行写的代码相互流通。然后调用一下:
person1 = Man('常康宁',20)
person2 = girlfriend('小美',20)
person1.introduce()
person2.introduce()
person2.speak()
print(Person.nums_of_Person())
#输出
我叫常康宁,我20岁了,我的身高是175cm。
我叫小美,我20岁了,我的身高是165cm。
我是常康宁的女朋友~
2
输出和前边是一样的,只不过这个类属性Person_list是一个包含了创建所有对象的列表,对其输出是这样的:
print(Person.Person_list)
[<__main__.Man object at 0x000001CD0A1F5208>, <__main__.girlfriend object at 0x000001CD0A1F5248>]
要说类属性和类方法有一点小不同就是引用的时候,引用类属性的时候,如前文,直接Person.num_of_Person
,而引用类方法则要Person.nums_of_Person()
,就是引用方法得记得加上括号哦。
静态方法
静态方法和类方法一样,也需要首先声明,创建一个简单静态方法:
@staticmethod
def talk():
print('Hello!')
person1.talk()
Person.talk()
#输出
Hello!
Hello!
实际上静态方法差不多算一种在类里面定义得一种普通函数一样,效果什么都差不多,就是在此类之外得对象无法访问而已,只供类里面得对象访问,当然也可以供子类访问,毕竟父类有的,子类都有。
总结
面向对象是很重要得知识,而各种语言中得面向对象原理什么都是差不多得,学好了这个,才能让你搞大型程序时不慌不忙。