首页 > 其他分享 >面向对象之派生方法、封装、伪装、三大特性、反射

面向对象之派生方法、封装、伪装、三大特性、反射

时间:2022-11-07 17:11:29浏览次数:38  
标签:封装 name self datetime 面向对象 def print class 三大

面向对象之派生方法、封装、伪装、三大特性、反射

派生方法实战演练

什么是派生方法?

  • 子类中的定义方法和父类定义方法一模一样的方法,并且扩展了新功能(子类和父类一样,但是子类可以修改父类自定义新功能)
import json
import datetime

d = {
    't1': datetime.date.taday(),
    't2': datetime.datetime.today(),
    't3': 'jason'
}
# 导入datetime、json模块直接打印
res=json.dumps(d)
print(res)
"""
出现报错,AttributeError: type object 'datetime.date' has no attribute 'taday'
查看源码发现datetime模块不能直接序列化(必须是要图片里面显示的类型)
"""
"""
能够被序列化的数据是有限的>>>:里里外外都必须是下列左边的类型
    +-------------------+---------------+
    | Python            | JSON          |
    +===================+===============+
    | dict              | object        |
    +-------------------+---------------+
    | list, tuple       | array         |
    +-------------------+---------------+
    | str               | string        |
    +-------------------+---------------+
    | int, float        | number        |
    +-------------------+---------------+
    | True              | true          |
    +-------------------+---------------+
    | False             | false         |
    +-------------------+---------------+
    | None              | null          |
    +-------------------+---------------+
"""

#解决方法:手动将不符合数据类型转成符合要求的数据类型
like={
    't1':str(datetime.datetime.today()),
    't2':str(datetime.date.today())
}
res=json.dumps(like)
print(res)
"""
输出结果:{"t1": "2022-11-07 15:18:39.654295", "t2": "2022-11-07"}
"""

# 利用派生方法

like={
    't1':datetime.datetime.today(),
    't2':datetime.date.today()
}
res=json.dumps(like)
"""
出现报错:TypeError: Object of type datetime is not JSON serializable
查看JSONEncoder源码发现序列化报错是由default方法触发的
raise TypeError(f'Object of type{o._class_._name_}'f'is not JSONli serializable')
我们如果想要避免报错,那么肯定需要对default方法做修改(派生)
"""
Like = {
    't1': datetime.datetime.today().__str__(),
    't2': datetime.date.today().__str__(),
}
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)
'''让python的不走自己的default走我们自定义的default再放他回去走它的'''

res = json.dumps(Like, cls=MyJsonEncode)
print(res)
json.dumps(Like, cls=MyJsonEncode)    
"""
输出结果:
{"t1": "2022-11-07 16:31:04.973732", "t2": "2022-11-07"}
"""

面向对象三大特性之封装

什么是封装?

  • 封装就是把数据或者功能隐藏起来、包起来
  • 隐藏的目的不是让用户无法使用,而是给这些隐藏的数据开设定的接口

什么是伪装?

  • 将类里面的方法伪装成类里面的数据
class Student(object):
    _school = '清华大学'

    def _init_(self, name, age):
        self._name = name
        self._age = age
1.在类的定义阶段使用双下划线开头的名字都是隐藏的属性(后续类和对象都不可以直接获取 会报错)
2.在python中不会真正的限制任何代码,隐藏的属性如果真的需要访问也可以,只不过需要做变形处理
eg: __隐藏的变量名,实际在名称空间里面_类名__变量名
ps:既然是隐藏,就不应该使用变形之后的名字去访问,那样就没有隐藏的意义了

class Person:
    def __init__(self, name, age, hobby):
        self.__name = name  # 对象也可以拥有隐藏的属性
        self.__age = age
        self.__hobby = hobby

    def get_info(self):
        # 类体代码中 是可以直接使用隐藏的名字
        print(f"""
        姓名:{self.__name}
        年龄:{self.__age}
        爱好:{self.__hobby}
        """)
    
# 隐藏的属性开放修改的接口 可以自定义很多功能
def set_name(self, new_name):
    if len(new_name) == 0:
        raise ValueError('你好歹写点东西')
    if new_name.isdigit():
        raise ValueError('名字不能是数字')
    self.__name = new_name


obj = Person('jason', 18, 'read')
obj.get_info()
# obj.set_name('tony老师')
# obj.get_info()
obj.set_name('')

"""
以后我们在编写面向对象代码类的定义时 也会看到很多单下划线开头的名字
表达的意思通常特使不要直接访问 而是查找一下下面可能定义的接口
"""

伪装

BMI指数:衡量一个人的体重与身高对健康影响的一个指标
    体质指数(BMI)=体重(kg)÷身高^2(m)
	 EX:70kg÷(1.75×1.75)=22.86

class Person(object):
    def __init__(self, name, height, weight):
        self.name = name
        self.height = height
        self.weight = weight
    @property
    def BMI(self):
        return self.weight / (self.height ** 2)


p1 = Person('jason', 1.83, 78)
# p1.BMI()  # BMI应该作为人的基本数据而不是方法
# print(p1.BMI)  # 利用装饰器伪装成数据



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')


f = Foo('jason')
print(f.name)
f.name = 'jason123'
print(f.name)
del f.name
# f.name = 'jason'  # 触发name.setter装饰器对应的函数name(f,’jason')
# f.name = 123  # 触发name.setter对应的的函数name(f,123),抛出异常TypeError
# del f.name  # 触发name.deleter对应的函数name(f),抛出异常PermissionError

面向对象三大特性之多态

多态:一种事物的多种形态
	水:液态 固态 气态
	动物:人 猪 猫 狗
 
# class Animal:
#     def spark(self):
#         '''叫的方法'''
#         pass
#
#
# class Cat(Animal):
#     # def miao(self):
#     #     print('喵喵喵')
#     def spark(self):
#         print('喵喵喵')
#
#
# class Dog(Animal):
#     # def wang(self):
#     #     print('汪汪汪')
#     def spark(self):
#         print('汪汪汪')
#
#
# class Pig(Animal):
#     # def heng(self):
#     #     print('哼哼哼')
#     def spark(self):
#         print('哼哼哼')


"""
面向对象中多态意思是 一种事物可以有多种形态但是针对相同的功能应该定义相同的方法
这样无论我们拿到的是哪个具体的事物 都可以通过相同的方法调用功能
"""
# s1 = 'hello world'
# l1 = [11, 22, 33, 44]
# d = {'name': 'jason', 'pwd': 123}
# print(s1.__len__())
# print(l1.__len__())
# print(d.__len__())

"""
鸭子类型:只要你看上去像鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子
"""

# linux系统
"""
文件      能够读取数据也能够保存数据
内存      能够读取数据也能够保存数据
硬盘      能够读取数据也能够保存数据
......
一切皆文件
"""
# class File:
#     def read(self): pass
#
#     def write(self): pass
#
#
# class Memory:
#     def read(self): pass
#
#     def write(self): pass
#
#
# class Disk:
#     def read(self): pass
#
#     def write(self): pass

'''python永远提倡自由简介大方 不约束程序员行为 但是多态提供了约束的方法'''
import abc


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


class Cat(Animal):  # 但凡继承Animal的子类都必须遵循Animal规定的标准
    def talk(self):
        pass


cat = Cat()  # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化

面向对象之反射

利用字符串操作对象的数据和方法
1.hasattr()		重点
	判断对象是否含有某个字符串对应的属性名或方法名
2.getattr()		重点
	根据字符串获取对象对应的属性名(值)或方法名(函数体代码)
3.setattr()
	根据字符串给对象设置或者修改数据
4.delattr()
	根据字符串删除对象里面的名字


# class C1:
#     school_name = '小姐姐学院'
#
#     def choice_course(self):
#         print('大宝贝们正在选课')
#
# obj = C1()
'''判断某个名字对象是否可以使用(存在)'''
# 推导思路
# try:
#     obj.xxx
# except AttributeError:
#     print('你木有这个名字')
'''判断用户随意指定的名字对象是否可以使用(存在)'''
# target_name = input('请输入对象可能使用的名字>>>:').strip()
# try:
#     obj.target_name
# except AttributeError:
#     print('你木有这个名字')
"""
字符串的名字跟变量名区别大不大
    'school_name'
    school_name
非常大 完全不一样
"""

# 反射:利用字符串操作对象的数据和方法
# print(hasattr(obj, 'school_name'))  # True
# print(getattr(obj, 'school_name'))  # 小姐姐学院
# print(getattr(obj, 'choice_course'))  # <bound method C1.choice_course of <__main__.C1 object at 0x00000248C0B65A30>>


class C1:
    school_name = '小姐姐学院'

    def choice_course(self):
        print('大宝贝们正在选课')

obj = C1()
while True:
    target_name = input('请输入您想要操作的名字>>>:')
    if hasattr(obj, target_name):
        print('恭喜您 系统中有该名字')
        # 获取该名字对应的数据(值 函数)
        data_or_func = getattr(obj, target_name)
        if callable(data_or_func):
            print('您本次使用的是系统中的某个方法')
            data_or_func()
        else:
            print('您本次使用的是系统中的某个数据')
            print(data_or_func)
    else:
        print('很抱歉 系统中没有该名字')

反射实战案例

1.什么时候应该考虑使用反射 只要需求中出现了关键字
	对象....字符串....
 
2.实战案例
	1.模拟cmd终端
    	class WinCmd:
        def tasklist(self):
            print("""
            1.学习编程
            2.学习python
            3.学习英语
            """)
        def ipconfig(self):
            print("""
            地址:127.0.0.1
            地址:上海浦东新区
            """)
        def get(self, target_file):
            print('获取指定文件',target_file)
        def put(self, target_file):
            print('上传指定文件',target_file)
        def server_run(self):
            print('欢迎进入简易版本cmd终端')
            while True:
                target_cmd = input('请输入您的指令>>>:')
                res = target_cmd.split(' ')
                if len(res) == 1:
                    if hasattr(self, res[0]):
                        getattr(self, res[0])()
                    else:
                        print(f'{res[0]}不是内部或者外部命令')
                elif len(res) == 2:
                    if hasattr(self, res[0]):
                        getattr(self, res[0])(res[1])
                    else:
                        print(f'{res[0]}不是内部或者外部命令')


        obj = WinCmd()
        obj.server_run()
	2.一切皆对象
    	  # 利用反射保留某个py文件中所有的大写变量名及对应的数据值
        import settings
        print(dir(settings))  # dir列举对象可以使用的名字

        useful_dict = {}
        for name in dir(settings):
            if name.isupper():
                useful_dict[name] = getattr(settings, name)
        print(useful_dict)

        # while True:
        #     target_name = input('请输入某个名字')
        #     if hasattr(settings, target_name):
        #         print(getattr(settings, target_name))
        #     else:
        #         print('该模块文件中没有该名字')

标签:封装,name,self,datetime,面向对象,def,print,class,三大
From: https://www.cnblogs.com/zhiliaowang/p/16866627.html

相关文章

  • APICloud实战案例:如何封装AVM组件?(以声网组件为例)
    AVM.js(Application-View-Model)是一个移动优先的高性能跨端JavaScript框架,支持一次编写多端渲染。它提供更趋近于原生的编程体验,通过简洁的模型来分离应用的用户界面、业......
  • 封装去重的方法
    封装的方法1.去除同一数组中对象属性相同的对象fn(array,key){letseen=newSet();returnarray.filter((item)=>{letk=key(item);......
  • python二十九课--对象的封装与多态等知识
    上周内容回顾动静态方法类体代码中编写的函数有三种类型1.绑定给对象的方法:对象调用自动当做第一个参数传入 类中直接定义函数 classC1:def......
  • 封装MyBatis输出结果-简单类型,对象类型,map,resulemap,模糊查询
    封装MyBatis输出结果resultType:执行sql得到ResultSet转换的类型,使用类型的完全限定名或别名。注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身......
  • PyQt5中处理自定义槽的手段(对于界面继承的封装)
    自定义槽由于我打算用QT编辑器来设计Qt界面,所以少不了ui转py的这一步骤。但是每次转ui时,都会自动覆盖原来的文件,这样的话,如果需要在源文件的基础上添加自定义槽,就很麻烦......
  • 面向对象
    目录一、面向对象概念引入(人狗大战)人狗大战简介推导步骤1:代码定义出人和狗推导步骤2:将产生人和狗的字典封装成函数并封装人和狗的攻击函数推导步骤3:人和狗的攻击混乱二......
  • Java学习笔记day5--面向对象的三条学习主线
    1.类及类的成员属性,方法;构造器,代码块,内部类2.面向对象编程的三大特征封装性继承性多态性3.其他关键字publicprivateprotected缺省pa......
  • python基础之面向对象
    python基础之面向对象面向对象前戏之人狗大战"""编写代码简单的实现人打狗,狗咬人的小游戏(剧情需要,人与狗是好朋友)"""#推导步骤1:代码定义出人和狗person1={'name......
  • 周结之面向对象
    周结目录周结编程思想面向对象之类与对象类与对象的创建对象独有的数据与功能动静态方法面向对象之继承的概念继承的本质名字的查找顺序经典类与新式类派生方法编程思想......
  • day28面向对象(2)
    动静态方法在类中定义的函数有多种特性classStudent:school_name='摆烂大学'#1.类中直接定义函数默认绑定给对象类调用有几个参数传几个对象调用第一......