面向对象 四

目录

1.封装的方法
2.封装的实现原理
3.property装饰器
4.多态
5.多态abc模块
6.多态abc理解
7.鸭子类型

1.封装的方法

class Camera:
    def __jj(self):
        print('聚焦')

    def __tgq(self):
        print('调节光圈')

    def __pz(self):
        print('拍照')

    def zx(self):
        self.__jj()
        self.__tgq()
        self.__pz()


c=Camera()
# 把其它方法隐藏了(在方法名前加 __)
# c.zx()
# 在方法名前加__,内部可以正常使用,外部不能使用,相当于隐藏起来了
# c.__jj()  # 报错,找不到这个属性
# c.__tgq()
# c.__pz()


print(Camera.__dict__) # 隐藏起来了,但是内部还是有,只不过变形了
# _类名__方法名
# 外部特别想用(python独有的)
c._Camera__jj()

# 案例二
# 面向对象封装使用之定义一个人类,人有名字,人名不能以sb开头

class Person:
    def __init__(self,name):
        if name.startswith('sb'):
            print('不能以sb开头,name没有放进来')
        else:
            self.__name=name

    def print_name(self):
        print(self.__name)

    def change_name(self,name):
        if name.startswith('sb'):
            print('不能以sb开头,name没有放进来')
        else:
            self.__name = name
# 把name属性隐藏起来,外部访问不到
# 访问不到name属性,如何打印出来?提供一个打印名字的方法
# 改名,定义一个修改名字的方法

# 保证了数据的安全
egon=Person('sb_egon')

egon.change_name('ddd')

egon.print_name()

# 强行使用(不推荐)
egon._Person__name='sb_egon'
egon.print_name()

# 面向对象封装:在类内部(属性/方法) 在前面加__,表示隐藏,只能在内部用,外部使用不到

# 模块中也可以隐藏属性,在属性前加_,只是在模块内部使用,不期望外部的使用
# from s1 import *  导入不进来
from s1 import __name
# print(_name)
print(__name)

2.封装的实现原理

class Person:

    def __init__(self,name,sex,age,idCard):
        self.name = name
        self.sex = sex
        self.__age = age
        self.__idCard = idCard

    def get_idCard(self):
        return self.__idCard

    def __test(self):
        pass

    print("aaaaaaaaaa")


p = Person("比尔盖茨","男",20,"322323232332332")

# print(p.__idCard)
p.__idCard = "XXXXXX"
print(p.__idCard)

print(p.get_idCard())

print(p.__dict__)
print(Person.__dict__)


p.__xxxxxxxxxxxx = 1

print(p.__dict__)


# 通过__dict__ 可以发现
# 1.私有的属性和方法名称 前自动加上了_类名 python就是通过这样的转换方式来实现封装
# 2.只有在类的内部的双下划线才会被自动转换,并且这个转换过程只执行一次,在类定义完成后 后续添加的双下划线开头的名称是不会自动转换的
# 3.父类中私有的方法 子类中无法使用


#在父类中定义的私有方法 能不能被子类所覆盖?

class A:
    def __f1(self):
        print("A __f1")

class B(A):
    def __f2(self):
        # self.__f1()
        super().__f1()
        print("B __f2")

    def test(self):
        self.__f2()

b = B()
b.test()




# 子类无法覆盖父类的私有方法

class  A:
    def f(self):
        self.__f1()   #_A__f1

    def __f1(self):
        print("A  __f1")

class B(A):
    def __f1(self):  # _B__f1
        print("B __f1")

    def f2(self):
        self.f()

b = B()
b.f2()
# 之所以无法覆盖 是因为 子类和父类中的私有方法 名称必然不相同 所以无法覆盖   子类的方法一定子类独有的 因为名称不同




class A:
    __age = 10

# 绕过封装的限制直接访问  这是毫无意义的
print(A._A__age)

3.property装饰器

'''
当一些属性的值 不是固定的而是通过计算得来的时候  我们必须为这个属性增加方法才能完成计算
但是一旦使用方法后 该属性的访问就变成了方法的调用  很明显与其他的属性访问方式不同,这样给使用者造成迷惑
所以需要将这个方法伪装成普通属性 这就用到了Property

property可以将方法伪装成属性 利用这个特点 我们也可以将其使用到封装中
之前没有这个装饰器我们需要为私有的属性 提供两个方法  但是这样一来方位私有属性时的方式就发生了变化
这时候就可以使用property来进行伪装 使得访问私有属性与访问普通属性的方式一致
另外 property还提供了 setter(用于修改属性的值)  和 deleter(删除属性的值)

重点:把方法包装成数据属性
'''

# BIM案例:
class Person:
    def __init__(self,name,weight,height):
        self.name = name
        self.weight = weight
        self.height = height
        # self.bmi = weight/(height*height)
    
    @property # 把方法包装成数据属性
    def bmi(self):
        return self.weight / (self.height * self.height)

p = Person("尔晴",50,1.5)

# 使用property装饰器 可以将一个方法伪装成一个属性
print(p.bmi)
p.height += 0.2
print(p.bmi)


class Student:
    def __init__(self,name,sex,idCard):
        self.name = name
        self.sex = sex
        self.__idCard = idCard

    def get_idCard(self):
        return self.__idCard

    def set_idCard(self,new_id):
        self.__idCard = new_id

    @property # 需要掌握
    def idCard(self):
        return self.__idCard


    @idCard.setter #了解的
    def idCard(self,new_id):
        self.__idCard = new_id

    @idCard.deleter # 了解的
    def idCard(self):
        print("身份证属性被删除了.....")
        del self.__idCard


stu = Student("尔康","男","323254554554")

# print(stu.get_idCard())

# stu.set_idCard("xxxx")

print(stu.get_idCard()) # 使用装饰器前
print(stu.name) # 普通属性的访问

print(stu.idCard) # 使用装饰器后

stu.idCard = "aaaaaaa" # 使用装饰器后的修改操作

print(stu.idCard)

del stu.idCard

print(stu.__dict__)
print(Student.__dict__)

4 .多态

'''
学习知识点的四个重要步骤
    What When Why HOW

多态
    什么是多态
        多种状态 形态
        生活中具备多种形态的事物  水(水蒸气,冰,液态水)  奥特曼(红色 力量,蓝色 速度)  数码宝贝(究极形态)
        一种事物 具备多种形态或状态 就称之为多态
        官方解释:不同对象 可以相应同一方法,并作出不同的行为,产生不同结果

如何实现多态?
   让几个不同类拥有相同父类,这样一来他们就具备了相同的方法,每个子类要覆盖父类的方法,从而每个类的对象行为都不同

    重点:多态的前提是:是同一类事物,最好的办法就是继承同一个基类,多态必须属性方法一致。
'''

# 案例 一


class Animal:
    def eat(self):
        print("动物在吃东西...")
    def sleep(self):
        print("动物在睡觉...")
    def drink(self):
        print("动物需要水.....")

# 以下三类属于同一类
class Person(Animal):
    def eat(self):
        print("人吃粮食...")

class Pig(Animal):
    def eat(self):
        print("猪吃饲料...")

class Dog(Animal):
    def eat(self):
        print("狗吃骨头...")


person = Person()
pig = Pig()
dog = Dog()

#  person,pig,dog对象,属于同一类
# 表现出来的不一样
# 同一类事物都在调用eat方法,但是执行的效果是不一样的:多态

person.eat()
pig.eat()
dog.eat()

# 案例 二

# 当使用了多态之后 对象的使用者不需要关系这个对象具体的实现,只需要知道该对象属于哪个基类,就能直接使用它
# 如此扩展性变高了


class Phone:
    def call(self):
        print("手机就能打电话..")

    def send_msg(self):
        print("手机能发短信..")


class WindowsPhone(Phone):
    def call(self):
        print("拨号打电话..")

    def send_msg(self):
        print("输入号码发短信..")

class IPhone(Phone):
    def call(self):
        print("拨号打电话..")


    def send_msg(self):
        print("输入号码发短信..")




# 可以定义一个方法接受一个手机为参数 无论是是类型的手机 都可以被使用

def CALL(phone):
    phone.call()

wp = WindowsPhone()
ipx = IPhone()

CALL(wp)
CALL(ipx)


# 系统内置的方法有很多都体现了多态


print(len("abc"))
print(len([1,2,3,4,]))
print(len({"name":"123","sex":"man"}))

print("abc".__len__())
print([1,2,3,4,].__len__())
print({"name":"123","sex":"man"}.__len__())

print(len({1,23,4,5}))

5.多态 abc模块

'''
多态是多个类的对象拥有相同的方法,但是我们没有从严格要求说必须提供这些方法,子类完全可以不提供这些方法

现在要做的就是 严格要求 子类必须实现父类声明的方法
'''

import abc
# abstract class 是抽象类的缩写   抽象的意思是 不清晰 不具体 看不懂

#使用ABC模块来限制子类 的步骤
#1.为类中指定元类为abc.ABCMeta
#2.在相应的方法上加上abc.abstractmethod装饰器

class Animal(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def eat(self):
        pass

    @abc.abstractmethod
    def drink(self):
        pass


class Cat(Animal):
    def eat(self):
        print("猫爱吃鱼肉...")

    def drink(self):
        print("用舌头舔..")

class Dog(Animal):
    def eat(self):
        print("狗爱吃骨头...")
    def drink(self):
        print("用舌头舔..")

class Pig(Animal):
    def eat(self):
        print("猪 爱吃草...")

    def drink(self):
        print("用嘴吸的..")

p = Pig()
# p.eat()

c = Cat()
# c.eat()

# 多态的好处 完全不需要考虑得到的对象时声明类型 只要知道了其基类中的内容就能使用
def feeding(animal):
    animal.eat()
    animal.drink()

feeding(c)
feeding(p)
# 多态中的基类 相当于(协议 标准 规范) 要求子类必须满足这些标准

6.多态abc理解

'''
为了保证多态,可以使用abc模块,来实现,如果子类不重写父类的方法,就会报错
不是我们惯用的做法(第一:它有其他方法实现  第二:python中不推荐强制使用父类来约束,推荐鸭子类型)
'''

import abc
class File(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def click(self):
        print('文件被点击')

# 子类如果继承了File,就必须重写click,如果不重写,就报错
class TxtFile(File):
    def click(self):
        print('文本文件,点击被打开了')


class ExeFile(File):
    def click(self):
        print('可执行文件,点击执行')


t = TxtFile()
e = ExeFile()

# t和e属于同一类,但是调用click,他们表现的样子不一样
t.click()
e.click()

7.鸭子类型

'''
有一个对象,只要看起来像鸭子,走路像鸭子,叫声像鸭子,那就是个鸭子
只要一个对象,具备鸭子的所有属性和方法,我们就认为这个对象就是鸭子类的对象,使用多态
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子

对应到代码中就是: 只要你的行为一样 那就把你当成同一个类型来看待
如果你足够自觉 你可以不使用abc模块 也不需要基类 自觉地将方法名字都写成一样 同样可以实现多态
这种方式称之为鸭子类型,是从多态中演变过来的

重点:python中推崇使用鸭子类型,不使用父类
'''

# 方案 一
class Duck:

    def bark(self):
        print("鸭子嘎嘎叫...")

    def run(self):
        print("摇摇晃晃走....")

class Chicken:
    def bark(self):
        print("鸡咯咯叫...")

    def run(self):
        print("摇摇晃晃走....")

def test(obj):
    obj.bark()
    obj.run()
duck = Duck()
c = Chicken()

test(duck)
test(c)

# 方案 二
# 唐老鸭类
class TDuck():
    def speak(self):
        print('唐老鸭叫')

    def run(self):
        print('唐老鸭走路')
    def money(self):
        print('唐老鸭赚钱')

# 普通鸭子类
class PDuck():
    def speak(self):
        print('普通鸭子叫')

    def run(self):
        print('普通鸭子走路')


p = PDuck()
# 只要这个对象有下面两个方法,我们就认为p就是鸭子对象
p.speak()
p.run()

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

推荐阅读更多精彩内容

  • 面向对象介绍 范式编程 编程是程序员用 特定的语法+数据结构+算法 组成的代码来告诉计算机如何执行任务的过程。 一...
    drfung阅读 1,842评论 0 1
  • 抽象类 什么是抽象类 与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的...
    go以恒阅读 555评论 0 3
  • 今日内容 面向对象的三大特性 封装 继承与派生 多态与多态性 绑定方法与非绑定方法 内置的方法 元类 异常处理 内...
    徐弱西阅读 169评论 0 0
  • 面向对象第二大特性:多态 一类事物的多种形态 动物的多种形态:人,狗,猪 文件的多种形态:文本文件,可执行文件 1...
    牛奶加醋阅读 265评论 0 0
  • 面向对象 创建类 通过class关键字定义,类名最好以大写字母开头,举例: 实例化 直接调用类即可实例化,举例: ...
    dawsonenjoy阅读 470评论 0 1