首页 > 编程语言 >Python——面向对象(封装、多态、反射)

Python——面向对象(封装、多态、反射)

时间:2022-11-07 18:33:39浏览次数:42  
标签:obj name Python res self 多态 面向对象 print def

Python——面向对象

派生方法实战

# coding:utf-8
import json
import datetime
# dict_demo = {
#     't1': datetime.date.today(),
#     't2': datetime.datetime.today(),
#     't3': 'jason'
# }
# res = json .dumps(dict_demo)
# print(res)
'''
序列化报错
 raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type date is not JSON serializable
上面序列化时,直接报错,因为字典里有方法,不是默认可序列化的

能够被序列化的数据(必须全部都是以下类型才可以)
  +-------------------+---------------+
    | Python            | JSON          |
    +===================+===============+
    | dict              | object        |
    +-------------------+---------------+
    | list, tuple       | array         |
    +-------------------+---------------+
    | str               | string        |
    +-------------------+---------------+
    | int, float        | number        |
    +-------------------+---------------+
    | True              | true          |
    +-------------------+---------------+
    | False             | false         |
    +-------------------+---------------+
    | None              | null          |
    +-------------------+---------------+
'''
# 解决办法:
# 1、手动转换类型
# dict_demo = {
#     't1': str(datetime.date.today()),
#     't2': str(datetime.datetime.today()),
#     't3': 'jason'
# }
# res = json.dumps(dict_demo)
# print(res)
'''
可正常输出:
{"t1": "2022-11-07", "t2": "2022-11-07 14:58:20.630274", "t3": "jason"}
'''
# 2、派生方法
'''
查看dumps源码,注意cls参数,默认传JsonEncoder
 if cls is None:
        cls = JSONEncoder
查看该类的源码,发现default方法时报错的发起者
 def default(self, o):
    raise TypeError(f'Object of type {o.__class__.__name__} 'f'is not JSON serializable')
编写类继承JsonEncoder并重写default方法之后调用dumps手动传cls = 我们自己写的类
'''
dict_demo = {
    't1': datetime.date.today(),
    't2': datetime.datetime.today(),
    't3': 'jason'
}


class MyJsonEncoder(json.JSONEncoder):
    def default(self, o):
        """
        :param o:接收无法被序列化的数据
        :return:返回可以被序列化的数据
        """
        if isinstance(o, datetime.datetime):
            return o.strftime('%Y-%m-%d %X')
        elif isinstance(o, datetime.date):
            return o.strftime('%Y-%m-%d')
        return super().default(o)


res = json.dumps(dict_demo, cls=MyJsonEncoder)
print(res)
'''
{"t1": "2022-11-07", "t2": "2022-11-07 15:17:57", "t3": "jason"}
'''

面向对象之封装

'''
封装: 将数据和功能'封装'起来
隐藏: 将数据和功能隐藏起来不让用户直接调用,而是通过一些接口,通过调用这些接口,间接的使用
'''
# coding:utf-8
# class C:
#     def func(self):
#         print('come on')
#
#
# obj = C()
# obj.func()  # come on
# # 将func方法伪装成类里面的数据
# obj.func  # 目前运行没有任何效果


# class MyClass:
#     school_name = '清华大学'
#     _ = '文学系'
#     _name = 'HaiMan'
#     '''
#     在类的定义阶段,名字前面有两个下划线,那么该名字会被隐藏,无法被访问
#     '''
#     __age = '18'
#     '''
#     在Python中其实没有真正意义上的隐藏,仅仅是换了名字而已
#     用 类名._类名__名字可以访问
#     '''
#     def __choice_course(self):
#         print('正在选课')
#
#
# print(MyClass.school_name)  # 清华大学
# obj = MyClass()
# print(obj.school_name)  # 清华大学
# print(MyClass._)    # 文学系
# # print(MyClass.__age)  # 报找不到对应的对象的属性错
# '''
# AttributeError: type object 'MyClass' has no attribute '__age'. Did you mean: '_name'?
# '''
# MyClass.__hobby = 'read'
# # 在类定义阶段之外,不会被隐藏
# print(obj.__hobby)  # read
# print(MyClass._MyClass__age)    # 18
# print(MyClass.__dict__)  # 查看类里面所有的名字


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

    def get_info(self):
        # 在类体代码中,是可以直接使用,隐藏的名字的
        print(f"""
        name: {self.__name}
        age: {self.__age}
        hobby: {self.__hobby}
        """)

    # 隐藏的属性开放修改的接口,可以自定义很多功能
    def set_name(self, new_name):
        if len(new_name) == 0:
            raise ValueError('Please input name')
        if new_name.isdigit():
            raise ValueError('Please dont\'t input digit' )
        self.__name = new_name


obj = Person('HanMan', 18, 'read')
print(obj.get_info())
'''
        name: HanMan
        age: 18
        hobby: read
'''
print(obj.set_name('jason'))
print(obj.get_info())
'''
        name: jason
        age: 18
        hobby: read
'''

'''
在今后编写面向对象代码类的定义时,还有很多单下划线开头的名字
表达的意思通常是不要直接访问,而是看看下面可能定义的接口
'''

伪装

'''
伪装: 将类里面的方法伪装成类里面的数据

BMI指数:衡量一个人的体重与身高对健康影响的一个指标
    体质指数(BMI)=体重(kg)÷身高^2(m)
	 EX:70kg÷(1.75×1.75)=22.86
'''
# coding:utf-8
# class Person:
#     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('HaiMan', 1.80, 80)
# p1.BMI()    # BMI应该作为人的基本数据而不是方法
# 报错TypeError:
# print(p1.BMI)   #  24.691358024691358


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(f'{value} must be str')
        # 通过类型检查后,将值value存放到真实的位置
        self.__NAME = value

    @name.deleter
    def name(self):
        raise PermissionError('Can not delete')


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


多态

# coding:utf-8
"""
面向对象中多态意思是
    一种事物可以有多种形态但是针对相同的功能应该定义相同的方法
    这样无论我们拿到的是哪个具体的事物
    都可以通过相同的方法调用功能
"""

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

import abc

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


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

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

反射

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

# class C1:
#     school = '剑桥大学'
#
#     def choice_course(self):
#         print('please choice course')
#
#
# obj = C1()
# obj.choice_course()     # please choice course
'''
判断某个名字对象是否存在
推导思路
try:
    obj.xxx
except AttributeError:
    print('your dont have the name')

判断用户随意指定的名字是否存在
target_name = input('Please input your need judge name')
try:
    obj.target_name
except AttributeError:
    print('your dont have the name')
'''


class C1:
    school_name = '清华大学'

    def choice_course(self):
        print('please choice your course')


obj = C1()
while True:
    target_name = input('Please input your need judge name>>>:')
    if hasattr(obj, target_name):
        print('congratulate you! name is exists')
        # 获取改名字对应的数据(func data)
        data_or_func = getattr(obj, target_name)
        if callable(data_or_func):
            print('it is a func')
            data_or_func()
        else:
            print('it is a data', data_or_func)
    else:
        print('the name is not exists')

反射实战案例

'''
1.什么时候应该考虑使用反射 只要需求中出现了关键字
	对象....字符串....
 
2.实战案例
	1.模拟cmd终端
'''
# coding:utf-8
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('该模块文件中没有该名字')

标签:obj,name,Python,res,self,多态,面向对象,print,def
From: https://www.cnblogs.com/HaiMan/p/16866961.html

相关文章

  • Python decorator
    此处只做标记,没有深入更深层次了解!!!初步的了解,是decorator库可以通过注解的方式扩展方法,扩展是在不改变原有函数的情况下进行的,如下图所示:    另外,网上也看到一些......
  • Python Colorama
    此处借用CSND上的一篇博文作为使用说明,连接为:https://blog.csdn.net/qq_23845779/article/details/105991806该库的主要作用就是用来改变命令行或者控制台输出文字色彩的,......
  • Python获取MySQL的创建表sql到文件中
    importosimportpymysqlpath=r'D:\Projects\sql'ifnotos.path.isdir(path):os.mkdir(path)conn=pymysql.connect(host='192.168.1.17',user='root',......
  • Python基础28
    今日内容概要派生方法实战演练面向对象三大特性之封装面向对象三大特性之多态面向对象之反射反射的实战案例今日内容详细派生方法实战演练importjsonimportda......
  • 面向对象3之封装多态映射
    目录派生方法实战演练面向对象三大特性之封装伪装三大特性之多态面向对象之反射反射实战案例派生方法实战演练importjsonimportdatetimed={'t1':datetime.da......
  • 面向对象之派生方法、封装、伪装、三大特性、反射
    面向对象之派生方法、封装、伪装、三大特性、反射派生方法实战演练什么是派生方法?子类中的定义方法和父类定义方法一模一样的方法,并且扩展了新功能(子类和父类一样,但是......
  • python3-环境篇-03-pycharm创建python工程之hello word
     1.打开pycharm,点击【NewProject】​编辑修改【location】,选择【BaseInterpreter】 编辑选择编辑工程创建成功编辑 右击工程,选择【new】编辑创建hello文件编辑编写输......
  • python监听鼠标键盘
    https://blog.csdn.net/Jason_WangYing/article/details/114155511 #-*-encoding:utf-8-*-importtimeimportpyautoguiaspagimportkeyboard#https:/......
  • Python工具箱系列(十二)
    在计算机世界里只有二进制。唯有人类才会对数据进行类型与价值判断。例如,认为某些文件是文本文件、是WORD/EXCEL文件或者是图片。对于加密算法来说也是一样的,加解密算法处......
  • trec_eval python版本使用及离线安装
    离线安装(服务器无网络)参考linux上离线安装python模块,搜索下载pytrec_eval-0.5.tar.gz,传到服务器上tar-zxvfpytrec_eval-0.5.tar.gz下载pytrec_eval-0.5/setup.py......