如何将参数名作为参数传递?

4

我有这段代码:

hobbies2 = form.cleaned_data.pop('hobbies2')
PersonneHobby.objects.filter(personne=obj).delete()
for pk_str in hobbies2:
    try:
        hobby = TagTraduit.objects.get(pk=int(pk_str))
        p = PersonneHobby.objects.create(personne=obj,
                                         hobby=hobby)
        p.save()
    except ValueError:
        break  # hack in the POST
    except LookupError:
        break  # hack in the POST

我将使用相同的代码来处理4个不同的字段,例如使用programme展示:

programmes2 = form.cleaned_data.pop('programmes2')
PersonneProgramme.objects.filter(personne=obj).delete()
for pk_str in programmes2:
    try:
        programme2 = TagTraduit.objects.get(pk=int(pk_str))
        p = PersonneProgramme.objects.create(personne=obj,
                                             programme=programme2)
        p.save()
    except ValueError:
        break  # hack = tout stopper
    except LookupError:
        break  # hack = tout stopper

完全相同的代码,只有字段名称不同。因此我想编写一个通用函数,并像这样调用它:

def update_field(post_field, class_field, **kwargs):
    try:
        values = form.cleaned_data.pop(post_field)
        class_field.objects.filter(personne=obj).delete()
        for pk_str in values:
            try:
                v = TagTraduit.objects.get(pk=int(pk_str))
                p = class_field.objects.create(**{'personne': obj,
                                                  field_name: v})
                p.save()
            except ValueError:
                break  # hack = tout stopper
            except LookupError:
                break  # hack = tout stopper
    except KeyError:
        pass
update_field('programmes2', PersonneProgramme, 'programme')
update_field('hobbies2', PersonneHobby, 'hobby')

我的主要问题是最后一个参数,这个参数是在数据库中创建记录时使用的字段名称。

如何操作?

3个回答

4
你可以使用任意数量的关键字参数(**)来实现,并在函数内部插入计算出的额外参数:
def update_field(field, update_this, **kwargs):
     ...
     kwargs[update_this] = TagTraduit.objects.get(pk=int(pk_str))
     p = field.objects.create(**kwargs)
     ...

这使得您可以像这样调用它:
update_field(PersonneHobby, 'hobby', personne=obj)
update_field(PersonneProgramme, 'programme', personne=obj)

3
您可以这样做:
def update_field(..., field_name):
   ...
   tag = TagTraduit.objects.get(pk=int(pk_str))
   p = PersonneProgramme.objects.create(**{'personne': obj, field_name: tag})

我已经更新了我的问题,使用kwargs,你会明白我的意思。 - Olivier Pons

1

我会采纳 @MSeifert 的建议。如果你想让你所写的任何内容都能够工作,仅使用位置参数。

def f(a,b,c):
    a.func(b=b, c=c)  # this is perfectly legal

但更好的方法是,

这样做:

def f(a, **kwargs):
    a.func(**kwargs)  # kwargs is passed as a dict. **kwargs is
                      # unpacking it into key1=val1, key2=val2, ... 

我已经更新了我的问题,使用kwargs,你会明白我的意思。 - Olivier Pons
@Sayse 如果出于某些原因你讨厌我,你可以这样说。但不是这个问题。看第一个代码块。他不确定从 (a,b,c) 中收集 c 是否为 (...,c=c) - C Panda
什么?我真的不讨厌任何人,更不用说网站上的陌生人了。我只是指出你刚刚展示了一段无法运行的代码,并声称别人的答案才是正确的方式,这是不必要的,而且对该答案进行点赞会更有建设性。 - Sayse
第一個,bc 都是值,因此它們不會與應該保存該值的關鍵字的名稱相同。 - Sayse
@Sayse,你是错误的bc根本不是值,它们只是名称/标识符。因此,a.func(b=b,c=c)是合法的,并且它表示a.func(a=<具有名称a的对象>,b=<具有名称b的对象>)。Python变量与C变量不同。在C、C++中,你无法这样做。称它们为“名称”更加恰当。 - C Panda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接