Python 是一门“面向对象的编程语言”(Object Oriented Programming)。这是指 Python 中有一个叫做 类(class)的结构,能够让你用一种特定的方式结构化你的软件。通过使用类,你可以让你的程序保持连贯性,使用起来更清晰。至少理论上是这样。
一、类(class) 1.1 类(class)的概念及实例在学习前我对‘类’的概念还十分模糊,认为类是一个模板,它描述一类对象的行为和状态,大概与“物以类聚”相似。下面进行实例练习:
class Song(object):
def __init__(self, lyrics):
self.lyrics = lyrics
def sing_me_a_song(self):
for line in self.lyrics:
print(line)
happy_bday = Song(["Happy birthday to you","I don't want to get sued","So I'll stop right there"])
bulls_on_parade = Song(["They rally around tha family",
"With pockets full of shells"])
happy_bday.sing_me_a_song()
bulls_on_parade.sing_me_a_song()
Happy birthday to you I don't want to get sued So I'll stop right there They rally around tha family With pockets full of shells
同样,根据前面的学习,遇到不懂的代码,通过进行逐句写标注的方式进行理解
class Song(object):#通过class定义类Song,类Song是从类object上继承下来的
def __init__(self, lyrics):#通过定义__init__()函数,把lyrics属性绑定到即将创建的实例上去
self.lyrics = lyrics#理解起来有些困难
def sing_me_a_song(self):#定义函数sing_me_a_song,参数为self,也就是上面创建的实例
for line in self.lyrics:#这里使用for...in循环将列表内的每一个元素代入变量line
print(line)#并打印字符串
happy_bday = Song(["Happy birthday to you","I don't want to get sued","So I'll stop right there"])
bulls_on_parade = Song(["They rally around tha family",
"With pockets full of shells"])#根据类Song,通过类名+()创建出Song的实例。对象happy_bday和对象bulls_on_parade分别指向Song的两个实例
happy_bday.sing_me_a_song()
bulls_on_parade.sing_me_a_song()#调用函数sing_me_a_song,对象分别为happy_bday和bulls_on_parade
通过上面的标注以及查找相关资料对‘类’的理解加深了一些。比如:
class后面紧接着是类名,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的。通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。
但是代码中的init()方法、使用类的方法还是不太理解。
1、用这个方法再写一些歌,确保你明白你正在用字符列表来传歌词。
class Song(object):
def __init__(self,lyrics):
self.lyrics = lyrics
def sing_me_a_song(self):
for line in self.lyrics:
print(line)
Vanilla = Song(["First time I met you in America",
"You showed me the way to your lonely mars",
"Where I tumbled down",
"Where I fall apart",
"Would you let me call your name",
"Vanilla"
])
Vanilla.sing_me_a_song()
First time I met you in America You showed me the way to your lonely mars Where I tumbled down Where I fall apart Would you let me call your name Vanilla
2、把歌词放在一个单独的变量里,然后把这个变量放在类里面来使用。
class Song(object):
def __init__(self,lyrics):
self.lyrics = lyrics
def sing_me_a_song(self):
for line in self.lyrics:
print(line)
lyrics_1 = ["First time I met you in America",
"You showed me the way to your lonely mars",
"Where I tumbled down",
"Where I fall apart",
"Would you let me call your name",
"Vanilla"]
Vanilla = Song(lyrics_1)
Vanilla.sing_me_a_song()
First time I met you in America You showed me the way to your lonely mars Where I tumbled down Where I fall apart Would you let me call your name Vanilla
这一题的意思我认为是,用单独变量存储歌词,然后把这个变量作为参数传递给类。
3、在网上搜搜“面向对象的编程”,然后填满你的大脑。别担心你看不懂,因为几乎一半的东西我也看不懂。
概述
面向过程:根据业务逻辑从上到下写垒代码
函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
面向对象:对函数进行分类和封装,让开发“更快更好更强…”
面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。
创建类和对象
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。
class是关键字,表示类创建对象,类名称后加括号即可
注:类中的函数第一个参数必须是self(详细见:类的三大特性之封装)
类中定义的函数叫做 “方法”。
面向对象三大特性
面向对象的三大特性是指:封装、继承和多态。
一、封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
将内容封装到某处
从某处调用被封装的内容
第一步:将内容封装到某处
self 是一个形式参数(形式参数在前面的练习有写到)
当执行 obj1 = Foo(‘wupeiqi’, 18 ) 时,self 等于 obj1
当执行 obj2 = Foo(‘alex’, 78 ) 时,self 等于 obj2
所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都封装了 name 和 age ,之前说的“内容封装到某处”其在内容里类似于下图来保存。
第二步:从某处调用被封装的内容
调用被封装的内容时,有两种情况:
通过对象直接调用
通过self间接调用
1、通过对象直接调用被封装的内容
上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
obj1 = Foo('wupeiqi', 18)
print obj1.name # 直接调用obj1对象的name属性
print obj1.age # 直接调用obj1对象的age属性
obj2 = Foo('alex', 73)
print obj2.name # 直接调用obj2对象的name属性
print obj2.age # 直接调用obj2对象的age属性
2、通过self间接调用被封装的内容
执行类中的方法时,需要通过self间接调用被封装的内容
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def detail(self):
print self.name
print self.age
obj1 = Foo('wupeiqi', 18)
obj1.detail() # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18
obj2 = Foo('alex', 73)
obj2.detail() # Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78
综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。
二、继承
继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。如下图所示:
多继承问题详见参考链接。
三、多态
Pyhon不支持多态并且也用不到多态,多态的概念是应用于Java和C++这一类强类型语言中
参考链接:https://www.cnblogs.com/zunchang/p/7965685.html
那么什么样的代码才是面向对象?
简单来说,如果程序中的所有功能都是用 类 和 对象 来实现,那么就是面向对象编程了。 二、学着去说面向对象
在这个练习中,我要教你如何去说“面向对象”。我所做的就是给你一些你需要了解的词和定义。然后我会给出一些需要填空的句子让你去理解。最后,你要完成一个大练习,从而在大脑中巩固这些句子。
2.1 词汇训练类(class) :告诉 Python 创建一个新类型的东西(Tell Python to make a new type of thing)。
对象(object)两种含义:最基本类型的东西, 任何实例。(the most basic type of thing, and any instance of something.)
实例(instance) :当你告诉 Python 创建一个类的时候你所得到的东西。(What you get when you tell Python to create a class.)
def :你如何在类里面定义一个函数。(How you define a function inside a class.)
self :在一个类的函数里面,self 是被访问的实例/对象的一个变量。(Inside the functions in a class, self is a variable for the instance/object
being accessed.)
继承(inheritance) :关于一个类能从另一个类那里继承它的特征的概念,很像你和你的父母。(The concept that one class can inherit traits from another class, much like you and your parents.)
组合(composition) :关于一个类可以由其他一些类构成的概念, 很像一辆车包含几个轮子。(The concept that a class can be composed of other classes as parts, much like how a car has wheels.)
属性(attribute) :类所拥有的从组合那里得到的特性,通常是变量。(A property classes have that are from composition and are usually variables.)
is-a :一种用来表达某物继承自一种东西的表述, 就像“三文鱼是一种鱼”。(A phrase to say that something inherits from another, as in a “salmon” is a “fish.”)
has-a :一种用来表达某物是由一些东西组成或具有某种特性的表述,就像“三文鱼有一个嘴巴”。(A phrase to say that something is composed of other things or has a trait, as in “a salmon has-a mouth.”)
花点时间为这些术语做一些闪词卡(flash cards)并记住它们,虽然在你完成这个练习之前单纯的记忆没有任何意义,但你必须要先了解这些基础的词汇。
2.2 短语训练接下来是一些 Python 代码片段以及右边的解释。
class X(Y) :创建一个名为 X 并继承自 Y 的类。(“Make a class named X that is-a Y.”)
class X(object): def init(self, J) 类 X 有一个带有 self 和 J 参数的 init 函数。(“class X has-a init that takes self and J parameters.”)
class X(object): def M(self, J):类 X 有一个带有 self 和 J 参数的 M 函数。(“class X has-a function named M that takes self and J parameters.”)
foo = X():设 foo 为类 X 的一个实例。(“Set foo to an instance of class X.”)
foo.M(J) 从 foo 那里获取 M 函数,并用 self 和 J 参数来调用它。(“From foo, get the M function, and call it with parameters self, J.”)
foo.K = Q 从 foo 那里获取 K 属性,并设它为 Q。(“From foo, get the K attribute, and set it to Q.”)
在上述每一句中,当你看到 X, Y, M, J, K, Q, 以及 foo, 你可以把它们当做空格,比如,我还可以把这些句子写成:
1.“Make a class named ??? that is-a Y.”
(创建一个名为 ??? 的类,它继承自 Y。)
2.“class ??? has-a init that takes self and ??? parameters.”
(类 ??? 有一个带了 self 和 ??? 参数的 init。)
3.“class ??? has-a function named ??? that takes self and ??? parameters.”
(类 ??? 有一个名为 ??? 的函数,这个函数带有 self 和 ??? 两个参数。)
4.“Set foo to an instance of class ???.”
(设 foo 为类 ??? 的一个实例。)
5.“From foo, get the ??? function, and call it with self=??? and parameters ???.”
(从 foo 那里获取 ??? 函数,并用 self=??? 以及参数 ??? 来调用它。)
6.“From foo, get the ??? attribute, and set it to ???.”
(从 foo 那里获取 ??? 属性,把它设为 ???。)
你现在需要继续读更多的代码,并在这些代码中复习你之前学过的短语。试着找到尽可能多的包含类的文件,然后跟着如下要求去做:
1、给出每个类的名字,以及其他的类从它那里继承了什么。
2、在每个类下面,列出它所拥有的函数以及它们的参数。
3、列出所有它用 self 使用的属性。
4、对于每个属性,给出它继承自哪个类。
这些练习的目的是过一遍真实的代码,并试着把你学过的短语和它们的用法匹配和关联起来。如果你做足了训练,你会开始看到这些匹配模式(match patterns)呼之欲出,而不再是一些你不明白的空格或字符。
三、总结 3.1相关知识概念
类(class)的概念:
class后面紧接着是类名,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的。通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。实例(instance)的概念:
定义好了类,就可以根据类创建出该类的实例,创建实例是通过类名+()实现的。init()函数的概念:
在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把你认为必须绑定的属性绑上去。
注意
类相当于盖楼房的图纸一样,虽然定义了有哪些成员,但并没有实际的空间类可以实例化出多个对象,实例化出的对象占有实际空间(用来存储成员变量)注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去。 3.2 总结
最后一个task了,其中的一些知识理解起来还是有些困难,比较抽象,比如第一个附加练习,需要在查阅资料的基础上再进行理解,建议遇到这种抽象化的知识点课程,可以多加几个实例~,教程给出的方法还是很实用的,需要后面自己上手编程时多加练习。感谢一起乘风破浪的船员们和航海士们,期待下一次的组队学习!



