栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Day33——派生方法的实战演练, 封装,多态

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Day33——派生方法的实战演练, 封装,多态

文章目录
  • 派生方法的实战演练
  • 面向对象三大特性之封装
  • property伪装属性
  • 面向对象三大特性之多态
  • 面向对象之反射
    • 什么是反射?
    • getattr(核心)
    • hasattr
    • settattr
    • delattr
  • 反射实战案例

派生方法的实战演练
import datetime
import json

d = {
  't1': datetime.datetime.today(),
  't2': datetime.date.today()
}
res = json.dumps(d)
print(res)  # 报错  序列化不能序列带有双引号的时间数据

上述代码会报错 无法正常序列化

raise TypeError(f’Object of type {o.class.name} ’
TypeError: Object of type datetime is not JSON serializable

json序列化python数据类型是有限制的 不是所有的类型都可以
ps:即将要被序列化的数据 里里外外都必须是满足的类型才可以

最简单的解决办法

import datetime
import json

d = {
    't1': str(datetime.datetime.today()),
    't2': str(datetime.date.today())
}
res = json.dumps(d)
print(res)  # {"t1": "2022-07-28 16:08:56.479959", "t2": "2022-07-28"}

但是这种方法显得很low,有一种高级的方法

import datetime
import json

d = {
    't1': datetime.datetime.today(),
    't2': datetime.date.today()
}


class MyJsonEncode(json.JSONEncoder):
    def default(self, o):
        '''o就是json即将要序列化的数据'''
        if isinstance(o, datetime.datetime):
            return o.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(o, datetime.date):
            return o.strftime('%Y-%m-%d')
        # 如果是可以序列化的类型 那么不做任何处理 直接让它序列化即可
        return super().default(o)


res = json.dumps(d, cls=MyJsonEncode)
print(res)  # {"t1": "2022-07-28 16:21:29", "t2": "2022-07-28"}
json.dumps(d, cls=MyJsonEncode)
面向对象三大特性之封装
  • 理解

    封装其实就是将数据或者功能隐藏起来(包起来 装起来)

  • 封装的目的

    隐藏的目的不是让用户无法使用 而是给这些隐藏的数据开设特定的接口 让用户使用接口才可以去使用 我们在接口中添加一些额外的操作

  • 注意

    1.在类定义阶段使用双下划线开头的名字,都是隐藏的属性

    后续类和对象都无法直接获取

    2.在python中不会真正的限制任何代码

    隐藏的属性如果真的需要访问 也可以 只不过需要做变形处理
    __变量名, _类名__变量名

    既然隐藏了 就不改使用变形之后的名字去访问 这样就失去了隐藏的意义

  • 举例说明

    class MyClass(object):
    
        school = '清华大学'
    
        def __init__(self, name, age):
            self.__name = name
            self.__age = age
    
        def info(self):
            print(f'''
            学生名字:{self.__name}
            学生年龄:{self.__age}
            ''')
    
        def view(self, name, age):
            if len(name) == 0:
                print('用户名不能为空')
                return
            if not isinstance(age, int):
                print('必须为数字')
                return
            self.__name = name
            self.__age = age
    
    
    obj = MyClass('lzq', 21)
    obj.info()
    obj.view('gsy', 21)
    obj.info()
    
    '''
    学生名字:lzq
    学生年龄:21
    
    学生名字:gsy
    学生年龄:21
    '''
    

    我们编写python很多时候都是大家墨守成规的东西 不需要真正的限制

property伪装属性
  • 理解

    可以简单的理解为 将方法伪装成数据
    obj.name # 数据只需要点名字
    obj.func() # 方法至少还要加括号
    伪装之后可以将func方法伪装成数据 obj.func

  • 扩展了解

    class Person:
        def __init__(self, name, weight, height):
            self.name = name
            self.weight = weight
            self.height = height
    
        @property
        def BMI(self):
            return self.weight / (self.height ** 2)
    
    
    p1 = Person('jason', 78, 1.83)
    res = p1.BMI  # 不用加括号
    print(res)  # 23.291229956104985
    p2 = Person('lzq', 70, 1.83)
    res = p2.BMI  # 不用加括号
    print(res)  # 20.902385858042937
    
    ```@property```
    
    class Foo:
        def __init__(self, val):
            self.__NAME = val  # 将属性隐藏起来
    
        @property
        def name(self):
            return self.__NAME
    
        @name.setter
        def name(self, value):
            if not isinstance(value, str):  # 在设定值之前进行类型检查
                raise TypeError('%s must be str' % value)
            self.__NAME = value  # 通过类型检查后,将值value存放到真实的位置self.__NAME
    
        @name.deleter
        def name(self):
            raise PermissionError('Can not delete')
    
    
    obj = Foo('jason')
    # print(obj.name)
    # obj.name = 666
    # print(obj.name)
    del obj.name
    
面向对象三大特性之多态

子类可以从父类继承相同的属性或者方法,比如相同的函数名,在子类中可以有不同的实现,即子类可以有自己的特殊性,这就叫做多态。

多态的话按照我的理解就是一个物体的多种形态,比如可口可乐,在原先的基础上现在又有了樱桃味的,无糖等等。就是让原本功能比较简单的类,去在原基础上可以添加其他功能,官方点说就是增加它的灵活性。

为了更加生动的理解多态,再次利用上面的例子:
现在就可以对子类增加一些方法

举例说明

class Animal(object):
    def spark(self):
        pass


class Cat():
    def spark(self):
        print('喵喵喵')


class Dog():
    def spark(self):
        print('汪汪汪')


class Pig():
    def spark(self):
        print('哼哼哼')


c1 = Cat()
d1 = Dog()
p1 = Pig()

c1.spark()  # 喵喵喵
d1.spark()  # 汪汪汪
p1.spark()  # 哼哼哼

一种事物有多种形态 但是相同的功能应该有相同的名字
这样的话 以后我无论拿到哪个具体的动物 都不需要管到底是谁 直接调用相同的功能即可
无论你是鸡 鸭 猫 狗 猪 只要你想叫 你就调固定的叫的功能

python也提供了一种强制性的操作(了解即可) 应该是自觉遵守

import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
    def talk(self): # 抽象方法中无需实现具体的功能
        pass
class Person(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
    def talk(self):
        pass
    def run(self):
        pass
obj = Person()

现在就可以总结出实现多态有两个前提:

1.继承:多态必须发生在父类与子类之间
2.重写:子类重写父类方法

操作系统

linux系统:一切皆文件
只要你能读数据 能写数据 那么你就是文件

内存
硬盘

class Txt: #Txt类有两个与文件类型同名的方法,即read和write
            def read(self):
                pass
            def write(self):
                pass    
        class Disk: #Disk类也有两个与文件类型同名的方法:read和write
            def read(self):
                pass
            def write(self):
                pass      
        class Memory: #Memory类也有两个与文件类型同名的方法:read和write
            def read(self):
                pass
            def write(self):
                pass

python:一切皆对象

只要你有数据 有功能 那么你就是对象

文件名 文件对象
模块名 模块对象

面向对象之反射 什么是反射?

反射就是通过字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动

可以使用反射的地方:

1.反射类中的变量 : 静态属性,类方法,静态方法
2.反射对象中的变量、对象属性、普通方法
3. 反射模块中的变量
4. 反射本文件中的变量

变量名school 与字符串school 区别大不大

stu.school
stu.‘school’

两者虽然只差了引号 但是本质是完全不一样的

getattr(核心)

判断类、对象或者模块中是否有相应的属性或方法。用法:getattr(obj,str,default=None) 判断obj中是否有str属性,有就返回,没有时有传入第三参数就返回第三参数,没有就报错。

class MyClass:
    name = 'lzq'
    age = 21


print(getattr(MyClass, 'name'))  # lzq
print(getattr(MyClass, 'hobby'))  # 报错
print(getattr(MyClass, 'hobby', 'not'))  # not
hasattr

判断时候有某个属性,有就返回True,没有就返回False

class MyClass:
    name = 'lzq'
    age = 21


print(hasattr(MyClass, 'name'))  # Ture
print(hasattr(MyClass, 'hobby'))  # Flase
settattr

设置属性,第三方参数为新的属性

class MyClass:
    name = 'lzq'
    age = 21


setattr(MyClass, 'hobby', 'read')
print(getattr(MyClass, 'hobby'))  # read 新增
setattr(MyClass, 'name', 'gsy')
print(getattr(MyClass, 'name'))  # gsy 修改
delattr

删除某个属性

class MyClass:
    name = 'lzq'
    age = 21


print(getattr(MyClass, 'name'))  # lzq
delattr(MyClass, 'name')  # 删除属性
print(getattr(MyClass, 'name'))  # 报错,因为已经被删除了
反射实战案例
class MyClass:
    def view(self):
        while True:
            choice = input('请输入你的指令:').strip()
            cmd, flag = choice.split()  # 以空格为分隔符分开
            if hasattr(self, cmd):  # 判断是否存在
                func = getattr(self, cmd)  # 取得值
                func(flag)  # 加括号调用,并传参
            else:
                print('没有该执行任务')

    def get(self, flag):
        print('正在下载%s' % flag)

    def put(self, flag):
        print('正在升级%s' % flag)


obj = MyClass()  # 产生对象
obj.view()

'''
请输入你的指令:get a.txt
正在下载a.txt
请输入你的指令:put a.txt
正在升级a.txt
请输入你的指令:a a.txt
没有该执行任务
'''
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1029895.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号