簡體   English   中英

python - 字符串模板 - 相同鍵的不同值

[英]python - string template - different values for same key

我有一個SQL模板,我需要替換隨機UUID。

from string import Template
import uuid

def gen_uuid():
    return str(uuid.uuid4())

s = """
insert ... values('foo', ${uuid});
insert ... values('bar', ${uuid});
insert ... values('baz', ${uuid});
"""

mappings = {
    "uuid": gen_uuid  # how??
}

template = Template(s)
print template.safe_substitute(mappings)

如何將不同的UUID值綁定到同一模板鍵?

更新

好的..我最終重載了getitem 不理想,但工作..

class UUIDDict(dict):
    def __init__(self, *args, **kwargs):
        self.update(*args, **kwargs)

    def __getitem__(self, key):
        if key == 'uuid':
            return str(uuid.uuid4())

        return super(UUIDDict, self).__getitem__(key)

第一個問題是您沒有將gen_uuid的結果傳遞給模板,而是在引用函數對象本身。 它應該是:

mappings = {
    "uuid": gen_uuid()
}

使用當前的方法,gen_uuid函數將僅被評估一次,因此每個語句將使用相同的值。

為什么不做這樣的事呢?:

names = ['foo', 'bar', 'baz']

for name in names:
    c.execute("INSERT into foo (a, b) VALUES (%s, %s)", (name, gen_uuid()))

string.Template()不是為單個鍵替換多個值。 其他模板系統可能會支持這一點,但string.Template意味着很簡單。

話雖如此,在循環中執行您想要的操作並不難,然后使用str.join組合結果:

>>> from string import Template
>>> import uuid
>>> def gen_uuid():
        return str(uuid.uuid4())

>>> s = Template("insert ... values('$name', ${uuid});")
>>> t = [s.substitute(name=name, uuid=gen_uuid()) for name in ('foo', 'bar', 'baz')]
>>> print '\n'.join(t)
insert ... values('foo', ee1b1b21-c022-4de5-8f7c-0a4d0554ae49);
insert ... values('bar', 0b96872f-ab0e-48cf-a025-f997f7976a0e);
insert ... values('baz', 25165bb6-8b7b-4c87-9ce1-ca274fc51bc8);

根據OP的建議,可以創建一個自定義字典,在每次查找時構建一個新的uuid():

>>> class UUID_Dict(dict):
        def __missing__(self, key):
            if key == 'uuid':
                 return str(uuid.uuid4())
            raise KeyError(key)


>>> s = Template("""
insert ... values('foo', ${uuid});
insert ... values('bar', ${uuid});
insert ... values('baz', ${uuid});
""")
>>> print s.substitute(UUID_Dict())

insert ... values('foo', eabc65b6-1294-43b7-9506-61a4e324e0f2);
insert ... values('bar', 93e4f0b7-7fa1-4e88-9696-e361da31358f);
insert ... values('baz', 503d34a3-17a4-4513-8ce0-b5efb70c94cc);

這是使用“默認字典”( defaultdict )的解決方案:

from collections import defaultdict
from string import Template
import uuid

def gen_uuid():
    return str(uuid.uuid4())

s = """
insert ... values('foo', ${foo_uuid});
insert ... values('bar', ${bar_uuid});
insert ... values('baz', ${baz_uuid});
"""

mappings = defaultdict(gen_uid)
template = Template(s)
print template.safe_substitute(mappings)

結果將如下所示:

insert ... values('foo', aedd5fb6-40da-45bd-bcf7-c7390ef8f13e);
insert ... values('bar', c7ea3090-2a0f-49aa-ace9-c5ef67b7888b);
insert ... values('baz', bf2d86b7-c13e-4498-8d4a-27e76c2e72ab);

defaultdict是使用單個參數(工廠函數)創建的。 每次在默認字典中查找未知鍵時,它都會調用該函數,將該值綁定到該鍵,然后返回該鍵。 因此,它將為每個變量分配一個新的UUID。

主要的缺點是你不能使用單變量${uuid} ; 您將必須為每個uuid定義一個新變量。 然后,從長遠來看,這可能是更好的做法:這樣,如果您再次需要,您可以訪問模板中每個值的特定UUID。 進行模板替換后,您甚至可以直接從Python代碼訪問UUID:

>>> for k, v in mappings.items():
...     print k, v
... 
baz_uuid bf2d86b7-c13e-4498-8d4a-27e76c2e72ab
bar_uuid c7ea3090-2a0f-49aa-ace9-c5ef67b7888b
foo_uuid aedd5fb6-40da-45bd-bcf7-c7390ef8f13e

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM