python - 将 JSON 转储解码为对象
问题描述
我正在做我的大学作业,我的讲座正在寻找的一件事是编码一个对象并将其转储为 JSON,对其进行解码然后将其加载到PassengerFlight
课堂中。
当我运行代码时,它一直显示
“PassengerFlight”对象没有属性“airlineName”
当我解码它时,VSCode 显示它具有所有设置的函数变量。我可以让它运行的唯一类是Flight
删除抽象方法时的类。有什么方法可以在PassengerFlight
类中运行它而不显示上述错误?
from abc import ABC, abstractmethod
import json
from json import JSONEncoder
class Flight(ABC, object): # Flight Class (MAIN)
def __init__(self, airlineName, departureAirport, arrivalAirport): # Constructor Method
self.airlineName: str # Declaring attributes & Setting Types
self.departureAirport: str # Declaring attributes & Setting Types
self.arrivalAirport: str # Declaring attributes & Setting Types
def setAirlineName(self, airlineName): # Mutator Method
self.airlineName = airlineName
@abstractmethod # Marking this methods as abstract method, any concrete subclass will have to implement this method
def getPrice(self):
pass
def setDepartureAirport(self, departureAirport): # Mutator Method
self.departureAirport = departureAirport
def getDepartureAirport(self): # Accessor Method
if len(self.departureAirport) > 0: # Error Checking
return self.departureAirport
else:
return "No departure airport set"
def setArrivalAirport(self, arrivalAirport): # Mutator Method
self.arrivalAirport = arrivalAirport
def getArrivalAirport(self): # Accessor Method
if len(self.arrivalAirport) > 0: # Error Checking
return self.arrivalAirport
else:
return "No arrival airport set"
def __eq__(self, otherFlight):
return (self.airlineName == otherFlight.airlineName)
def __str__(self): # Overiding Method
return "\n==================================================\n++++++++++++++++++ Flight Info ++++++++++++++++++\n==================================================\nAirline Name: " + self.airlineName + "\Departure Airport: " + self.departureAirport + "\nArrival Airport: " + self.arrivalAirport
class PassengerFlight(Flight, object): # PassengerFlight Class (EXTENDS MAIN)
def __init__(self, airlineName, departureAirport, arrivalAirport, price, redEye, passengerList, flightType, baggageWeight): # Constructor Method
super().__init__(airlineName, departureAirport, arrivalAirport)
self.passengerList: list # Declaring attributes & Setting Types
self.flightType: str # Declaring attributes & Setting Types
self.baggageWeight: float # Declaring attributes & Setting Types
self.price: float # Declaring attributes & Setting Types
self.redEye: bool
def getAirlineName(self): # Accessor Method
if len(self.airlineName) > 0: # Error Checking
return self.airlineName
else:
return "No airline name set"
def setRedEye(self, redEye):
self.redEye = redEye
def isRedEye(self):
if self.redEye == True:
return "Flight is red eye"
else:
return "Flight is not a red eye"
def setPassengerName(self, passengerList): # Mutator Method
self.passengerList = passengerList
def getPassengerName(self): # Accessor Method
if len(self.passengerList) > 0: # Error Checking
self.passengerList.sort()
return self.passengerList
else:
return "Passenger List Not Set"
def setFlightType(self, flightType): # Mutator Method
self.flightType = flightType
def getFlightType(self): # Accessor Method
if len(self.flightType) > 0: # Error Checking
return self.flightType
else:
return "No Flight Type Set"
def setBaggageWeight(self): # Mutator Method
baggageWeight = 0
for i in range(len(self.passengerList)): # Iterates through passenger list
baggageWeight += 50.00 # For each passenger in the list add 50KG to baggage variable
self.baggageWeight = baggageWeight # Set our attribute equal to the variable
def getBaggageWeight(self): # Accessor Method
if self.baggageWeight == 0:
return "No Baggage Weight Set"
else:
return self.baggageWeight
def setPrice(self, price):
self.price = price * len(self.passengerList)
def getPrice(self):
if self.price != 0:
return self.price
else:
return "Price is not set"
def sortedNames(self):
return sorted(self.passengerList)
def __str__(self): # Overiding Method
return super().__str__() + "\nPassenger Names using sort(): " + str(self.getPassengerName()) + "\nFlight Type: " + self.flightType + "\nBaggage Weight: " + str(self.baggageWeight) + '(KG)\n' + "Money earned for this flight is: " + str(self.getPrice()) + "\nPassenger Names using Sorted(): " + str(self.sortedNames()) + '\n==================================================\n'
class FlightEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
##########################################################
# Calling PassengerFlight Class #
##########################################################
# Initialize Class & Set to Variable
passenger = PassengerFlight(None, None, None, None, None, None, None, None)
passenger.setAirlineName('Aer Lingus') # Set mutators & values
passenger.setArrivalAirport('Chicago O\'Hare Intl') # Set mutators & values
passenger.setDepartureAirport('Dublin') # Set mutators & values
passenger.setRedEye(True)
passenger.setFlightType('Long Haul') # Set mutators & values
passenger.setPassengerName(
['Andrew Check', 'Graham Whitaker', 'John Eire', 'Vicky Bunsworth', 'Lorna Lopsworth']) # Set mutators & values
passenger.setBaggageWeight() # Set mutators & values
passenger.setPrice(200.00)
# uses the overridden _str_ method to print detail of the class
print(passenger)
##########################################################
passengerEncode = json.dumps(passenger, cls=FlightEncoder, indent=4)
passengerDecode = json.loads(passengerEncode)
passengerObj = PassengerFlight(**passengerDecode)
print(passengerObj)
解决方案
暗示
def __str__(self): # Overiding Method
return (
super().__str__()
+ "\nPassenger Names using sort(): "
+ str(self.getPassengerName())
+ "\nFlight Type: "
+ self.flightType
+ "\nBaggage Weight: "
+ str(self.baggageWeight)
+ "(KG)\n"
+ "Money earned for this flight is: "
+ str(self.getPrice())
+ "\nPassenger Names using Sorted(): "
+ str(self.sortedNames())
+ "\n==================================================\n"
)
你打电话super().__str__()
。self
是PassengerFlight
从 继承的实例Flight
。super()
意思是:“调用父类中定义的方法next in__mro__
”。Flight
没有属性。
极好的
该
super()
函数用于访问父类或兄弟类的方法和属性。该super()
函数返回一个表示父类的对象。
面向对象
在父类中使用子类属性打破了“依赖倒置原则”(SOLID)。
在面向对象设计中,依赖倒置原则是解耦软件模块的一种特定形式。当遵循这一原则时,从高级策略设置模块到低级依赖模块建立的常规依赖关系被颠倒,从而使高级模块独立于低级模块实现细节。
高级模块不应该依赖于低级模块。两者都应该依赖于抽象(例如,接口)。抽象不应该依赖于细节。细节(具体实现)应该依赖于抽象。
您的抽象取决于更高级别的实现。
解决方案
from abc import ABCMeta, abstractproperty
class Flight(metaclass=ABCMeta):
@abstractproperty
def airLineName(self):
raise NotImplementedError()
使用抽象中声明的属性,您必须在子类型中实现它。基于此,您可以在没有错误和风险的情况下使用抽象中的抽象属性来调用未实现的属性。此外,它满足 SOLID 原则。
推荐阅读
- c++ - 整数数组回文检查器
- python - 从
- javascript - 如何在表格标签中获取ID
- php - 搜索字符串以查看它是否包含数组 PHP 中的任何字符串
- java - Java RMI 缓冲图像不可序列化
- list - 未处理的异常:迭代期间的并发修改:“_GrowableList”的实例(长度:1)
- android - 滚动 android recyclerview 禁止点击屏幕
- javascript - querySelectorAll() - 为什么它看不到 css 显示的属性
- windows - Directshow CLSID_AsyncReader:如何设置输出引脚样本大小?
- javascript - 检测组件是否只能在滚动时查看一次