面向对象

继承下派生的使用

import json
import datetime


class MyJsonEncode(json.JSONEncoder):
    def default(self, o):
        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)


a = {'b': datetime.datetime.now()}
res = json.dumps(a, cls=MyJsonEncode)
print(res)
'''
TypeError: Object of type 'datetime' is not JSON serializable
json 不能序列化python中所有的数据类型 只能试一下基本数据类型 例如 datetime.datetime类型的数据

解决方法:
1.手动将不能序列化的类型先转换称字符串
str(datetime.datetime.now())
2.研究json源码并重写序列化方法
	研究源码发现报错的方法叫default
		raise TypeError("Object of type '%s' is not JSON serializable" % o.__class__.__name__)
		我们可以重写一个类继承JSONEncoder然后重写default方法
'''

面向对象三大特性之封装

# 封装的含义
将类中某些名字隐藏起来,不让外界直接调用
隐藏的目的是为了提供专门的通道去访问 在通道内可以额外添加功能
# 代码实操
class Student:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    # 设置一个通道,专门修改学生数据
    def set_info(self, name, age):
        if len(name) == 0:
            print('用户名不能为空')
            return
        if not isinstance(age, int):
            print('年龄必须是数字')
            return
        self.__name = name
        self.__age = age

    # 设置一个通道 查看学生数据
    def check_info(self):
        print(f"学生的姓名是{self.__name}")
        print(f"学生的年龄是{self.__age}")


stu1 = Student('tom', 20)
# print(stu1.name)  # AttributeError: 'Student' object has no attribute 'name'
print(stu1.__dict__)  # {{'_Student__name': 'tom', '_Student__age': 20}
stu1.name = 'tom'
print(stu1.__dict__)  # {'_Student__name': 'tom', '_Student__age': 20, 'name': 'tom'}
stu1.check_info()  # 学生的姓名是tom  学生的年龄是20
stu1.set_info('jason',28)
stu1.check_info()  # 学生的姓名是jason 学生的年龄是28

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

property

property就是将方法伪装成数据
'''
eg: 
		体质指数(BMI)=体重(kg)÷身高^2(m)
'''
有时候我们很多数据需要经过计算才可以获得,但是这些数据给我们的感觉属于是数据,而不是功能
class Person:
    def __init__(self, name, heiget, weight):
        self.__weight = weight
        self.__heiget = heiget
        self.__name = name
    @property
    def BMI(self):
        BMIis = self.__weight / self.__heiget ** 2
        return BMIis
p1 = Person('jason',1.83,60)
print(p1.BMI)  # 17.916330735465376

面向对象三大特征之多态

# 什么是多态
一种事物的多种形态
eg:
    动物	猫、狗、猪
    蔬菜  番茄、白菜、西兰花
# 多态性
  class Animal(object):
     def speak(self):
         pass

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

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

  class Pig(Animal):
      def speak(self):
          print('哼哼哼')
'''只要是动物,那么就会交流,就应该调用一个相同的方法,而不是同一个功能,在不同的类里面是不同的名字。这样便于管理'''



# 面向对象的多态性,很早之前我们就接触过
s1 = 'hello world'
l1 = [1,2,3,3]
print(len(s1))
print(len(l1))

'''
多态性的好处在于增强了程序的灵活性和可扩展性,你让通过继承animal类创建一个新类,实例化得到一个对象object,可以使用形同的方法使用object.speak()
面向对象的多态性也需要python程序员自己去遵守,但是python也提供了强制性措施来是想多态性但是不推荐使用
'''
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod   # 该装饰器限制子类必须定义有一个名为talk的方法
    def talk(self):
        pass  # 抽象方法中无需实现具体的功能


class Cat(Animal):  # 只要是继承了Anima的类,就必须遵循Ani规定的标准
    def talk(self):
        pass  # 遵守Animal的规定,定义一个talk方法

c1 = Cat()  #  若Cat类中没有talk方法,就会抛出异常,无法实例化

'''
由多态衍生出一个鸭子类理论
	只要你看着像鸭子、说话像鸭子、走路像鸭子,那么你就是鸭子 
'''
# 鸭子类型举例
'''
在Linux只给你有 一切皆文件的说法
	内存可以存储数据
	硬盘可以存取数据
	那么就都是文件
'''

class Memory(object):
    def read(self):
        pass
    def write(self):
        pass
class Disk(object):
    def read(self):
        pass
    def write(self):
        pass
# 得到内存或者硬盘对象之后 只要想读取数据就调用read 想写入数据就调用write 不需要考虑具体的对象是谁

面向对象之反射

# 什么是反射
专业解释:指程序可以访问、检查和修改本身状态或者行为的一种能力
大白话:其实就是通过字符串来操作对象的数据和功能
# 反射需要掌握的四个方法
hasattr();判断对象是否含义字符串对应的数据或者功能
getattr():根据字符串获取对应的变量名或者函数名
setattr():根据字符串设置对应的键值对(名称空间中的名字)
delattr():根据字符串删除对象对应的键值对(名称空间中的名字)
    
# 反射的实际应用
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def get(self):
        pass

stu1 = Student('jason',23)

print(hasattr(stu1, 'name'))  # True
delattr(stu1,'name')  
print(hasattr(stu1, 'name'))  # False
print(hasattr(Student,'__init__'))  # True
print(getattr(stu1, 'name'))  # jason
print(getattr(Student,'__init__'))  # <function Student.__init__ at 0x0000022F76C2EEE8>
setattr(stu1,'name','tom')
print(stu1.name)  # tom

反射实际案例

# 利用反射获取配置文件中的配置信息
'''一切皆对象,文件也是对象'''
import settings
dir(settings)  # 获取对象中所有可以使用的名字
choice = input('请输入您想要获取的名字:')
getattr(settings, choice)



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()
posted @   名字只需六字  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示