Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
像Python描述符这样的D元编程?_Python_D_Python Descriptors - Fatal编程技术网

像Python描述符这样的D元编程?

像Python描述符这样的D元编程?,python,d,python-descriptors,Python,D,Python Descriptors,我正在尝试将我的框架的一部分从Python翻译成D,并且正在努力解决一个细节:但首先我必须扩展范围。该组件类似于ORM。我的用户定义类,这些类的实例将在数据库中持久化。用户API应该尽可能简单。比如说 class Person: identity _id, string name, date birthdate, ... class Car: indentity _id, string ident, int power, Person owner ...

我正在尝试将我的框架的一部分从Python翻译成D,并且正在努力解决一个细节:但首先我必须扩展范围。该组件类似于ORM。我的用户定义类,这些类的实例将在数据库中持久化。用户API应该尽可能简单。比如说

class Person:
  identity _id,
  string name,
  date birthdate,
  ...

class Car:
  indentity _id,
  string ident,
  int power,
  Person owner
  ...

myCar = Car.load(ident="DEAD-BEAF")
print myCar.power
print myCar.owner.name
load函数从数据库加载实例数据。但是车主的加载应该推迟到实例被使用之后,因为大多数应用程序都在汽车上工作,车主很少被使用

在Python中,我可以使用。我有一组“字段”类,它们是描述符。比如说

class StringField(object):

    def __get__(self,obj,objtype):
        # get the value from obj

    def __set__(self,obj,value):                    
        # set value in obj
EntityClass有一个适当的元类,用于连接所需的连接。用户在Python中定义:

class Person(EntityClass):      
    name = StringField()
    birthdate = DateField()
    ...

class Car(EntityClass):
  ident = StringField()
  power = IntField()
  owner = RelationField(Person)
  ...
并使用以下类:

myCar = Car.load(ident="DEAD-BEAF")
print myCar.power      (#1)
print myCar.owner.name (#2)
引擎盖下对myCar.power的调用扩展到

Car.power.__get__(myCar,Car)
如果我从数据库加载汽车,我只加载车主Id 所有者

我可以从数据库中加载Person实例

class RelationField(object):

    def __get__(self,obj,objtype):
        if not instance in obj.cache:
            load instance
            add instance to obj.cache
        return instance from obj.cache
将ORM转换为D我尝试了不同的实现。对于简单的基类型,将用户定义属性(UDA)与模板和统一调用语法结合使用非常简单:

struct Persistent {};

save(T)(ref T obj)
  {
  ...
  }

T load(T)(...) 

class Person
  {
  @Persistent string name;
  @Persistent Date birthday;
  ...
  }

class Car
  {      
  @Persistent string ident;
  @Persistent int power;
  @Persistent Person owner; //???
  ...
  }

auto myCar = load!Car(...);
writeln(myCar.power);
writeln(myCar.owner.name)
这个API和Python API一样简单,但我不知道如何实现所有者的延迟加载。我需要的是用属性函数替换所有者成员,但我不知道如何使用编译时元编程实现这一点。那么这是怎么做到的呢?或者有一种惯用的方法吗?

您可以使用。属性名称在编译时可用,因此您可以使用通用代码处理它们,也可以像下面的代码一样,在
模板
行之后使用
if
,创建专门化

struct-Person{
int-id;
字符串名;
}
Person[int]Person\u by\u id;
结构车{
int-id;
整数幂;
int所有者id;
// https://dlang.org/spec/operatoroverloading.html#dispatch
模板opDispatch(字符串属性)
如果(属性=“所有者”)
{
@property ref Person opDispatch(){
按身份返回人员[所有者身份];
}
}
}
void main(){
自动p=人(1,“乔”);
个人身份证[p.id]=p;
汽车c=汽车(123900,1);
断言(c.owner.name==“Joe”);
c、 owner.name=“普通乔”;
断言(person_by_id[1]。name==“Average Joe”);
}
opDispatch
模板可以由mixin模板生成,因此用户应该编写如下内容:

struct-Car{
int-id;
整数幂;
int所有者id;
混合addMyHandlers!汽车;
}
这里,
addMyHandler
mixin模板应该使用传入结构的内省生成上面的
opDispatch
函数。如果希望保持结构整洁,可以在结构外部生成函数,并利用统一函数调用语法(UFCS):

struct-Car{
int-id;
整数幂;
int所有者id;
}
@财产参考人所有者(施工参考车){
按身份证返回人员[汽车车主身份证];
}

owner
函数也可以使用mixin模板生成,使用
Car
上的内省来调查要生成的内容。(与您的python代码类似。)

我想您可以创建一个
Deferred
模板,用它包装
Person
。在那里,您可以创建一个加载它的
get
函数,并使用
alias get this
,这样您就可以编写
owner.xyz
,而不是
owner.get.xyz
。我试过了,但我也想设置值,因此必须能够编写
myCar.owner=new owner(…)。因此,我需要为get和set使用别名this。如果模板实例化到一个结构中而不是类中,您应该能够重写opAssign,尽管我不知道别名this是否适用于结构。非常感谢,将结构模板与
alias this
opAssign
配合使用效果很好。
struct Persistent {};

save(T)(ref T obj)
  {
  ...
  }

T load(T)(...) 

class Person
  {
  @Persistent string name;
  @Persistent Date birthday;
  ...
  }

class Car
  {      
  @Persistent string ident;
  @Persistent int power;
  @Persistent Person owner; //???
  ...
  }

auto myCar = load!Car(...);
writeln(myCar.power);
writeln(myCar.owner.name)