学习Python解析器

问题描述 投票:0回答:1

我对 Python 相当陌生,并尝试使用构造函数设置一个类,以具有少量必需属性和大量可选属性,并具有默认值和可接受输入的定义。

我尝试使用 argparse 模块,但我不明白如何解析参数然后将结果传递到类的属性中。这也不允许我定义预期输入的逻辑标准。

我想做一些与此 MATLAB 脚本类似的事情。

methods
        function obj = Platform(ClassID,varargin)
            inPar = inputParser;
            
            expectedClass = {'Ownship', 'Wingman', 'Flight Group', 'Unknown', 'Suspect', 'Neutral', 'Friend', 'Foe'};
            validClassID = @(x) any(validatestring(x,expectedClass));
            addRequired(inPar,'ClassID',validClassID)
            
            defaultDim = struct('length', 0, 'width', 0, 'height', 0, 'oOffset', [0 0 0]);
            validDim = @(x) ~isempty(intersect(fieldnames(x),fieldnames(defaultDim)));
            addOptional(inPar,'Dimensions',defaultDim,validDim)
            
            defaultPos = [0 0 0];
            validPos = @(x) isclass(x,'double') && mean(size(x) == [1 3]);
            addOptional(inPar,'Position',defaultPos,validPos)
            
            defaultOr = [0 0 0];
            validOr = @(x) isclass(x,'double') && mean(size(x) == [1 3]);
            addOptional(inPar,'Orientation',defaultOr,validOr)
          
            defaultTraj = struct('Waypoints',[0 0 0],...
                'TimeofArrival',0,...
                'Velocity',[0 0 0],...
                'Orientation',[0 0 0]);
            validTraj = @(x) ~isempty(fieldnames(x),fieldnames(defaultTraj));
            addOptional(inPar,'Trajectory',defaultTraj,validTraj)
            
            expectedDL = {'LK-16', 'MADL', 'VMF'};
            defaultDL = {};
            validDL = @(x) any(validatestring(x,expectedDL));
            addOptional(inPar,'DataLinks',defaultDL,validDL)
            
            defaultSens = {};
            validSens = @(x) isa(x,'Sensor');
            addOptional(inPar,'Sensors',defaultSens,validSens)
            
            
            parse(inPar,ClassID,varargin{:})
            
            obj.PlatformID = randi([1 10000]);
            obj.ClassID = inPar.Results.ClassID;
            obj.Dimensions = inPar.Results.Dimensions;
            obj.Position = inPar.Results.Position;
            obj.Orientation = inPar.Results.Orientation;
            obj.Trajectory = inPar.Results.Trajectory;            
            obj.Sensors = inPar.Results.Sensors;
            obj.DataLinks = inPar.Results.DataLinks;

            
        end
python matlab parsing python-3.2
1个回答
0
投票

Python 不需要进行这种临时字符串和数组解析排序。

好的 Python 代码是面向对象的。它们应该被封装为“有意义类型的对象”,而不是作为原始字符串和数组传递值。这些对象应该负责在构造时验证自身并在其整个生命周期中维护其不变量。 更好的 Python 代码利用静态类型提示将大部分验证工作转移到代码运行之前。

惯用的 Python 翻译可能看起来像这样(带有一些自由猜测):

from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import NamedTuple, Literal class Position(NamedTuple): x: float y: float z: float @classmethod def origin(cls) -> Position: return cls(0, 0, 0) class Orientation(NamedTuple): yaw: float pitch: float roll: float @classmethod def pos_x(cls) -> Orientation: return cls(0, 0, 0) @classmethod def pos_y(cls) -> Orientation: return cls(1, 0, 0) @classmethod def pos_z(cls) -> Orientation: return cls(0, 1, 0) class Geometry(NamedTuple): extent: Position o_offset: Position @classmethod def unit_cube(cls) -> Geometry: return cls((1, 1, 1), (0, 0, 0)) @dataclass class Trajectory: waypoints: list[Position] = field(default_factory=list) time_of_arrival: float = 0 velocity: Position = Position.origin() orientation: Orientation = Orientation.pos_x() class Platform(ABC): _geometry: Geometry _position: Position _orientation: Orientation _trajectory: Trajectory _datalinks: list[Literal['LK-16', 'MADL', 'VMF']] _sensors: list[Sensors] def __init__( self, geometry: Geometry = Geometry.unit_cube(), pos: Position = Position.origin(), orientation: Orientation = Orientation.pos_x(), trajectory: Trajectory | None = None, datalinks: list[Literal['LK-16', 'MADL', 'VMF']] | None = None, sensors: list[Sensors] | None = None, ) -> None: if trajectory is None: trajectory = Trajectory() if datalinks is None: datalinks = [] if sensors is None: sensors = [] self._geometry = geometry self._position = pos self._orientation = orientation self._trajectory = trajectory self._datalinks = datalinks self._sensors = sensors @abstractmethod def do_something_class_specific(self) -> None: ... class NeutralPlatform(Platform): def do_something_class_specific(self) -> None: self.watch_and_wait() class FooPlatform(Platform): def do_something_class_specific(self) -> None: self.attack_mode()

就是这样。只要类型检查通过,您构造的任何 
Platform

都将得到充分验证。无需对类型系统已经可以验证的内容进行手动验证。

需要更多不变量?以适当的类型强制执行它们。在良好的面向对象设计中,

Platform

不需要(也不应该)需要知道什么是有效的

Orientation
,只需知道它有一个并且它已经有效。
    

© www.soinside.com 2019 - 2024. All rights reserved.