是否可以在Python中创建类似于C宏的命名函数?

2024-10-03 02:42:47 发布

您现在位置:Python中文网/ 问答频道 /正文

抱歉,标题太混乱了。你知道吗

我想做以下工作:(类似于Lisp中的defstruct

def mkstruct(structname, field_dict):
    # create a function called "structname" and get/set functions
    # called "structname_get(s, field_name)" and "structname_set(s, field_name, value)"

# Create a struct "lstnode"
mkstruct("lstnode", {ndkey : 0, nxt: None})
# Make a new struct
node = lstnode()
node_set(node, "ndkey", 5)
v = node_get(node, "ndkey") # v should be 5

这可以在C中通过宏定义来完成。我不使用类的原因是因为我创建的“struct”将“绑定”到数据库(在本例中只是某种格式的文本文件)。我不想占用任何与对象相关联的内存—我将用一个数字来表示结构(如果您愿意的话,可以用一个对象ID)


Tags: and对象namenode标题fieldgetstruct
3条回答

在我看来,您要查找的内容已经由type内置提供:

def mkstruct(structname, field_dict):
    return type(structname, (object,), field_dict)

lstnode = mkstruct("lstnode", {'ndkey' : 0, 'nxt': None})
node = lstnode()
node.ndkey = 5
v = node.ndkey

如果只需要field_dict中的键作为结构的成员,可以将'__slots__'添加到field_dict。你知道吗

注意:这并没有实现任何setter或getter,但是正如注释中已经指出的那样,在使用类时并不真正需要它。你知道吗

这应该是朝着你想要的方向迈出的一步:

def mkstruct(name, attrs):
    def init(self):
        self.id = # not sure how you want to get the id

    def getattr(self, attr):
        if attr not in attrs:
            raise AttributeError(attr)
        # put your database lookup statement here

    def setattr(self, attr, value):
        if attr not in attrs:
            raise AttributeError(attr)
        # put your database update statement here

    return type(
        name,
        (object,),
        __init__=init,
        __getattr__=getattr,
        __setattr__=setattr)

lstnode = mkstruct("lstnode", ("ndkey", "nxt"))

在python中完成这项工作似乎并不容易——经过一些研究之后。将内部函数添加到全局名称空间的唯一方法是修改globals()dict,这相当尴尬。你知道吗

>>> def mkfunc(funcname):
...   def func():
...     print "my name is %s" % funcname
...   func.__name__ = funcname
...   return func
... 
>>> mkfunc("abc")
<function abc at 0xb773ae64>
>>> globals()["abc"] = mkfunc("abc")
>>> abc()
my name is abc

至于我自己的问题,我愿意做以下几点:

def mkstruct(fields):
    def maker(args):
        # validate @args against @fields
        oid = db_insert_row(fields)
        return oid
    def getter(oid, fieldname):
        rec = db_retrieve(oid)
        return rec[fieldname]
    def setter(oid, fieldname, value):
        db_update(oid, fieldname, value)
    return (maker, getter, setter,)

lstnode, lstnode_get, lstnode_set = mkstruct({nodekey: 0, nxt: None})
n = lstnode(nodekey=5)

相关问题 更多 >