day17-面向对象和json

本文介绍了面向对象编程中的属性、继承、多态,以及如何使用json进行数据交换。实例涵盖类属性、对象属性、类方法与对象方法的区别,以及如何在子类中扩展和使用。还演示了如何将Python对象转化为JSON并解析JSON数据。

day 17 面向对象和json知识点

1、属性

​ 1、属性

​ 1)定义类就是用代码描述清楚这个类是拥有哪些相同功能和哪些相同属性的对象的集合

​ a.方法(函数)用来描述相同功能

​ b.属性(变量)用来描述相同属性

​ c.属性分为两种:类属性、对象属性

​ 2)类属性

​ a.怎么定义:直接定义在类中的变量就是类属性

​ b.怎么使用:通过 ‘类.’ 的方式去使用

​ c.什么时候用:如果属性值不会因为读写不同而不一样的时候就用类属性

​ 3)对象属性

​ a.怎么定义:以 ‘self.属性名 = 值’ 的方式定义在 _ init _方法中

​ b.怎么使用:通过 ‘对象.’ 的方式去使用

​ c.什么时候用:如果属性值会因为对象不同而不一样的时候就用对象属性

class Student:
    """学生"""
    # a是类属性
    a = 10

    # name和age是对象属性
    def __init__(self):
        self.name = '朴彩英'
        self.age = 25


print(Student.a)
Student.a = 200
print(Student.a)

stu = Student()
print(stu.name, stu.age)


class Circle:
    """圆"""
    pi = 3.1415926

    def __init__(self):
        self.radius = '半径'


print(Circle.pi)
cir = Circle()
print(cir.radius)

​ 2、对象属性默认值

​ 1)赋一个固定值:每次创建对象的时候不能重新赋值,只能在创建好对象以后修改属性值

​ 2)使用没有默认值的参数赋值

​ 3)使用有默认值的参数赋值

class Person:
    """人"""
    def __init__(self, name, age, gender='女'):
        self.name = name
        self.age = age
        self.gender = gender
        self.height = 170

    def __repr__(self):
        # return f'<name:{self.name}, age:{self.age}, gender:{self.gender}>'
        return str(self.__dict__)


p1 = Person('朴彩英', 25)
p2 = Person('小明', 18, '男')
p3 = Person('小花', 19)

# print(p1.name, p2.name, p3.name)
# print(p1.age, p2.age, p3.age)
# print(p1.gender, p2.gender, p3.gender)
print(p1)
print(p2)
print(p3)

​ 3、self的使用

​ self是谁调用就指向谁,所有在对象中可以直接将self当成对象来使用(这个类的对象能做的事情self都能做)

class Rectangle:
    """矩形"""
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def get_area(self):
        """面积"""
        return self.length * self.width

    def get_perimeter(self):
        """周长"""
        # 将self当成对象来使用
        # self = R1 , self = R2
        return (self.length + self.width) * 2


R1 = Rectangle(10, 20)
R2 = Rectangle(10, 5)
print(R1.get_perimeter())
print(R2.get_perimeter())
print(R1.get_area())
print(R2.get_area())

​ 4、方法的选择

​ 1)对象方法:如果实现函数的功能需要对象(对象属性)就使用对象方法

​ 2)类方法:实现函数的功能不需要对象(对象属性)的前提下需要类就使用类方法

​ 3)静态方法:既不需要类,也不需要对象

2、继承

​ 1、继承:继承就是让子类直接拥有父类的所有属性和方法

​ a.子类:继承者

​ b.父类:被继承者

​ c.语法:

"""
class 类名(父类列表):
    类的说明文档
    类的内容
    
注意:如果定义类的时候没有写父类,那么这个类默认继承python的基类 - object
"""
class Person:
    """人类"""
    count = 61

    def __init__(self):
        self.name = '朴彩英'
        self.age = 25
        self.gender = '女'

    def eat(self):
        """吃饭"""
        print('吃饭')

    def sleep(self):
        """睡觉"""
        print('睡觉')


class Student(Person):
    """学生类"""
    pass


print(Student.count)

stu = Student()
print(stu.name, stu.age, stu.gender)
stu.eat()
stu.sleep()


class A:
    x = 10

    def __init__(self):
        self.y = 12

    @classmethod
    def func1(cls):
        print('func1')

    @staticmethod
    def func2():
        print('func2')

    def func3(self):
        print('func3')


class B(A):
    pass


print(B.x)

b1 = B()
print(b1.y)
b1.func1()
b1.func2()
b1.func3()

​ 2、在子类中添加内容

​ 1)添加类属性和方法:直接在子类中定义新的类属性和新的方法

​ 2)添加对象属性

class C:
    a = 10

    def func1(self):
        print('对象方法func1')

    def __init__(self):
        self.m = 100
        self.n = 200


class D(C):
    # 新增类属性
    x = 1
    y = 2

    def func2(self):
        print('朴彩英')

    def __init__(self):
        # 在这儿调用父类的__init__方法就可以继承父的对象属性
        super().__init__()  # 调用当前类的父类的__init__()
        self.t = 2


print(C.a)
d1 = D()
d1.func1()
d1.func2()
print(d1.t, d1.m, d1.n)


class Animal:
    """动物类"""
    def __init__(self, age, gender='雌'):
        self.age = age
        self.gender = gender


class Cat(Animal):
    def __init__(self, name, breed='金渐层', age=4, gender='雌'):
        super().__init__(age, gender)
        self.name = name
        self.breed = breed

    def __repr__(self):
        return str(self.__dict__)


cat1 = Cat('板栗')
cat2 = Cat('糖一', '布偶', 2)
print(cat1)
print(cat2)

​ 3、多继承可以继承所有父类的所有方法和属性,只能继承第一个父类的对象属性

3、 json 数据

​ 1、json 数据:json 是一种通用的数据格式,主要用于不同语言之间进行有效的数据沟通

​ 2、json 数据格式

​ 1)要求:

​ a.一个json有且只有一个数据

​ b.唯一的这个数据必须是json支持的类型的数据

​ 2)json支持的数据类型:

​ 数字 - 数字直接写,并且支持科学计数法:3e5

​ 字符串 - 只能使用双引号,支持转义字符:“abc”、"\u4e00"、’"\u9fa5"’

​ 布尔值 - 只有 true 和 false 两个值

​ 空值 - null

​ 数组 - 相当于python的列表,[元素1, 元素2,…]

​ 字典 - 相当于python的字典,json的键只能是字符串

​ 3、python数据和json数据的相互转换

​ json模块提供了python中所有和json操作相关的函数

​ 1)json 转 python

"""
json          python
数字           int、float   
字符串          str(双引号变单引号)
布尔值          true -> True;false -> False
空值            null -> None
数组              list
字典              dict

json.loads(json格式字符串)    -   将json格式字符串对应的json数据转换成相应的python数据
注意:json格式字符串    -   指的是字符串内容是json的字符串

"""
import json
json.loads('"abc"')         # 'abc'
json.loads('100')           # 100
json.loads('[10, 20, 30]')  # [10, 20, 30]
json.loads('{"a":10}')  # [10, 20, 30]

result = json.loads(open('files/汽车新闻.json',encoding='utf-8').read())
for x in result['newslist']:
    print(x['title'])

​ 2)python 转 json

"""
python           json
int、float        数字
str              字符串,单引号变双引号
bool              布尔True -> true;False -> false 
列表、元组           数组
dict                字典,键会编程双引号字符串
None                null

json.dump(python数据)     -   将指定的python数据转换成json格式字符串
"""
json.dumps(100)         # 100
json.dumps(True)         # true
json.dumps(None)         # null
json.dumps({10: 20, 'name': '小明', 'b': True})       # {"10":" 20", "name": "小明", "b": true}

result = json.loads(open('files/yxlm.json', encoding='utf-8').read())
for x in result['hero']:
    print(x['title'], x['goldPrice'])

day 17 作业

  1. 定义一个狗类和一个人类:

    狗拥有属性:姓名、性别和品种 拥有方法:叫唤

    人类拥有属性:姓名、年龄、狗 拥有方法:遛狗

    class Dog:
        """狗类"""
        def __init__(self, name, gender, breed):
            self.name = name
            self.gender = gender
            self.breed = breed
    
        def bark(self):
            """叫唤"""
            return '叫唤'
    
    
    class Person:
        """人类"""
    
        def __init__(self, name, age, dog):
            self.name = name
            self.age = age
            self.dog = dog
    
        def walk(self):
            """遛狗"""
            return '遛狗'
    
  2. 定义一个矩形类,拥有属性:长、宽 拥有方法:求周长、求面积

    class Rectangle:
        """矩形类"""
        def __init__(self, width, length):
            self.width = width
            self.length = length
    
        def perimeter(self):
            """周长"""
            return (self.width + self.length) * 2
    
        def area(self):
            """面积"""
            return self.width * self.length
    
    
    r1 = Rectangle(10, 20)
    print(r1.perimeter())           # 60
    print(r1.area())                # 200
    
  3. 定义一个二维点类,拥有属性:x坐标、y坐标 拥有方法:求当前点到另外一个点的距离

    class TheTwoDimensionalPoint:
        """二维点类"""
    
        def __init__(self, x_coordinate, y_coordinate):
            # x坐标和 y坐标
            self.x_coordinate = x_coordinate
            self.y_coordinate = y_coordinate
    
        def distance(self, x1, y1):
            """距离"""
            return ((self.x_coordinate - x1) ** 2 + (self.y_coordinate - y1) ** 2) ** (1/2)
    
    
    t1 = TheTwoDimensionalPoint(1, 2)
    print(t1.distance(2, 3))            # 1.4142135623730951
    
  4. 定义一个圆类,拥有属性:半径、圆心 拥有方法:求圆的周长和面积、判断当前圆和另一个圆是否外切

    class Circle:
        """圆类"""
        pi = 3.1415926
    
        def __init__(self, radius, x_coordinate, y_coordinate):
            # 半径
            self.radius = radius
            # 圆心
            self.center = (x_coordinate, y_coordinate)
    
        def perimeter(self):
            """周长"""
            return 2 * Circle.pi * self.radius ** 2
    
        def area(self):
            """面积"""
            return Circle.pi * self.radius ** 2
    
        def circumscribe(self, radius2, x1, y1,):
            """是否外切"""
            # 两圆心之间的距离
            value1 = ((self.center[0] - x1) ** 2 + (self.center[-1] - y1) ** 2) ** (1/2)
            # 两圆半径之和
            value2 = self.radius + radius2
            if value1 == value2:
                # 外切
                return True
            else:
                # 没有外切
                return False
    
    
    cir1 = Circle(1, 2, 2)
    print(cir1.circumscribe(1, 2, 0))           # True
    print(cir1.circumscribe(1, 4, 5))           # False
    
  5. 定义一个线段类,拥有属性:起点和终点, 拥有方法:获取线段的长度

    class Segment:
        """线段类"""
        def __init__(self, x1, y1, x2, y2):
            self.start = (x1, y1)
            self.end = (x2, y2)
    
        def length(self):
            """线段的长度"""
            return ((self.end[0] - self.start[0]) ** 2 + (self.end[-1]- self.start[-1]) ** 2) ** (1/2)
    
    
    seg1 = Segment(1, 2, 3, 4)
    print(seg1.length())
    
<think>好的,我现在需要帮助用户在DevEco Studio中使用面向对象的方法解析天气预报的JSON数据。用户之前已经询问过类似的问题,所以我要参考之前的回答并调整内容以适应天气预报的场景。 首先,我需要回顾用户提供的上一个回答,确保结构一致。之前的回答包括定义模型类、JSON反序列化、类型安全验证、网络请求结合以及性能优化建议。现在需要将这些步骤应用到天气预报的数据结构上。 天气预报的JSON结构可能比订单更复杂,可能包含嵌套对象数组。例如,可能有一个主对象包含城市信息、当前天气、未来几天的预报等。我需要设计相应的类结构来映射这些数据。 步骤一:定义数据模型类。需要创建CityInfo、CurrentWeather、Forecast等类。注意JSON中的字段命名可能与类属性不同,比如JSON中的"temp"对应类中的temperature。这时候可能需要使用装饰器或手动映射来处理字段名称不一致的问题,但ArkTS可能不支持装饰器,所以需要手动处理。 步骤二:反序列化JSON数据。使用JSON.parse()解析字符串,然后手动将数据赋值到对象实例中。需要确保嵌套对象也被正确转换,比如将每日预报的数组转换为Forecast对象的数组。 步骤三:类型安全验证。添加静态方法或工具类来检查JSON数据的类型,确保字段存在且类型正确,避免运行时错误。例如,检查温度是否为数字,日期是否为字符串等。 步骤四:结合网络请求。使用HarmonyOS的Network Kit发送HTTP请求获取天气预报数据,并在回调中解析JSON。需要处理异步操作,确保在数据返回后更新UI或处理业务逻辑。 步骤五:性能优化。针对可能较大的天气预报数据,使用Profiler工具监控解析过程的性能,考虑流式解析或数据分页来减少内存占用。 还需要考虑用户可能的问题,例如字段名称不一致、处理数组数据、日期格式转换等。在示例代码中要展示如何处理这些情况,比如在模型类中添加fromJson方法或使用构造函数进行转换。 同时,用户提到的引用[1]关于Profiler的Time场景分析任务,应该在性能优化部分提到如何使用该工具来监控JSON解析的耗时,特别是在处理大量预报数据时的性能表现。 最后,生成的相关问题需要围绕天气预报解析的具体挑战,例如处理嵌套数组、字段映射、日期处理等,确保问题与当前主题相关,并引导用户进一步学习。</think>#### 使用面向对象方法解析天气预报JSON数据(DevEco Studio ArkTS示例) --- ### 一、天气预报JSON数据结构分析(示例) 假设接口返回数据结构如下: ```json { "city": { "id": "101010100", "name": "北京市", "coord": {"lon": 116.39, "lat": 39.9} }, "current": { "temp": 26.5, "humidity": 65, "weather": [{"main": "晴", "icon": "01d"}] }, "daily": [ { "dt": 1696233600, "temp": {"day": 28.3, "night": 22.1}, "pop": 0.15 }, { "dt": 1696320000, "temp": {"day": 25.7, "night": 20.8}, "pop": 0.45 } ] } ``` --- ### 二、面向对象解析实现步骤 #### 步骤1:定义领域模型类 ```typescript // 城市信息类 class CityInfo { id: string; name: string; longitude: number; // JSON字段名: coord.lon latitude: number; // JSON字段名: coord.lat constructor(id: string, name: string, lon: number, lat: number) { this.id = id; this.name = name; this.longitude = lon; this.latitude = lat; } } // 温度详情类(处理嵌套对象) class Temperature { day: number; night: number; constructor(day: number, night: number) { this.day = day; this.night = night; } } // 单日预报类 class DailyForecast { timestamp: number; // JSON字段名: dt temperature: Temperature; precipitation: number; // JSON字段名: pop constructor(dt: number, temp: Temperature, pop: number) { this.timestamp = dt; this.temperature = temp; this.precipitation = pop; } // 转换Unix时间戳为可读格式 getFormattedDate(): string { const date = new Date(this.timestamp * 1000); return `${date.getMonth()+1}月${date.getDate()}日`; } } // 主天气数据类 class WeatherData { city: CityInfo; currentTemp: number; // JSON字段名: current.temp dailyForecasts: DailyForecast[]; // 处理数组结构 constructor(city: CityInfo, currentTemp: number, daily: DailyForecast[]) { this.city = city; this.currentTemp = currentTemp; this.dailyForecasts = daily; } } ``` --- #### 步骤2:实现解析处理器 ```typescript class WeatherParser { static parse(jsonStr: string): WeatherData | null { try { const rawData = JSON.parse(jsonStr); // 构建城市信息对象 const city = new CityInfo( rawData.city.id, rawData.city.name, rawData.city.coord.lon, rawData.city.coord.lat ); // 处理每日预报数组 const dailyForecasts = rawData.daily.map((item: any) => new DailyForecast( item.dt, new Temperature(item.temp.day, item.temp.night), item.pop ) ); return new WeatherData( city, rawData.current.temp, dailyForecasts ); } catch (e) { console.error("JSON解析失败: " + e); return null; } } } ``` --- #### 步骤3:实际使用示例 ```typescript // 模拟网络请求获取数据 const jsonResponse = `{...上述JSON结构数据...}`; // 解析并转换 const weatherData = WeatherParser.parse(jsonResponse); if (weatherData) { console.log(`当前温度: ${weatherData.currentTemp}℃`); weatherData.dailyForecasts.forEach(forecast => { console.log( `${forecast.getFormattedDate()} 白天${forecast.temperature.day}℃ ` + `降水概率: ${forecast.precipitation * 100}%` ); }); } ``` --- ### 三、高级技巧 #### 1. 类型安全增强 ```typescript class TypeValidator { static isWeatherDataValid(data: any): boolean { return data?.city?.id && typeof data.current?.temp === 'number' && Array.isArray(data.daily); } } // 在解析前增加校验 if (TypeValidator.isWeatherDataValid(rawData)) { // 安全处理逻辑 } ``` #### 2. 性能优化实践(引用[1]) 1. 使用**Profiler的Time场景分析**监控`WeatherParser.parse()`耗时 2. 对`daily`数组采用分批解析策略(流式处理) 3. 对重复使用的数据(如城市信息)进行缓存 --- ### 四、典型问题解决方案 #### 问题:JSON字段与类属性命名不一致 ```typescript // 方案1:在构造函数中转换 class Temperature { constructor(public day: number, public night: number) {} static fromJson(json: any): Temperature { return new Temperature(json.day_temp, json.night_temp); // 处理字段差异 } } // 方案2:使用适配器模式 class WeatherAdapter { static convertFieldNames(rawData: any) { return { currentTemp: rawData['current-temperature'], // 其他字段转换... }; } } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值