2020-07-22 Python学习笔记26 类和面向对象编程

一些关于自己学习Python的经历的内容,遇到的问题和思考等,方便以后查询和复习。

声明:本人学习是在扇贝编程通过网络学习的,相关的知识、案例来源于扇贝编程。如果使用请说明来源。

第26关:类和面向对象的编程

练习:中奖号码

模板代码是彩票抽奖机的代码,使用的是 面向过程 的思维方式写的,思考一下用 面向对象 的思维如何改写?写完记得查看答案对比一下哦~

#from random import randint

#times = 6

#lottery = []

#for i in range(0, times):

#  number = randint(0, 99)

#  lottery.append(number)

#print('本期彩票中奖号码为:%s' % lottery)

#面向对象

from random import randint

# 由于需要随机产生的数字,所以导入随机生成函数是必须的。

class Lottery:  #定义一个类,这个我想到了,但是忘记了类的名称首字母要大写的要求了

  def __init__(self, times):  #定义一个初始化,参数处理self,还有一个是抽奖次数。

    self.times = times  #设置初始化的特征

    self.lottery = []  # 设置一个空列表,因为是初始化特征,所以前面加个self

  def draw_lottery(self):  # 定义一个抽奖的方法/行为

    for i in range(0, self.times):  #用for循环,来个遍历,只是范围末端是一个参数

      number = randint(0, 99)

      self.lottery.append(number)

  def print_lottery(self):    # 定义一个打印结果的方法/行为

    print('本期彩票中奖号码为:%s' % self.lottery)


lottery = Lottery(6)  #实例化,同时对times赋值


lottery.draw_lottery()  # 调用实例化后的抽奖方法


lottery.print_lottery()  #调用打印抽奖结果的方法

说实话,我是没有弄出来,通过前面的例子,我知道面向对象的变成思路是三个部分:第一个是定义一个类,第二个是实例化,第三个是调用。其中后两个比较简单,第一个是比较难的。我看了前面那个关于学生姓名和成绩的例子,但是我还是没有思路如何做。

原因是前面学生成绩的例子是个静态的,就是资料时固定的,不变的。而这个是动态的,号码是没有的。所以如何用定义类的方式来解决呢。我没有思路,没有办法。只好看了答案。

发现:三个步骤是找到了,第一个步骤是重点,而且第一个步骤中就是抽即将的过程,所以这个步骤是对象中包含过程的,把整个抽奖过程作为一个对象。

练习:kakarotto

赛亚人会在月圆之夜因为月亮发射出来的布尔兹光,进化成巨猿。变身后是常态的 10 倍左右,并且会失去理智。

假设现在是月圆之夜,请你在类实例化时自动调用 transform() 方法变身,并添加 __str__() 方法返回 我是来自xxx的xxx,代码最终运行结果应如下:

变身巨猿

我是来自贝吉塔行星的卡卡罗特

要求:

给 Saiyan 类添加初始化方法,初始化方法接受 name 参数用于初始化 self.name,并调用 transform() 方法;

给 Saiyan 类添加 __str__() 方法,使打印 Saiyan 类的实例 kakarotto 时结果为 我是来自贝吉塔行星的卡卡罗特。

class Saiyan:

  def __init__(self, name):

    self.name = name


    self.born_place = '贝吉塔行星'

self.character = '天生好战性格暴躁' 

#这两个没有赋值,还是特征,答案是放在外面的,我也考虑了这一点,放在初始化外面更合理。放在这里前面加self,放在初始化外面,前面则不用加self

这两个应该也是赋值了,只不过似乎固定的值,而不是一个变量。

  def transform(self):

    print('变身巨猿')

  def __str__(self):

    return('我是来自%s的%s'%(self.born_place, self.name))


kakarotto = Saiyan('卡卡罗特')

kakarotto.transform() #答案是在初始化中调用这个方法的,所以最后就没有了,符合题意

print(kakarotto)

变身巨猿

我是来自贝吉塔行星的卡卡罗特


根据答案更改之后的结果:

class Saiyan:

  born_place = '贝吉塔行星'

  character = '天生好战性格暴躁'  #不在初始化中,所以前面不能再加self

  def __init__(self, name):

    self.name = name

    self.transform()  #可以在初始化中赋值,可以调用方法



  def __str__(self):

    return('我是来自%s的%s'%(self.born_place, self.name))

  def transform(self):

    print('变身巨猿')


kakarotto = Saiyan('卡卡罗特')

#kakarotto.transform()

print(kakarotto)

也可以这样修改:

class Saiyan:


  def __init__(self, name, born_place, character):  四个参数

    self.name = name

    self.transform()

    self.born_place = born_place

    self.character = character  所有参数都进行了初始化


  def __str__(self):

    return('我是来自%s的%s,%s'%(self.born_place, self.name, self.character))

  def transform(self):

    print('变身巨猿')


kakarotto = Saiyan('李建升','地球','天生爱吃肉')

#kakarotto.transform()

print(kakarotto)

变身巨猿

我是来自地球的李建升,天生爱吃肉

kakarotto = Saiyan('卡卡罗特','贝吉塔行星','天生天生好战性格暴躁')

#kakarotto.transform()

print(kakarotto)

变身巨猿

我是来自贝吉塔行星的卡卡罗特,天生天生好战性格暴躁

练习:三头六臂的哪吒

哪吒会 三头六臂 的法术,我们来给模板代码中的类补充一个初始化方法,使其打印出 我叫哪吒,我有 3 头 6 臂。

class Human:

  # 在这里补充初始化方法

  def __init__(self, name, heads, arms):

    self.name = name

    self.heads = heads

    self.arms = arms


  def intro(self):

    print('我叫{},我有{}头{}臂'.format(self.name, self.heads, self.arms))

nezha = Human('哪吒', 3, 6)

nezha.intro()

练习:三头六臂的哪吒 另一个答案:

我们通过 intro() 方法打印出了 我叫哪吒,我有 3 头 6 臂。接下来我们去掉 intro() 方法,使用神奇方法 __str__() 来打印 我叫哪吒,我有 3 头 6 臂。

class Human:

  def __init__(self, name, heads, arms):

    self.name = name

    self.heads = heads

    self.arms = arms

  def __str__(self):

    return '我叫{},我有{}头{}臂'.format(self.name, self.heads, self.arms)

  #def intro(self):

  # print('我叫{},我有{}头{}臂'.format(self.name, self.heads, self.arms))

nezha = Human('哪吒', 3, 6)

#nezha.intro()

print(nezha)

学习笔记:

初始化方法

在 Python 的类中,有一种特殊的方法——初始化方法。它的格式是 def __init__(self):,方法名由 init(initialize 的缩写,初始化的意思)加左右两边的 双下划线 组成。

注意:初始化方法的 init 前后有 两个 下划线。

初始化方法的特殊之处是:每当进行类的实例化时,初始化方法会自动被执行。

只是创建了实例,并没有调用 __init__ 方法,它自己就自动执行了。利用这个特性,我们通常会在 初始化方法 里完成类属性初始值的设置。

除了进行固定的初始值设置,初始化方法 可以接收其他参数,进行自定义的属性初始值设置。

class Human:

  def __init__(self, name, arms, legs, hair):

    # self.不能丢

    self.name = name

    self.arms = arms

    self.legs = legs

    self.hair = hair

  def walk(self):

    print('直立行走')

  def speak(self):

    print('说着各式各样的语言')

  def intro(self):

    print('我叫{},我有{}'.format(self.name, self.hair))

xiaobei = Human('小贝', 2, 2, '粉红色的头发')

print(xiaobei.name)

# 输出:小贝

xiaobei.intro()

# 输出:我叫小贝,我有粉红色的头发

给 初始化方法 额外添加了 4 个参数,因此在实例化的时候要传入对应的值。Human('小贝', 2, 2, '粉红色的头发') 这里的 '小贝' 赋值给 self.name,两个 2 分别赋值给 self.arms 和 self.legs,'粉红色的头发' 赋值给 self.hair。

当实例化完成之后,初始化方法会自动执行,这样我们就完成了自定义的属性初始值设置。然后我们可以通过 实例名.属性名 在类外访问或 self.属性名 在类的方法中访问了。

神奇方法

像 __init__() 这样的方法在 Python 的类中被称为 神奇方法(或魔术方法),它们的特征是被 双下划线 所包裹。这一节中我们再介绍一个神奇方法——__str__()。

class Human:

  arms = 2

  legs = 2

  hair = '各种颜色的头发'

  def walk(self):

    print('直立行走')

  def speak(self):

    print('说着各式各样的语言')

  def intro(self):

    print('人类有%d条胳膊%d条腿' % (self.arms, self.legs))

# 类的实例化

human = Human()

human.intro()

# 输出:人类有2条胳膊2条腿

class Human:

  arms = 2

  legs = 2

  hair = '各种颜色的头发'

  def __str__(self):

    return '人类有%d条胳膊%d条腿' % (self.arms, self.legs)

  def walk(self):

    print('直立行走')

  def speak(self):

    print('说着各式各样的语言')

human = Human()

print(human)

# 输出:人类有2条胳膊2条腿

可以看到,有了 __str__() 方法,直接打印实例的结果为 __str__() 方法的返回值。因此,我们可以使用 __str__() 方法来描述一个类。

面向对象与面向过程

与 面向对象 相对应的是 面向过程,我们之前写代码都用的是 面向过程 的思维方式。也就是把一个问题拆分成一个个步骤,然后用函数实现各个步骤,依次调用解决问题。

而 面向对象 的思维方式是:把一个问题拆分成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为和特征(方法和属性)

可以看到,面向过程 是以动作(函数)为主体,对象(这个例子里是学生)作为参数传递给函数。而 面向对象 是以对象为主体,动作和特征分别是对象的方法和属性。用代码来描述就是,面向过程:动作(对象);面向对象:对象.动作()。

使用 面向对象 的思维方式的好处是:程序的可读性、可拓展性、可维护性高。但并不是说 面向过程 就一无是处了,二者相辅相成,并不是对立的,我们要根据实际情况选择合适的编程思维方式。


你可能感兴趣的:(2020-07-22 Python学习笔记26 类和面向对象编程)