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('该模块文件中没有该名字')

原文地址:http://www.cnblogs.com/HaiMan/p/16866961.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性