2011-12-20 78 views
3

對不起,令人困惑的標題。是否有可能在Python中創建類似於C宏的命名函數?

我想做到以下幾點:(類似defstruct Lisp中)

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與宏進行定義。我沒有使用類的原因是因爲我創建的「結構」將被「綁定」到數據庫(在這種情況下,只是某種格式的文本文件)。並且我不想佔用任何與對象關聯的內存 - 我會將結構表示爲一個數字(如果您願意,則使用對象ID)

+0

所以你要這些getter和setter方法做的,如果沒有實際的記憶是什麼? – robert

+5

對於厭惡課堂,你能更具體嗎?如果你把你的函數放在字典中,你基本上只是重新創建了這個類。這聽起來就像是這裏的標題。 – nmichaels

+0

我有一個巨大的樹形結構。如果我可以避免使用OID而不是對象,那麼我不會使用任何對象引用作爲結果。每個對象訪問都被轉換爲數據庫操作(查找和更新)。 – dividebyzero

回答

1

這應該是您想要的方向上的一個步驟:

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")) 
1

看來,我認爲你正在尋找已經由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,但正如已經通過註釋指出的那樣,這在使用類時並不是真的需要。

0

看起來,這是不容易做蟒蛇 - 經過一些研究。將內部函數添加到全局名稱空間的唯一方法是修改globals()字典,這相當尷尬。

>>> 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) 
相關問題