面向对象(二)

面向对象编程

私有属性

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

练习

  • 定义类为:"人"类
  • 创建对象:rose
  • 初始化对象属性:name 与 age
  • 要求:age 不能在类的外部访问
class People:
    def __init__(self, name, age):
        self.name = name
        # self.age = age
        self.__age = age

    def print_info(self):
        print(self.__age)

    def get_age(self):
        return self.__age

    def set_age(self, new_age):
        self.__age = new_age
        print(f"new_age:{self.__age}")


zs = People('zs', 19)
print(zs.name)
# print(zs.age)       # 在类的外部访问私有属性报错:AttributeError: 'People' object has no attribute 'age'

# 如何才能在类的外部访问私有属性?
zs.print_info()         # 1.私有属性在类的内部的方法当中时可以访问的
print(zs.get_age())     # 2.在类的内部将私有属性返回出来,进行访问
zs.set_age(50)          # 3.在类的外部对私有属性进行修改

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

  • 可以通过类的内部的方法访问私有属性
  • 通过类的内部方法将私有属性返回出去
  • 在类的外部调用该方法并且接收就可

私有方法

私有方法: 就是对象不希望公开的方法
定义方式: 在方法名前面增加两个下划线(例如:__test)
注意:
在 python 中,并没有真正意义上的私有,只有伪私有。当我们在访问时,以 对象 ._ 类名 __ 私有属 性 即可访问,私有方法同理。但是不建议使用。

class Demo:
    def test1(self):
        print('--1--')

    def __test2(self):
        print('--2--')

    def test3(self):
        return  self.__test2()


d = Demo()
d.test1()
# d.__test2()     # 私有方法没有办法直接在类的外部进行访问,报错:AttributeError:

d.test3()         # 通过类的内部的方法去进行调用

d._Demo__test2()    # 注意:可以直接通过 对象._类名__私有方法名()去访问私有方法,但是不推荐使用

知识点

成员介绍

属性

方法

面向对象编程

成员

image.png

实例属性

实例属性属于对象,只能通过对象访问
定义:self. 属性名称
访问:self. 属性名称 或 对象 . 属性名称

练习: 定义一个省份类,打印输出班级每位同学所在的国家与省份。

class Procince:
    def __init__(self, name):
        # 实例属性 self.属性名
        self.country = '中国'
        self.name = name

    def print_info(self):
        # print(self.country, self.name)      # self就是对象本身访问
        # print(clara.country, clara.name)  # 通过每个对象 访问 可以 但不建议使用
        # print(Procince.country, Procince.name)  # 报错

clara = Procince('湖南')
jx = Procince('广州')
clara.print_info()
jx.print_info()
image.png

类属性 ( 静态属性 )

类属性属于类,保存在类中。在创建时,仅创建一份,并且所有对象都共享
静态属性。执行时可以是类访问也可以是对象访问。
定义: 直接在类中定义
访问: 类名 . 属性名称 或 self. 属性名称 或 对象 . 属性名称

class Province:
    country = '中国'

    def __init__(self, name):
        self.name = name

    def print_info(self):
        # print(self.country, self.name)    # self就是对象本身访问 类属性
        # print(clara.country, clara.name)  # 通过每个对象 访问 可以 但是不建议使用
        print(Province.country, self.name)  # 类属性,可以直接通过类名来访问


clara = Province('湖南')
jx = Province('广州')
clara.print_info()
jx.print_info()

属性总结

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

实例方法

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

  • 当需要在方法中使用实例属性时,通常使用实例方法
  • self 仅仅是变量名。使用其它也可,但最好不要修改
class Demo:
    def __init__(self):
        self.name = 'hlll'

    # 实例方法:通常用于需要使用实例属性
    def test_one(self):
        # print(self)
        print(self.name)


d = Demo()
d.test_one()

类方法

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

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

静态方法

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

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

    def __init__(self):
        self.name = 'hlll'

    def test_one(self):
        print(self.name)


    @classmethod
    def cls_md(cls, age):   # 自建参数不再是self,而是cls,代指类
        print(cls)          # <class '__main__.Demo'>
        print(age)

    @staticmethod
    def stat_md():
        print('我是静态方法')


d = Demo()
d.test_one()
d.cls_md(18)
d.stat_md()
import time

# 获取当前的时间
def show_time():
    print(time.localtime()) # 返回当前的时间,元组

    print(time.strftime('%Y : %m : %d',time.localtime()))

show_time()
import time


class TimeTes:

    @staticmethod
    def show_time():
        print(time.localtime()) # 返回当前时间,元组

        # 进行时间格式化
        print(time.strftime('%Y : %m : %d', time.localtime()))

t = TimeTes
t.show_time()

知识点

封装

继承

多态

面向对象编程

封装介绍

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

image.png
class Student:
    addr = "123"

    def __init__(self, name, age):
        self.name = name  # 将属性封装到类的内部
        self.age = age

    def print_info(self):
        print(self.name, self.age)

        # print(self.addr)
        # self.addr = "222"
        # print(self.addr)    # 不能通过实例去修改类属性的
        # print(Student.addr)


# 在同一个类创建多个对象之间,属性是互不干扰的
xn = Student("寻你", 19)
jx = Student("九夏", 29)
xn.print_info()
jx.print_info()

继承 ( 重点 )

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

image.png

注意:在 python 中,新建的类可以继承一个或多个父类
继承作用:避免重复造轮子,减少代码的冗余

新式类与经典类

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

image.png

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

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

  • 对象 .__dir__() 查看对象的属性与方法
# 但是注意,在python3当中,默认的手是新式类
class Dome:     # 在python2中,经典类
    pass


class Dome2(object):    # 继承了object,在python2中,新式类
    pass

d1 = Dome()
d2 = Dome2()

print(len(d1.__dir__()))
print(len(d2. __dir__()))

单继承

子类继承父类,则可以直接享受父类中已经封装好的方法
练习:用代码实现如下

image.png

单继承

当对象调用方法时,查找顺序先从自身类找,如果自身没找到,则去父类找,父类
无,再到父类的父类找,直到object类,若还无,则报错。这也称为深度优先机制

image.png

单继承

需要注意的是,当子类与父类拥有同名称的方法时,子类对象调用该方法优先执行
自身的方法。那么实际上就是子类的方法覆盖父类的方法,也称为重写
但是实际的开发中,遵循开放封闭原则。我们并不会完全的重写父类的方法,而是
希望同时实现父类的功能。这时,我们就需要调用父类的方法了,可以通过 super()
函数实现。

super()

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

  • type --> 类
  • object-or-type --> 对象或类,一般是 self
    练习: 继以上练习实现,在Son的sleep方法当中,调用父类的sleep方法。
class GrandFather(object):
    def sleep(self):
        print('GrandFather sleep 10')


class Father(GrandFather):
    def eat(self):
        print('Father')

    def drink(self):
        print('Father drink')


class Son(Father):
    def stuy_python(self):
        print('Son study python')

    def sleep(self):
        print('Son sleep 8')    # 当子类与父类名字相同的方法时,就意味着重写了父类的方法!
        # 在执行自己的方法的时候 仍然继承父类的方法
        super(Son, self).sleep()    # Son的对象去调用父类的sleep方法
        # super().sleep()     # 参数不传也可以
        # GrandFather.sleep(self)     # 通过 类名.方法名(self)


s = Son()
s.eat()
s.sleep()

'''
1.单继承:深度优先
2.重写:
      防止执行父类当中的方法
3.self永远指的是执行该方法的调用着
4.super(当前类,self).父类的发方法(arg)
'''

注意

  • init方法也会继承,同实例方法一致
  • 私有属性以及私有方法没有被继承
"""
__init__方法是否会被继承?也会继承,并且同实例方法一致。深度优先
"""

class Father(object):
    def __init__(self):
        print('Father')


class Son(Father):
    pass

s = Son()


"""
私有属性与私有方法是否被继承?
"""
class Father(object):
    def __init__(self):
        self.name = 'amy'
        self.__age = 18

    def test(self):
        print('test')

    def __test2(self):
        print('__test2')


class Son(Father):
    def get_test(self):
        print(self.name)
        self.test()
        # 注意:私有属性不会被继承
        # print(self.__age)
        # 注意:私有方法也不会被继承
        # self.__test2()


s = Son()
# print(s.name)
# print(s.__age)
s.get_test()
image.png
"""
ü 作业 1
玩个特别无聊的游戏 , 猜数字。
玩家输入一个数字与
计算机随机生成的数字作对比
当两个值相等时 , 则说明用户猜对了
注意 : 外部不能获取到计算机随机生成的值
"""
import random

class GuessNumber:

    def j_number(self):
        a = input('请输入一个数字:')
        n = random.randint(0, 9)
        if n == a:
            print('猜对了!')
        else:
            print('猜错了。')


c = GuessNumber()
c.j_number()
import random


class GuessNum(object):
    def __init__(self):
        self.__rand_num = random.randint(1, 10)
        print(f'random_number:{self.__rand_num}')


    def guess_it(self):
        ipt_num = int(input('请输入1-10的数'))

        while True:
            if self.__rand_num == ipt_num:
                print('猜对了')
                break
            else:
                ipt_num = int(input('猜的不对奥,请重新输入!'))


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

    def __str__(self):
        return f'煎饼的状态{self.cake_status},煎的时长{self.cake_level},添加的佐料{self.condiments}'

    def cook(self, cooked_time):
        self.cake_level += cooked_time
        if self.cake_level >= 0 and self.cake_level < 3:
            self.cake_status = '生的'
        elif self.cake_level >= 3 and self.cake_level < 5:
            self.cake_status = '半生不熟的'
        elif self.cake_level >= 5 and self.cake_level < 8:
            self.cake_status = '全熟的'
        elif self.cake_level >= 8:
            self.cake_status = '焦了'

    def add_condiments(self, food):
        self.condiments.append(food)
        
        
pc = PanCate()
pc.cook(1)
pc.cook(1)
pc.add_condiments('肠')
print(pc)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 面向对象 回顾:反射:以字符串的形式去某个对象(模块,类,对象)操作它的成员(python中,一切皆对象)# 从模...
    AndroidCat阅读 243评论 0 0
  • 1.内置类属性 内置类属性就是魔法属性魔法属性:属性名的前后都有两个下划线魔法方法:方法的前后都有两个下划线类的属...
    oxd001阅读 169评论 0 1
  • 继承 面向对象编程中有一个重要的思想叫继承,子类通过继承可以获得父类的属性和方法,被继承的类叫做父类(基类),继承...
    8053820bb06a阅读 50评论 0 0
  • 一.析构函数 # __del__方法,只要这个对象在内存中即将被消灭的时候,就会调用这个方法 class Pers...
    无敌帅帅头阅读 163评论 0 0
  • 周末学习了一下Dart语言,按照慕课网Flutter开发第一步-Dart编程语言入门[https://www.im...
    h2coder阅读 424评论 0 1