这是本文的目录
前言
面向对象编程是在面向过程编程的基础上发展来的,它比面向过程编程具有更强的灵活性和扩展性。面向对象编程是程序员发展的分水岭,很多初学者会因无法理解面向对象而放弃学习编程。
面向对象编程(Object-oriented Programming,简称 OOP),是一种封装代码的方法。

面向对象的基础
为了方便理解其中的抽象概念,我们要学会先打比方,习惯对身边的事物进行分类:
比如说猫和狗都是动物,
直线和圆都是平面几何的图形,
哈利波特和冰与火之歌都是小说。
同一类事物便会有相似的特性:
也就是说动物会动,
平面图形有面积和周长,
小说也都有相应的作者和大致情节等各种元素。
我们先来看一段最基本的Python面向对象的应用代码:
class Document():
def __init__(self,title,author,context):
print('init function called')
self.title title
self.author author
self.__context=context#_开头的属性是私有属性
def get_context_length(self):
return len(self.__context)
def intercept_context(self,Length):
self.__context self.__context[:Length]
harry_potter_book Document('Harry Potter','J.K.Rowling','..Forever Do I
print(harry_potter_book.title)
print(harry_potter_book.author)
print(harry_potter_book.get_context_length)
harry_potter_book.intercept_context(10)
print(harry_potter_book.get_context_length())
print(harry_potter_book.__context)
##########输出##########
init function called
Harry Potter
J.K.Rowling
77
10
---------------------------------------------------------------------------------------------
AttributeError Traceback(most recent call last)
<ipython-input-5-b4d048d75003>in <module>)
---22 print(harry_potter_book.get-context-length())
---24 print(harry_potter_book.context)
AttributeError:'Document' object has no attribute 'context'
根据这段代码,简单了解几个概念:
1、类: 一群有着相似性的事物的集合,这里对应python的 class
2、对象: 集合中的一个事物,这里对应由class生成的某一个object,比如代码中的Harry potter book。
3、属性:对象的某个静态特征,比如上述代码中的title 、author和contact。
4、函数: 对象的某个动态能力,比如上述代码中的intercept context函数。
这样对面向对象编程了解不完全,但是可以迅速有一个直观的了解。

更为严谨的定义:
1、类:一群有着相同属性和函数的对象的集合
class Document():
def __init__(self,title,author,context):
print('init function called')
self.title title
self.author author
self.__context=context#_开头的属性是私有属性
def get_context_length(self):
return len(self.__context)
def intercept_context(self,Length):
self.__context self.__context[:Length]
harry_potter_book Document('Harry Potter','J.K.Rowling','..Forever Do I
print(harry_potter_book.title)
print(harry_potter_book.author)
print(harry_potter_book.get_context_length)
harry_potter_book.intercept_context(10)
print(harry_potter_book.get_context_length())
print(harry_potter_book.__context)
##########输出##########
init function called
Harry Potter
J.K.Rowling
77
10
---------------------------------------------------------------------------------------------
AttributeError Traceback(most recent call last)
<ipython-input-5-b4d048d75003>in <module>)
---22 print(harry_potter_book.get-context-length())
---24 print(harry_potter_book.context)
可以看到class document定义了document类,再往下能看到它有三个函数,这三个函数即为document类的三个函数。
其中init表示构造函数,即一个对象生成时会被自动调用的函数。我们能看到Harry Potter book等于document(…)这一行代码被执行的时候,init function called字符串会被打印出来。而get context length()和intercept context则为类的普通函数,我们调用它们来对对象的属性做一些事情。
class document还有三个属性,Title author和context,分别表示标题、作者和内容,通过构造函数传入这里。代码很直观,我们可以看到intercept context能修改对象Harry potter book的context属性。
唯一需要强调的一点是,如果一个属性以—___(注意此处有两个)开头,我们就默认这个属性是私有属性。
私有属性是指不希望在类的函数之外的地方被访问和修改的属性。所以你可以看到title和author能够很自由的被打印出来,但是打印print(Harry potter book context)就会报错。

掌握了最基础的概念,随着复杂度继续提升,我们可能又会想到这些问题:
1、如何在一个类中定义一些常量,每个对象都可以方便访问这些常量而不用重新构造。
2、如果一个函数不涉及到访问、修改这个类的属性而放到类外面有点不恰当,怎么做才能更优雅呢?
3、既然类是一群相似的对象的集合,那么可不可以是一群相似的类的集合呢?
前两个问题它的解决方法会涉及到一些常用的代码规范,示例:


第一个问题, 在Python的类里,我们需要和函数并列的声明并赋值就可以实现这一点。例如这段代码中的welcome str,一种很常规的做法是用全大写来表示常量,因此我们可以在类中使用self.welcome str,或者在内外用empty.welcome str 达这个字符串。
第二个问题, 我们提出了类函数、成员函数和静态函数三个概念。我们要知道前两者产生的影响是动态的,能够访问或者修改对象的属性,而静态函数则与类没有什么关联,最明显的特征便是静态函数的第一个参数没有任何特殊性。
具体看看这几种函数,静态函数可以用来做一些简单独立的任务,既方便测试,也能优化代码结构。静态函数还可以通过在函数前一行加上@ staticmethod来表示,代码中有相关示例,这是使用了装饰器的概念,
类函数的第一个参数一般为CLS,表示必须传一个类进来。类函数最常用的功能是实现不同的init构造函数。
比如上文代码中,我们使用create emptyb book类函数来创造新的书籍对象,其context一定为nothing,这样的代码就比直接构造要清晰一些。类似的类函数需要装饰器ADD class method来声明。
成员函数是我们最正常的类的函数,不需要任何装置器声明。第一个参数self代表当前对象的引用,我们可以通过这个函数来实现想要的查询、修改类的属性等功能。
继承
第三个问题,类是一群相似的对象的集合,那么也可以是一群相似的类的集合,只要抽象的好,类可以描述成任何事物的集合。但是要小心严谨的去定义它,不然很容易引起第三次数学危机。
类的继承指的是一个类既拥有另一个类的特征,也拥有不同于另一个类的独特特征。这里的第一个类叫做子类,另一个叫做父类。特征其实就是类的属性和函数。
结合代码来看:



在这段代码中,Document和video它们有相似的地方,都有相应的标题、作者和内容等属性。我们可以从中抽出一个叫做entity的类来作为它俩的父类。
但是 要注意构造函数,每个类都有构造函数,继承类在生成对象的时候是不会自动调用父类的构造函数的,因此必须在init()函数中显示调用父类的构造函数。它们的执行顺序是,先是子类的构造函数,然后是父类的构造函数。
然后还要注意父类get context length()函数,如果使用entity直接生成对象,调用get context length()函数,就会raise error中断程序的执行,这也是一种很好的写法,叫做函数重载,可以使此类必须重新写一遍get context length()函数来覆盖掉原有函数。
最后还要注意到print title函数,那这个函数定义在父类中,但是子类的对象可以毫无阻力的使用它来打印title,这也就体现了继承的优势,减少重复的代码,降低系统的熵值。

抽象函数和抽象类
先来代码示例:
from abc import ABCMeta,abstraetmethod
class Entity(metaclass=ABCMeta)
@abstractmethod
def get_title(selt)
pass
@abstractmethod
def set_title(selt,title)
pass
class Document(Entity):
def get_title(self):
return self.title
def set_title(self,title):
self.title title
document Document)
document.set_title('Harry Potter')
print(document.get_title())
entity Entity()
##########输出##########
Harry Potter
-----------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-266b2aa47bad>in <module>()
21 print(document.get_titleO)
22
---23 entity Entity()
24 entity.set_title('Test')
TypeError:Can't instantiate abstract class Entity with abstract methods get_t
代码中可以看出,entity本身没有什么用的,只需要拿来定义document和video的一些基本元素就够了。但是如果不小心生成entity的对象,我们先了解一下抽象类:
抽象类是一种特殊的类,它生下来就是作为父类存在的,一旦对象化就会报错。同样,抽象函数定义在抽象类之中,子类必须重写该函数才能使用,相应的抽象函数则是使用装饰器@abstract method来表示。
我们看到代码中entity=entity()直接报错,只有通过document继承entity才能正常使用。
这其实是一个很重要的概念,定义接口。抽象类就是这么一种存在,它是一种自上而下的设计风范,需要用少量的代码描述清楚要做的事情,定义好接口,然后就可以交给不同开发人员去开发和对接。

总结
面向对象编程是软件工程中重要的思想,是一种综合能力的体现,是将大型工程结耦化、模块化的重要方法。在实践中要多想,尤其是抽象的想,才能更快掌握这个技巧。
视频版学习资料领取
零基础Python学习资料
附上Python学习指南

👉Python学习路线汇总👈
围绕Python所有方向的技术点做的整理,以形成各个领域的知识点汇总,这样就可以按照上面的知识点去找对应的学习资源,保证学得较为全面。

👉Python必备开发工具👈

温馨提示:篇幅有限,已打包文件夹,获取方式在:文末
👉Python学习视频600合集👈
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

👉实战案例👈
边学边练是最高效的学习方法,这时候可以搞点实战案例来学习。

👉100道Python练习题👈
检查学习结果。
👉面试刷题👈


👉资料领取👈
这份完整版的Python全套学习资料已为大家备好,朋友们如果需要可以微信扫描下方二维码添加“住隔壁的王叔”,输入"领取资料" 可免费领取全套资料【有什么需要协作的还可以随时联系我】朋友圈也会不定时的更新最前言python知识。

本文详细介绍了面向对象编程基础,包括类、对象、属性和函数,以及继承、抽象函数和抽象类的概念。通过实例演示,学习者将掌握Python中创建类、对象操作及面向对象设计的关键要素。
3807

被折叠的 条评论
为什么被折叠?



