封装,property伪类属性,多态,反射

一:派生方法实战演练

import datetime
import json

d = {
    't1': datetime.datetime.today(),
    't2': datetime.date.today()
}
res = json.dumps(d)
print(res)

上述代码无法实现序列化操作

解决办法1:
  • 直接转成字符串,可以解决简单得问题,不推荐使用
import datetime
import json

d = {
    't1': str(datetime.datetime.today()),
    't2': str(datetime.date.today())
}
res = json.dumps(d)
print(res)
解决办法2:
  • 自定义一个类,继承json.JSONEncoder方法,通过派生产生功能
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)
json.dumps(d, cls=MyJsonEncode)

二:封装

1.什么是封装?
  • 封装其实就是将数据或者功能隐藏起来,隐藏的目的不是让用户无法使用 而是给这些隐藏的数据开设特定的接口 让用户通过接口才可以去使用 我们在接口中添加一些额外的操作
2.怎样实现封装?
  • 1.在类定义阶段使用双下划线开头的名字(__ name) 都是隐藏的属性 后续类和对象都无法直接获取
  • 2.由于在python中不会真正的限制任何代码 隐藏的属性如果真的需要访问 也可以 只不过需要做变形处理( 类名_ 变量名)
  • 3.既然隐藏了 就不改使用变形之后的名字去访问 这样就失去了隐藏的意义
class Flower:
    __type = "植物"

    def __init__(self, name, color):
        self.__name = name
        self.__color = color


f1 = Flower('郁金香', '红白相间')

print(f1.__dict__)

# print(f1.name)  # 报错
# print(f1.__name)  # 报错


# 下面的方法虽然能够得到我们想要的数据,但是失去了封装的意义,作为君子不应该这样
print(f1._Flower__color)  # 红白相间
print(f1._Flower__name)  # 郁金香
  • 4.给这些隐藏的数据开设特定的接口 让用户通过接口才可以去使用 我们在接口中添加一些额外的操作
class Flower:
    __type = "生物"

    def __init__(self, name, color):
        self.__name = name
        self.__color = color

    # 获取数据的方法
    def get_info(self):
        print(f"""
            花名是:{self.__name}
            颜色是:{self.__color}
            """)

    # 操作数据的方法
    def set_info(self, name, color):
        if isinstance(name, str) and isinstance(color, str):
            self.__name = name
            self.__color = color
        else:
            print('名字和颜色不许是字符串')
            return


f1 = Flower('郁金香', '红白相间')

f1.get_info()
f1.set_info('玫瑰', '红色')
print(f1.__dict__)  # {'_Flower__name': '玫瑰', '_Flower__color': '红色'}

三:property伪装属性

  • 功能:能够将方法的调用形式伪装成数据的调用形式
1.案例:体脂率BMI
# 体质指数(BMI)=体重(kg)÷身高^2(m)

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)
p2 = Person('悍匪', 72, 1.73)
res = p2.BMI()
print(res)


p1 = Person('BingBing', 75, 1.80)
print(p1.BMI)
print(p1.name)
2.案例:

class Person:

    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, name):
        if not isinstance(name, str):  # 在设定值之前进行类型检查
            raise TypeError('%s must be str' % name)
        self.__name = name  # 通过类型检查后,将值value存放到真实的位置self.__NAME

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


p = Person('ming')
print(p.__dict__)  # {'_Person__name': 'ming'}
p.name = 'xie'
print(p.__dict__)  # {'_Person__name': 'xie'}

del p.name
print(p.__dict__)  # {'_Person__name': 'xie'}

四:面向对象三大特征之多态

1.多态:
  • 多态:一种事物的多种形态

  • 多态就是多个类在继承同一个父类的基础上,具有一个相同的功能(eg:动物共有的功能:叫 ),这个功能的名字可以自定义,但是最好定义成和父类中该功能的名字一样

  • 代码示范:

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


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


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


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

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

  • 代码实现强制执行多态
# 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()
2.鸭子类型
  • 什么是鸭子类型?

  • 只要你长得像鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子

  • 代码示范:

class Teacher:
    def run(self): pass

    def eat(self): pass


class Student:
    def run(self): pass

    def eat(self): pass
  • 拓展
"""
操作系统
    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.反射的四种方法
  • hasattr():判断对象是否含有某个字符串对应的属性
  • getattr():获取对象字符串对应的属性
  • setattr():根据字符串给对象设置属性
  • delattr():根据字符串给对象删除属性
3.反射的代码实现:
# 需求:判断用户提供的名字在不在对象可以使用的范围内

class Person:
    where = "earth"

    def talk(self):
        print('洽谈')


p1 = Person()

# while True:
#     choice = input('请输入要查找的名字').strip()
#     if hasattr(p1, choice):  # 判断名字是否存在
#         res = getattr(p1, choice)  # 得到名字
#         if callable(res):
#             print(res, res())
#         else:
#             print(res)
#     else:
#         print('你要查找的名字不存在')


# 设置名字(存在则修改,不存在则新增)
setattr(p1, 'age', '18')
setattr(p1, 'hobby', 'sing')

print(p1.__dict__)  # {'age': '18', 'hobby': 'sing'}

# 删除名字
delattr(p1, 'age')
print(p1.__dict__)  # {'hobby': 'sing'}
4.反射案例
class FtpServer:
    def serve_forever(self):
        while True:
            inp = input('input your cmd>>: ').strip()
            cmd, file = inp.split()
            if hasattr(self, cmd):  # 根据用户输入的cmd,判断对象self有无对应的方法属性
                func = getattr(self, cmd)  # 根据字符串cmd,获取对象self对应的方法属性
                func(file)
    def get(self, file):
        print('Downloading %s...' % file)

    def put(self, file):
        print('Uploading %s...' % file)
obj = FtpServer()
obj.serve_forever()
5.总结:
  • 以后只要在需求中看到了关键字:…对象…字符串 那么肯定需要使用反射
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python是一门面向对象的编程语言,它支持封装、继承和多态封装是指将数据和行为封装在一个类中,对外部隐藏实现细节,只保留接口。Python通过使用双下划线“__”来实现类的私有属性和方法。 继承是指一个子类可以继承父类的属性和方法,并且可以自己添加新的属性和方法。Python中使用类名后面的括号指定父类,子类会自动继承父类的所有属性和方法。 多态是指同一个方法在不同的子类中具有不同的实现方式。Python中的多态是通过方法重写(覆盖)实现的。子类可以重写父类的方法,并且可以在子类中调用父类的同名方法。 下面是一个简单的Python类的示例,展示了封装、继承和多态的用法: ```python # 定义一个Animal类 class Animal: def __init__(self, name): self.name = name def speak(self): pass # 定义一个Dog类,继承Animal类 class Dog(Animal): def speak(self): return "Woof!" # 定义一个Cat类,继承Animal类 class Cat(Animal): def speak(self): return "Meow!" # 创建一个Dog对象和一个Cat对象 dog = Dog("Rufus") cat = Cat("Fluffy") # 调用它们的speak()方法,输出不同的结果 print(dog.speak()) # 输出:Woof! print(cat.speak()) # 输出:Meow! ``` 在这个示例中,Animal类封装了一个名称属性和一个空的speak()方法,子类Dog和Cat继承了Animal类,并重写了speak()方法以实现多态。最后创建了一个Dog对象和一个Cat对象,分别调用它们的speak()方法,输出不同的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值