Python面向对象二(第十二讲)

在这里插入图片描述

知识点

  • 私有属性与私有方法
  • 成员
  • 属性
  • 方法
  • 封装
  • 继承
  • 多态

1.私有属性与私有方法

    在实际开发中,对象的某些属性或者方法,只希望在对象的内部使用,这时,我们就可以使用私有属性私有方法

1.私有属性

  • 私有属性:就是对象不希望公开的属性
  • 定义方式:在属性名前面增加两个下划线(例如:__name)

    练习

  • 定义类为:"人"类
  • 创建对象:rose
  • 初始化对象属性:name 与 age
  • 要求:age 不能在类的外部访问
class Human:
    def __init__(self):
        self.name = 'rose'
        # 两个下划线,则为私有属性
        self.__age = 18
        # 报错:因为定义为私有属性,则在外部无法访问
        # AttributeError: 'Human' object has no attribute 'age'
rose = Human()
print(rose.name)
print(rose.age)

    需求:一定要在类的外部访问到对象的私有属性,如何实现?

    方法:

  • 可以通过类的内部的方法访问私有属性
class Human:
    def __init__(self):
        self.__name = 'rose'
        # 两个下划线,则为私有属性
        self.age = 18
    def __str__(self):
        print(self.__name)
rose = Human()
rose.__str__()
  • 通过类的内部方法将私有属性返回出去,在类的外部调用该方法并且接收就可
class Human:
    def __init__(self):
        self.__name = 'rose'
        # 两个下划线,则为私有属性
    def __str__(self):
        return self.__name
name = Human()
print(name.__str__())

2.私有方法

  • 私有方法:就是对象不希望公开的方法
  • 定义方式:在方法名前面增加两个下划线(例如:__test)

    注意:
在 python 中,并没有真正意义上的私有,只有伪私有。当我们在访问时,以 对象._类名__私有属性 即可访问,私有方法同理。但是不建议使用。

2.成员

在这里插入图片描述

3.实例属性

    实例属性属于对象,只能通过对象访问

  • 定义:self.属性名称
  • 访问:self.属性名称对象.属性名称
        练习:定义一个省份类,打印输出班级每位同学所在的国家与省份。
class Province:
    def __init__(self, country, province):
        self.country = country
        self.province = province
    def print_def(self):
        print(self.country, self.province)


jeff = Province('中国', '广东')
jeff.print_def() # 中国 广东
amy = Province('中国', '湖南')
amy.print_def() # 中国 湖南

1.类属性(静态属性)

    类属性属于类,保存在类中。在创建时,仅创建一份,并且所有对象都共享静态属性。执行时可以是类访问也可以是对象访问。

  • 定义:直接在类中定义
  • 访问:类名.属性名称 或 self.属性名称 或 对象.属性名称
class Province:
    country = '中国' # 静态属性
    def __init__(self, province):
        self.country
        self.province = province

    def print_def(self):
        print(self.country, self.province)


jeff = Province( '广东')
jeff.print_def()  # 中国 广东
amy = Province( '湖南')
amy.print_def()  # 中国 湖南

2.属性总结

    在实际开发中,如果属性的值是固定的,不随对象的改变而改变。那就使用静态属性(类属性),这样有利于节省内存的消耗。而如果属性的值随对象的改变而改变,就使用实例属性。

4.实例方法

    普通方法保存在类中,在实例化对象后,一般通过对象调用。第一个参数必须为系统自建参数,默认为 self,代指对象本身。

class Demo:
    def __init__(self, name):
        self.name = '啊巴啊巴'
    def text(self):
        print(self.name)
d = Demo('Jeff')
d.text()

    注意:

  • 当需要在方法中使用实例属性时,通常使用实例方法
  • self 仅仅是变量名。使用其它也可,但最好不要修改

5.类方法

    类方法通过在方法上面添加@classmethod 装饰器,保存在类中;

class Abc:
	def abc(self):
		pass
    @classmethod
    def bnc(cls): # 自建参数为cls,指当前的类
        pass

    注意:

  • 类方法不需要传入self。但有一个系统自建参数为cls,cls代指类本身;
  • 类方法一般通过类调用,也可通过对象调用

6.静态方法

    静态方法通过在方法上面添加 @staticmethod 装饰器定义,保存在类中;

import time
# 导入时间模块
class ShowTime:
	@staticmethod # 静态方法
    def time_1(): # 静态方法不需要传入self
        print(time.strftime('%Y:%m:%d',time.localtime()))
        # 2021: 01:26

sj = ShowTime()
sj.time_1()

    注意:

  • 静态方法不需要传入self参数,即使传入了self参数也并不像普通方法那样代指对象本身,仅仅是一个普通的形参。
  • 静态方法的调用虽然可以通过对象调用,但一般由类调用。
  • 静态方法的参数并不代表对象这一特点,使静态方法在类中使用起来更像一个单纯的函数。完全可以将静态方法放在类的外部,当成函数使用。但是放在类中,便于使用与维
    护。

7.封装介绍

    封装是面向对象编程的一大特点,将属性和方法放到类的内部,通过对象访问属性或者方法,隐藏功能的实现细节,也可以设置访问权限。

class Student:
    def __init__(self, name, age): # 将属性封装到类的内部
        self.name = name
        self.age = age
    def print_text(self):
        print(self.name, self.age)
yu = Student('屿', 18)
yu.print_text() # 屿 18
# 在同一个类,创建多个对象之间互不干扰
ywyg = Student('屿我有关', 18)
ywyg.print_text() # 屿我有关 18

8.继承(重点)

    继承是一种创建新类的方式,如果子类需要复用父类的属性或者方法时,就可以使用继承。当然,子类也可以提供自己的属性和方法。

class Father:
    pass
class Son(Father):
    pass

    注意:

  • 在 python 中,新建的类可以继承一个或多个父类
  • 继承作用:避免重复造轮子,减少代码的冗余
class Father:
    def chi(self):
        print('吃')
class Son(Father):
    def he(self):
        print('喝')
jc = Son()
jc.chi() # 吃

    由此可见,我调用的子类中并没有 ‘吃’ 这个代码,但是却可以在父类中继承。

9.新式类与经典类

    在 Python2 当中类分为新式类和经典类,如果有继承父类 object 则是新式类,否则为经典类。

class Demo(object): # 新式类
	pass
class Demo: # 经典类
	pass

    但是在 Python3 当中,全部都是新式类,默认继承 object。

练习

    验证 Python3 中,全部都是新式类
    实现思路:比较继承与无继承两个空类的成员是否一致拓展方法:

  • 对象.dir() 查看对象的属性与方法
class Demo1:
    pass
class Demo2(object):
    pass
d1 = Demo1()
d2 = Demo2()
print(d1.__dir__())
print(d2.__dir__())

10.单继承

    子类继承父类,则可以直接享受父类中已经封装好的方法

class Father:
    pass
class Son(Father):
    pass

    当对象调用方法时,查找顺序先从自身类找,如果自身没找到,则去父类找,父类无,再到父类的父类找,直到object类,若还无,则报错。这也称为深度优先机制
在这里插入图片描述
    需要注意的是,当子类与父类拥有同名称的方法时,子类对象调用该方法优先执行自身的方法。那么实际上是子类的方法覆盖父类的方法,也称为重写

class Father:
    def shui(self):
        print('父亲睡')
class Son(Father):
    def shui(self):
         print('儿子睡')
son = Son()
son.shui() # 儿子睡

    但是实际的开发中,遵循开放封闭原则。我们并不会完全的重写父类的方法,而是希望同时实现父类的功能。这时,我们就需要调用父类的方法了,可以通过 super()函数实现。
    注意:

  • __init__方法也会继承,同实例方法一致
  • 私有属性以及私有方法没有被继承

1.super()

    super(type[, object-or-type]) 函数是用于调用父类(超类)的一个方法

  • type --> 类
  • object-or-type --> 对象或类,一般是 self

练习

  •     用代码实现如下:
    在这里插入图片描述
class GrandFather:
    def shui(self):
        print('睡')
class Father(GrandFather):
    def chi(self):
         print('吃')
    def he(self):
        print('喝')
class Son(Father):
    def xue(self):
        print('学python')
son = Son()
son.xue() # 学python
son.he() # 喝
son.chi() # 吃
son.shui() # 睡
  • 继以上练习实现,在Son的sleep方法当中,调用父类的sleep方法。
class Father:
    def shui(self):
        print('父亲睡')
class Son(Father):
    def shui(self):
        print('儿子睡')
        super().shui()
son = Son()
son.shui() 
# 儿子睡
# 父亲睡

11.作业

  • 作业1
        玩个特别无聊的游戏,猜数字。玩家输入一个数字与计算机随机生成的数字作对比当两个值相等时,则说明用户猜对了
        注意: 外部不能获取到计算机随机生成的值
import random
class GuessNumber(object):
    def __init__(self):
        self.__i = random.randint(0, 10)

    def guess(self):
        num = int(input('请输入一个0-10的整数'))
        # print('猜对了' if self.__i == num else '错了错了')
        # print(f'私有属性{self.__i}')
        while True:
            if self.__i == num:
                print('答对了')
                break
            else:
                num = int(input('猜的不对哦,请重新输入:'))

guess_1 = GuessNumber()
guess_1.guess()
  • 作业2
    创建一个煎饼类 调用烹饪时长的方法累计煎饼状态
  • 如果煎的时间在0-3之间则状态为生的
  • 如果煎的时间在3-5之间则状态为半生不熟的
  • 如果煎的时间在5-8之间则状态为全熟的
  • 当时间超过8分钟状态焦了
  • 并且还可以给煎饼添加作料,比如大葱(hhh),大蒜(hhh)?,烤肠等等
class Pancake(object):
    def __init__(self):
        self.pancake_time = 0
        self.status = '生的'
        self.seasoning = []

    def __str__(self):
        return f'煎饼的时间为{self.pancake_time},煎饼的状态为{self.status},加的料是{self.seasoning}'

    def pancake_status(self, cook_time):
        self.pancake_time += cook_time
        if self.pancake_time >= 0 and self.pancake_time < 3:
            self.status = '生的'
        elif self.pancake_time >= 3 and self.pancake_time < 5:
            self.status = '半生不熟'
        elif self.pancake_time >= 5 and self.pancake_time < 8:
            self.status = '全熟'
        elif self.pancake_time >= 8:
            self.status = '焦了'

    def pancake_seasoning(self, seasoning):
        self.seasoning.append(seasoning)


jianbing = Pancake()
jianbing.pancake_status(1)
jianbing.pancake_seasoning('一根香肠,两个蛋')
print(jianbing)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值