《从python开始学编程》第四章总结

朝思暮想是对象

本章将用一种完全不同的编程范式——面向对象。
那什么是面向过程,什么又是面向对象呢?
面向过程:我们要干什么,做这件事情需要什么步骤,用函数把这些步骤一个个实现。
面向对象:将面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。对象是按功能进行划分的;(例如:整个五子棋可以分为1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。)该例子便是从对象的角度来设计程序的。

4.1轻松看对象

面向对象语言的来历

类(Class)和对象(Object)提高了程序的可复用性。
面向对象可看作是故事和指令之间的桥梁,程序员用一种故事性的编程语言描述问题,编译器把这些程序翻译成机器指令(计算机看的懂的0/1代码)。
早期由于这样的翻译很占用计算机资源,所以并不流行,而在计算机性能提高后,人们更注重程序员的产量后,面向对象开始被发掘。

有相似特点的事物我们将其归为一类。
在每个类下面有多个个体,我们把某一个个体称为对象。例如:鸟类


class Bird(object):
  feather = True
  reproduction = "egg"

我们将有羽毛会下蛋的东西称为鸟类,在上面类中所定义的两个量,称之为属性属性用来区分类的,是类的特点。


而除了用特点来区分不同类之外,我们还会用这类东西能做什么事情来区分;在类的定义中我们将这样的“行为”属性称为方法


class Bird(object):
  feather = True
  reproduction = "egg"
  def chirp(self, sound):
    print(sound)

方法chirp()有点类似函数,但是它必须在括号中加self。
self是为了在方法内部引用对象自身。无论是否用到,都必须要有。

对象

每个类都包含多个对象,我们通过调用类,来创建对象。


summer = Bird()         #summer是属于鸟类的一个对象

而这一个对象拥有鸟类的属性和方法。我们可以用对象名.属性(object.attribute)来引用属性。如:


print(summer.reproduction)            #输出“egg”

此外我们也能通过对象名.方法()来调用方法。如:


summer.chirp("jijiji")          #输出“jijiji”

为了描述完整个体我们除了共性的类属性外,还要有说明个体对象的属性。而由于对象属性没办法像类属性一样,在类下方直接赋值,所以我们只能通过对象.属性的方式来操作对象属性,而在类内部我们只能借助self来指代对象。


class Bird(object):
  def chirp(self, sound):
    print(sound)
  def set_color(self,color):
    self.color = color

summer = Bird()
summer.set_color("yellow")
print(summer.color)                    #输出“yellow”

python还提供了初始化对象属性的办法,这类特殊方法又被称为魔法方法(Magic Method)。这类方法的前后都有两个下划线
如:init()方法,在python每次创建对象都会自动调用,可以用来初始化对象属性。


class Bird(object):
  def __init__(self, sound):
    self.sound = sound
    print("my sound is:", sound)
  def chirp(self):
    print(self, sound)

summer = Bird("ji")            #在调用类时,后面可以跟一个参数列表,这里将参数列表传给__init__()
summer.chirp()                 #输出“ji”

self参数还有另外的功能,可以让我们在一个方法内部调用同一类的其他方法。


class Bide(object):
  def chirp(self, sound):
    print(sound)
  def chirp_repeat(self, sound,  n):
    for i in range(n):
      self.chirp(sound)

summer = Bird()
summer.chirp_repeat("ji", 10)              #重复输出“ji”10次

4.2继承者们

子类

类本身还能细分为子类,就比如,鸟类还能分为鸡,天鹅。这种将类细分的过程,我们通过继承来实现。


class Bird(object):             #object是python的内置类,它充当所有类的祖先
  feather = True
  reproduction = "egg"
  def chirp(self, sound):
    print(sound)

class chicken(Bird):
  how_to_move = "walk"
  edible      = True

class swan(Bird):
  how_to_move = "swim"
  edible      = False
 
summer = chicken()
print(summer.feather)             #输出True
summer.chirp("ji")                #输出“ji”

chicken是Bird的一个子类,它继承了Bird的所有属性和方法,同时还增加了自己特有的方法。

属性覆盖

子类中与父类同名的属性会覆盖掉父类的属性,在调用中使用子类的属性;但是我们可以通过super关键字在子类中调用父类中被覆盖的方法。如:


class Bird(object):
  def chirp(self):
    print("make sound")

class chicken(Bird):
  def chirp(self):
    super().chirp()
    print("ji")

bird = Bird()
bird.chirp()        #输出“make sound”

summer = chicken()
summer.chirp()      #输出“make sound”和“ji”

4.3那些年,错过的对象

列表对象

每个列表都属于list这一个类,该类是python自带的,事先定义好的,所以称为内置类。
我们可以用dir()来查询一个类或者对象的所有属性。


>>>dir(list)

也可以使用help来查询类的说明文档


>>>help(list)

类的说明文档制作方式与函数的说明文档制作相似


class HelpDemo(object):
  """
  This is a demo for using help() on a class
  """
  pass       #pass是python中的特殊关键字用来说明该语法结构说明都不做
print(help(HelpDemo))

list的方法


>>>a = [1, 2, 3, 5, 9.0, "Good", "-1", "True", "False", "Bye"]
>>>a.count(5)      #计数,看总共有多少个元素5
>>>a.index(3)      #查询元素3第一次出现时的下标
>>>a.append(6)     #在列表最后添加一个新元素6
>>>a.sort()        #排序
>>>a.reverse()     #颠倒次序
>>>a.pop()         #去除最后一个元素,并将该元素返回。
>>>a.remove(2)     #去除第一次出现的元素2
>>>a.insert(0,9)   #在下标为0的位置插入9
>>>a.clear()       #清空列表

元组和字符串对象

元组内容不可变更,所以只能进行查询操作。


>>>a = (1, 3, 5)
>>>a.count(5)         #计数,看总共有多少个元素5
>>>a.index(3)         #查询元素3第一次出现时的下标

字符串其实是特殊的元组所以它可以执行元组的方法,同时字符串还可以变更,但是它的变更并不是修改而是删除原来的字符串再建立以新的字符串。


>>>str = "Hello World!"
>>>sub = "World"
str.count(sub)   #sub在str中出现的次数
str.find(sub)    #从左开始寻找sub在str第一次出现的位置,若str中无sub则返回-1

index(sub), rindex(sub)一个从左查找一个从右找sub在str第一次出现的位置,若str无sub则举报错误


str.spilt([sep,[max]])          #从左开始,以空格进行分隔,max为分隔几次。
str = "Hello World!"
sub = "World"
a = str.split(" ", 2)
print(a[0])                     #输出Hello

str.rjust(width)          #返回:长度为width的字符串,将原有字符串右对齐放入其余为空格,但是若width小于原有字符串的长度则按原字符串输出
str = "Hello World!"
b=str.rjust(15)
c=str.rjust(3)
print(b)                  #输出“   Hello World!”
print(c)                  #输出“Hello World!”

词典对象

我们可以用keys()方法来遍历每个元素的键,values()方法来遍历每个元素的值,或者用items()方法来遍历每个元素,也可以用clear()来清空整个字典。


a = {"a":1, "b":2}
for k in a.keys():
  print(k)
for v in a.values():
  print(v)
for k,v in a>items():
  print(k,v)

4.4意想不到的对象

循环对象

所谓的循环对象包含有一个next()方法,这个方法的目的是生成循环的下一个结果,在生成所有循环的结果后该方法抛出StopIteration异常。
我们可以用iter()函数把一个列表转变为循环对象。
for结构自动调用next()方法,并且还会自动执行iter()转化,所以我们可以省略这一转化。
借助生成器来自定义循环对象,生成器的编写与函数相似但是将return改为yield,且遇到一个yield自动停止运行生成器,返回yield后面的值,再次调用生成器时从停止的地方开始运行。


def gen()
  a = 100
  yield a
  a = a*8
  yield a
  yield 1000

:range()返回的也是一个循环对象

函数对象

任何一个有call()特殊方法的对象都被当作函数。


class SampleMore(object):
  def __call__(self, a):
    return a + 5
add_five = SampleMore()         #生成函数对象
print(add_five(2))              #像一个函数一样调用函数对象,结果为7

模块对象

一个.py文件就是一个模块,模块也是对象,我们用import语句引入其他文件中定义的函数,实际上就是引入模块对象的属性。
将功能相似的模块放在同一个文件中,构成一个模块包,如:


import this_dir.module     #引入this.dir文件夹中的module模块

:在该文件夹中必须包含一个init().py文件,提醒python这是一个模块包,这个文件可以为空


每一个都有一个name属性,但是当.py文件作为主程序运行时,这个属性会是"main"。所以我们在很多.py文件中看见下面的语句:


if __name__ == "__main__"
  ...

它的意思是当.py文件作为主程序时将执行下面的操作,所以我们在把.py作为库引入的时候,我们不希望执行的语句可以放到if中去。

异常对象

try结构捕捉程序中的异常,实际上也是一个对象。
利用except...as...的语法,我们在except结果中用e来代表捕获到的类型对象。关键字except直接跟随的ZeroDivisionError实际上是异常对象的类。
创建异常对象:

raise ZeroDivisionError()

你可能感兴趣的:(《从python开始学编程》第四章总结)