将数据集DataSet对象化

在delphi开发数据库应用程序时,经常需要和数据集打交道,TDataSet 提供了浏览,修改数据等操作,使用非常方便。但也正因为使用方便,所以代码中到处充斥着 FieldByName 这样的语句,随着时间的推移,项目的维护修改,整个代码阅读起来很艰涩,且DataSet作为数据存储的中心,经常在多个目模块间传递引用,而其他模块也很方便修改DataSet中的数据,常常容易造成数据混乱,发生错误。

在实际工作中,发现解决上面问题的较好的方法是,将 DataSet  的数据转化为业务对象,并且业务对象的定义统一放置于一个单元中,这样在其它模块中使用的是业务对象,代码阅读起来容易理解,方便修改,且在一个单元中维护对象的定义也为日后维护提供了方便。

所以,如何将 DataSet  转为为业务对象就成为关键,在这里我提供一个简单例子,希望neng抛砖引玉的作用。 

例子:

业务对象为 People

unit uMap_Peo;

interface

uses DB;

type
  PeoRec = record  //Peo结构
    Name: string;
    Age: Integer;
    Nation: string;
  end;
  PPeoRec = ^PeoRec;
 
  TPeoField = (Name, Age, Nation);  //Peo数据字段定义

const
  PeoFieldName: array[TPeoField] of string = ( //Peo数据库中字段名
     'Name', 'Age', 'Nation'
  );

type

  TPeo = class  
  private
    aDs : TDataSet;
  public
    constructor Create(aDs: TDataSet);
    function GetProps(Prop: TPeoField): Variant;
    procedure SetProps(Prop: TPeoField; const Value: Variant);
    property Prop[Prop: TPeoField]:Variant  read GetProps write SetProps; default; //默认属性
    property Data:TDataSet  read aDs;
  end;

procedure NewPeo(aDs: TDataSet; var aPeo : PeoRec);


implementation

{ TPeo }

procedure NewPeo(aDs: TDataSet; var aPeo : PeoRec);
var
  aDsPeo: TPeo;
begin
  aDsPeo:= TPeo.Create(aDs);
  try
    aPeo.Name := aDsPeo[Name];
    aPeo.Age := aDsPeo[Age];
    aPeo.Nation := aDsPeo[Nation];
  finally
    aDsPeo.Free;
  end;
end;

constructor TPeo.Create(aDs: TDataSet);
begin
  inherited Create;
  Self.aDs := aDs;
end;

function TPeo.GetProps(Prop: TPeoField): Variant;
begin
  Result := aDs.FieldByName(PeoFieldName[Prop]).Value;
end;

procedure TPeo.SetProps(Prop: TPeoField; const Value: Variant);
begin
  aDs.FieldByName(PeoFieldName[Prop]).Value := Value;
end;

end.

TPeo 作为 DataSet  的影射集,和 DataSet  一样,操作只影响当前记录,使用如:
var
  Peo: TPeo
.......
 edtname.text :=  Peo[Name];
 edtAge.text := Inttostr(Peo[Age]);
edtNation.text :=  Peo[Nation];
....

一般来说,创建 TPeo 的模块是数据管理中心,集中管理这个TPeo 中的 DataSet  的数据。

其他模块要使用此数据集中的一条或多条数据,应使用 DataSet  的数据副本,而不是将DataSet 传递过去,从而避免对数据中心管理DataSet产生影响。

使用 DataSet  的数据副本, 也就是使用 PeoRec 记录结构,它占用资源小,操作方便,值传递.
var
  aPeo: PeoRec;
.......
    aPeo.Name := 'XXX';   
........ 

通过对DataSet的对象化,传递数据副本,有效避免了以往程序中多模块间相互粘连多个数据集的情况,有效划分了模块间的责任,毕竟很多的处理需要的是对象而不是数据集本身.

 

 在delphi2005之后,编译器支持一种新的数据类型 records 如:

type
  PeoRec = record
    var
      Age: Integer;
      Name: string; 
    class var
      Nation: string;
    procedure SayHello();
    procedure SetAge(value: integer);
    constructor Create(const aName: string; val: Integer); //可选的
    property AgeProp: Integer read Age write SetAge;
    class property NationProp: String read Nation ;
end;


可以看到,Records 可以将 Record类型 像对象那样看待,允许包含过程,方法,属性。使用起来更方便了。

 

 

 

在 PyTorch 中,自定义数据集可以通过继承 `torch.utils.data.Dataset` 类来实现。这个类需要实现两个方法:`__len__` 和 `__getitem__`。 `__len__` 方法返回数据集的长度,即样本数量。`__getitem__` 方法返回数据集中一个索引对应的样本。 下面是一个简单的例子,假设我们有一个文件夹 `data`,里面包含若干张图片和对应的标签,我们要把这个数据集用 PyTorch 加载起来: ```python import os from PIL import Image import torch.utils.data as data class CustomDataset(data.Dataset): def __init__(self, root_dir): self.root_dir = root_dir self.img_list = os.listdir(root_dir) def __len__(self): return len(self.img_list) def __getitem__(self, index): img_path = os.path.join(self.root_dir, self.img_list[index]) img = Image.open(img_path).convert('RGB') label = int(self.img_list[index].split('_')[0]) return img, label ``` 在上面的例子中,我们定义了一个 `CustomDataset` 类,它有一个构造函数 `__init__`,接收一个参数 `root_dir` 表示数据集所在的文件夹路径。`__init__` 方法初始化了 `img_list` 属性,里面保存了所有图片文件名。 `__len__` 方法返回了 `img_list` 的长度,即数据集中样本的数量。 `__getitem__` 方法接收一个索引 `index`,返回了数据集中第 `index` 个样本的图片和标签。具体地,它首先获取了图片文件的路径,然后用 `PIL` 库打开图片并换成 RGB 模式。最后,它从文件名中解析出标签信息,并把图片和标签一起返回。 有了这个自定义数据集类,我们就可以用 PyTorch 的 `DataLoader` 类来加载数据集了。例如: ```python import torch.utils.data as data dataset = CustomDataset('data') dataloader = data.DataLoader(dataset, batch_size=32, shuffle=True) ``` 在上面的例子中,我们创建了一个 `CustomDataset` 对象 `dataset`,然后用 `DataLoader` 类来初始化 `dataloader` 对象。`DataLoader` 的第一个参数是数据集对象,第二个参数是批量大小,第三个参数是是否打乱数据集顺序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值