文章目录

  • 面向对象
  • 特征
  • 封装
  • 继承
  • 多态
  • 具体实现
  • 创建一个类
  • 继承这个类
  • 类属性
  • 类方法
  • 静态方法
  • 总结


面向对象

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!

实际上静态方法差不多算一种在类里面定义得一种普通函数一样,效果什么都差不多,就是在此类之外得对象无法访问而已,只供类里面得对象访问,当然也可以供子类访问,毕竟父类有的,子类都有。

总结

面向对象是很重要得知识,而各种语言中得面向对象原理什么都是差不多得,学好了这个,才能让你搞大型程序时不慌不忙。