如何在函数中传递命名元组的可选参数

3
__author__ = 'mayukhsarkar'
import collections


def search_student(database=None, ID=None):
    flag = False
    try:
        if ID is None or ID == 0:
            raise TypeError
        for each in database:
            if each.id == ID:
                print 'Student Name: ', each.name
                flag = True
    except TypeError:
        print 'Provide the arguments properly'
    finally:
        return flag


studentDatabase = collections.namedtuple("student", "id name roll_no phone email")

DATABASE = [studentDatabase(1, 'Mayukh Sarkar', 9, '555-2312', 'mayukh2012@hotmail,com'),
        studentDatabase(2, 'Alisha Sengupta', 7, '555-1345', 'alisha@gmail.com')]

if not search_student(DATABASE, 1):
    print "Data not found"

在这个片段中,我想要在函数search_student中添加可变参数选项,以便如果我传递roll_noemail,那么如果找到该id的学生,则只会打印出姓名、滚动和电子邮件。但是如果我不传递任何参数,则只会打印出姓名。

1
我不清楚你在问什么。这里有一个练习可能会有所帮助:假装你的函数已经按照你想要的方式运行,然后发布演示如何使用它的代码。 - Rob Kennedy
好的,我正在提交,请检查。 - Mayukh Sarkar
3个回答

3
使用布尔值来设置是否打印和发送邮件的标志:
```html

使用布尔值来设置是否打印和发送邮件的标志:

```
def search_student(database=None, ID=None, roll=False, email=False):
    if ID is None or ID == 0:
        print 'Provide the arguments properly'
        return False
    for each in database:
        if each.id == ID:
            print 'Student Name: {}'.format(each.name)
            if roll:
                print 'Stutent Roll: {}'.format(each.roll_no)
            if email:
                print("Student email: {}".format(each.email))
            break
    else:
        return "User does not exist in database"


studentDatabase = collections.namedtuple("student", "id name roll_no phone email")

DATABASE = [studentDatabase(1, 'Mayukh Sarkar', 9, '555-2312', 'mayukh2012@hotmail,com'),
            studentDatabase(2, 'Alisha Sengupta', 7, '555-1345', 'alisha@gmail.com')]

输出:

In [9]: search_student(DATABASE, 1, email=True,roll=True)
Student Name: Mayukh Sarkar
Stutent Roll: 9
Student email: mayukh2012@hotmail,com

In [10]: search_student(DATABASE, 1,roll=True)
Student Name: Mayukh Sarkar
Stutent Roll: 9

In [11]: search_student(DATABASE, 1, email=True)
Student Name: Mayukh Sarkar
Student email: mayukh2012@hotmail,com

In [12]: search_student(DATABASE, 1)
Student Name: Mayukh Sarkar

In [13]: search_student(DATABASE, 5)
Out[13]: 'User does not exist in database'

我会将用户信息以字典形式存储,以id作为键:

def search_student(database=None, ID=None, roll=False, email=False):
    if ID is None or ID == 0:
        print 'Provide the arguments properly'
        return False
    get = database.get(ID)
    if get is not None:
            print 'Student Name: {}'.format(get.name)
            if roll:
                print 'Student Roll: {}'.format(get.roll_no)
            if email:
                print("Student email: {}".format(get.email))
    else:
        return "User does not exist in database"

然后将字典作为数据库传递:

studentDatabase = collections.namedtuple("student", "id name roll_no phone email")

DATABASE = {1: studentDatabase(1, 'Mayukh Sarkar', 9, '555-2312', 'mayukh2012@hotmail,com'),
            2: studentDatabase(2, 'Alisha Sengupta', 7, '555-1345', 'alisha@gmail.com')}

输出结果相同:
In [18]: search_student(DATABASE, 1, email=True,roll=True)Student Name: Mayukh Sarkar
Student Roll: 9
Student email: mayukh2012@hotmail,com

In [19]: search_student(DATABASE, 1,roll=True)
Student Name: Mayukh Sarkar
Student Roll: 9

In [20]: search_student(DATABASE, 1, email=True)
Student Name: Mayukh Sarkar
Student email: mayukh2012@hotmail,com

In [21]: search_student(DATABASE, 1)
Student Name: Mayukh Sarkar

In [22]: search_student(DATABASE, 5)
Out[22]: 'User does not exist in database'

你最好使用字典来处理所有逻辑,但是getattr可以与**kwargs一起使用:

import collections


def search_student(database=None, ID=None, **kwargs):
    if ID is None or ID == 0:
        print 'Provide the arguments properly'
        return False
    get = database.get(ID)
    if get is not None:
        print 'Student Name: {}'.format(get.name)
        for k in kwargs:
            print("Student {}: {}".format(k, getattr(get,k)))
    else:
        return "User does not exist in database"


studentDatabase = collections.namedtuple("student", "id name roll_no phone email")

DATABASE = {1: studentDatabase(1, 'Mayukh Sarkar', 9, '555-2312', 'mayukh2012@hotmail,com'),
            2: studentDatabase(2, 'Alisha Sengupta', 7, '555-1345', 'alisha@gmail.com')}

search_student(DATABASE,1,roll_no=True,email=True)

我们需要捕捉用户输入无效的关键字/属性,处理方式有很多种,但一个简单的方法是捕捉属性错误:
        try:
            print("Student {}: {}".format(k, getattr(get, k)))
        except AttributeError:
            print("Informative message or whatever is suitable")

或者使用 hasattr,如果返回 False,则可以执行任何操作:
 if get is not None:
    print 'Student Name: {}'.format(get.name)
    for k in kwargs:
        if not hasattr(get,k):
            continue
        print("Student {}: {}".format(k, getattr(get, k)))

或者向getattr传递默认值:
if get is not None:
        print 'Student Name: {}'.format(get.name)
        for k in kwargs:
            val = getattr(get, k,False)
            if val:
                print("Student {}: {}".format(k, val))
            else:....

这确实很方便,但问题是每次我向命名元组添加一些元素时,都需要再次编辑整个函数... 我希望有一种方法,可以将所有可选参数作为列表传递,并且无论列表中有什么,对于每个元素,都会打印Listvalue。 - Mayukh Sarkar
是的,你说得对。我认为在这种情况下使用字典会更有效率。 - Mayukh Sarkar
我已经完成了一个字典示例,接下来我会添加它,然后再添加一个kwargs版本。 - Padraic Cunningham
尝试捕获异常会很好。否则,如果我们循环遍历每个ID以检查输入的ID是否存在,那么对于大量数据来说,这个过程将非常昂贵。 - Mayukh Sarkar
@MayukhSarkar,hasattr也可以使用,我也添加了它。如何处理用户输入不正确的数据以及你如何处理这个问题,这取决于个人喜好。上面的代码只是给出了正确方向的推动。 - Padraic Cunningham
显示剩余6条评论

1

所以这不是答案,而是一篇帖子,因为@Rob要求进一步澄清

所以如果函数存在,则为func(database=None, ID=None, [optionals])

所以当你调用func(DATABASE, 1, roll_no, email)时,将打印ID为1的人的姓名、电子邮件和roll号码。

但是如果我传递func(DATABASE, 1, roll_no, email, phone),那么将打印姓名、roll号码、电子邮件和电话号码,但如果我只给出DATABASE和ID而没有其他参数,则仅应打印姓名。如果找不到该ID的记录,则不应打印任何内容。


0

您可以使用**符号将变量数量不定的命名参数传递给函数。

如果参数是**args,那么它将是一个字典,其中包含在函数定义中尚未定义的任何命名参数,然后您可以检查args中是否存在roll_noemail,如果存在,则执行您的逻辑。

示例代码 -

>>> def func(**args):
...     print(args)
...     if 'abc' in args:
...             print(args['abc'])
...
>>> func(hello=10)
{'hello': 10}
>>> func(hello=10,abc="Student")
{'hello': 10, 'abc': 'Student'}
Student
>>> def search_student(database=None, ID=None, **args):
...     if 'roll_no' in args:
...             print(args['roll_no'])
...
>>> search_student(roll_no=10)
10

我知道这种方法,但我认为它无法用于命名元组的扩展。您所谈论的是字典,而我不是。 - Mayukh Sarkar
我认为要求是传入一个参数来确定是否打印roll_no和email。 - Anand S Kumar
不仅需要传递变量参数,还需要将它们作为namedtuple的成员进行传递。 - Mayukh Sarkar

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