面向对象编程(三)

2022/4/8 22:19:05

本文主要是介绍面向对象编程(三),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

面向对象编程(三)

继承下的派生实际应用

# 功能:重写已有方法,在保证原来功能正常的情况下加入自己需要的功能
import datetime
import json

dict1 = {'datetime':datetime.datetime.today(),'time':datetime.date.today()}
# res = json.dumps(dict1)
# print(res)  # Object of type 'datetime' is not JSON serializable

class MyJSONEncoder(json.JSONEncoder):
    def default(self,o):  # 形参o就是即将要被序列化的数据对象
        print('重写了')
        if isinstance(o, datetime.datetime):
            return o.strftime('%Y-%m-%d %X')  # datetime格式转成字符串
        elif isinstance(o, datetime.date):
            return o.strftime('%Y-%m-%d')  # data时间格式转成字符串
        return super(MyJSONEncoder, self).default(o)  # 重新调用父类的方法,防止以前的功能不能用

res = json.dumps(dict1,cls=MyJSONEncoder)
print(res)  # {"datetime": "2022-04-08 16:01:19", "time": "2022-04-08"}

面向对象三大特征之封装

# 封装的含义
	将类中的某些名字'隐藏'起来 不让外界直接调用
    隐藏的目的是为了提供专门的通道(接口)去访问 在通道内可以添加额外的功能

# 如何封装
eg:
    class Student(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age

        __school = '家里蹲大学'  # 名字前面加杠杠'__'即是封装该名字的意思
        def func1(self):
            print('func1')
        def __func2(self):  # 函数名前面加__就是封装整个函数
            print('func2')

    obj1 = Student('petter',18)
    # print(obj1.name)  # petter
    # print(obj1.__school)  # AttributeError: 'Student' object has no attribute '__school'
    obj1.func1()  # func1
    obj1.__func2()  # AttributeError: 'Student' object has no attribute '__func2'
 
# 怎么调用封装数据?
eg:
    class Student(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age

        __school = '家里蹲大学'  # 名字前面加杠杠'__'即是封装该名字的意思

        def func1(self):
            print('func1')

        def __func2(self):  # 函数名前面加__就是封装整个函数
            print('func2')

        def interface_school(self):  # 定义调用数据的接口
            print('我来自%s'%self.__school)

        def interface_func2(self):  # 定义调用函数的接口
            self.__func2()

    obj1 = Student('petter', 18)
    obj1.interface_school()  # 我来自家里蹲大学
    obj1.interface_func2()  # func2
"""
将数据隐藏起来就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,
    接口之上可以附加额外的逻辑来对数据的操作进行严格地控制
    
目的的是为了隔离复杂度,例如ATM程序的取款功能,该功能有很多其他功能组成
    比如插卡、身份认证、输入金额、打印小票、取钱等,而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来
"""

property(方法伪装成数据)

eg:
    # 输入正方形边长,计算周长和面积
    class Calculate(object):
        def __init__(self, r):
            self.r = r

        @property
        def perimeter(self):
            return '该正方形的周长是%f' % (self.r * 4)

        @property
        def area(self):
            return '该正方形的面积是%f' % (self.r ** 2)
    obj1 = Calculate(5)
    print(obj1.perimeter)  # 和数据一样的调用方式
    print(obj1.area)
运行结果:
    该正方形的周长是20.000000
	该正方形的面积是25.000000

小发现

def func():
    a = 2
    return '运行结果是%s'%a * 3


print(func())
运行结果:
    运行结果是2运行结果是2运行结果是2
如果return关键字后面有运算,要括号括起来,否则会出现多重输出

面向对象三大特征之多态

# 什么是多态?
	一种事物的多种形态
    eg:
        植物>>>草本植物、木本植物、禾本植物
  
# 多态性
	str,dict,tuple,set是不同的数据类型,他们的类也是不同
    但是统计长度的方法都叫len,这就是多态
eg:
    class Cat(object):
        def call(self):
            print('猫叫了')

    class Dog(object):
        def call(self):
            print('狗叫了')

    class Pig(object):
        def call(self):
            print('猪叫了')

    obj1 = Cat()
    obj2 = Dog()
    obj3 = Pig()
    obj1.call()  # 猫叫了
    obj2.call()  # 狗叫了
    obj3.call()  # 猪叫了
'''
有相同操作的类,在定义这种操作时,应统一命名,生成不同的对象后,用不同的对象调用同一个方法名实现不同类里的操作

面向对象的多态性也需要python程序员自己去遵守
'''
# 虽然python推崇的是自由 但是也提供了强制性的措施来实现多态性(不推荐使用)
eg:
    import abc


    class Animal(object,metaclass=abc.ABCMeta):
        @abc.abstractmethod  # 这个语法糖使用后,在继承这个类时,必修要实现下面的方法
        def call(self):
            pass

    class Cat(Animal):
        def aa(self):
            print('aa')
    class Dog(Animal):
        def call(self):
            pass
        def aa(self):
            print('aa')
    # obj1 = Cat()
    # obj1.aa()  # TypeError: Can't instantiate abstract class Cat with abstract methods call
    obj2 = Dog()
    obj2.aa()  # aa
    

面向对象之反射

# 什么是反射
	专业解释:指程序可以访问、检测和修改本身状态或者行为的一种能力
  大白话:其实就是通过字符串来操作对象的数据和功能

# 反射需要掌握的四个方法
	hasattr():判断对象是否含有字符串对应的数据或者功能
  	getattr():根据字符串获取对应的变量名或者函数名
  	setattr():根据字符串给对象设置键值对(名称空间中的名字)
  	delattr():根据字符串删除对象对应的键值对(名称空间中的名字)
      
# 反射的实际应用
# 编写小程序,判断对象中是否有指定的名字,有则取出展示
class Student(object):
    school = '家里蹲大学'

obj1 = Student()
res = input('请输入字段').strip()
if hasattr(obj1, res):  # 如果obj1对象里面有字段,返回Ture
    name = getattr(obj1, res)  # 获取字符串对应变量名或函数名
    if callable(name):  # 如果可调用
        print('类中有一个功能%s'%res,obj1.name())
    else:
        print('类中有一个变量%s'%res,obj1.name)
else:
    print('没找到')

setattr(obj1, 'name','petter' )  # 创建新名字
delattr(obj1,'school')  # 删除名字



这篇关于面向对象编程(三)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程