关于python:用可选的关键字参数定义类’__init__方法有什么更好的方法?

What is a better way to define a class' __init__ method with optional keyword arguments?

我想让全班同学做同样的事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Player:
    def __init__(self, **kwargs):
        try:
            self.last_name = kwargs['last_name']
        except:
            pass
        try:
            self.first_name = kwargs['first_name']
        except:
            pass
        try:
            self.score = kwargs['score']
        except:
            pass

但我觉得这很马虎。有没有更好的方法来定义这个初始化方法?我希望所有关键字参数都保持可选。


如果您只有3个关键字参数,那么这会更好。

1
2
3
4
5
6
class Player:

    def __init__(self, last_name=None, first_name=None, score=None):
        self.last_name = last_name
        self.first_name = first_name
        self.score = score


如果您只有3个参数,那么Bhargav Rao的解决方案更合适,但是如果您有很多潜在参数,请尝试:

1
2
3
4
class Player:
    def __init__(self, **kwargs):
        self.last_name = kwargs.get('last_name')
        # .. etc.

kwargs.get('xxx')如果存在将返回xxx键,如果不存在则返回none。.get接受一个可选的第二个参数,如果xxx不在kwargs中(而不是None中),则返回该参数,例如使用kwargs.get('xxx',"")将属性设置为空字符串。

如果您真的希望属性未定义,如果它不在kwargs中,那么将执行以下操作:

1
2
3
4
class Player:
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

这将是令人惊讶的行为,所以我建议不要这样做。


有一种方法可以很容易地进行更改:

1
2
3
4
5
6
7
8
9
10
class Player:
    _VALID_KEYWORDS = {'last_name', 'first_name', 'score'}

    def __init__(self, **kwargs):
        for keyword, value in kwargs.items():
            if keyword in self._VALID_KEYWORDS:
                setattr(self, keyword, value)
            else:
                raise ValueError(
                   "Unknown keyword argument: {!r}".format(keyword))

样品用途:

1
Player(last_name="George", attitude="snarky")

结果:

1
2
3
4
5
6
Traceback (most recent call last):
  File"keyword_checking.py", line 13, in <module>
    Player(last_name="George", attitude="snarky")
  File"keyword_checking.py", line 11, in __init__
    raise ValueError("Unknown keyword argument: {!r}".format(keyword))
ValueError: Unknown keyword argument: 'attitude'


可以使用关键字参数:

1
2
3
4
5
6
7
8
9
class Player:

    def __init__(self, last_name=None, first_name=None, score=None):
        self.last_name = last_name
        self.first_name = first_name
        self.score = score

obj = Player('Max', 'Jhon')
print obj.first_name, obj.last_name
1
Jhon Max

带参数**Kwargs

1
2
3
4
5
6
7
8
9
10
11
12
class Player:
    def __init__(self, **args):

        self.last_name = args.get('last_name')

        self.first_name = args.get('first_name')

        self.score = args.get('score', 0) # 0 is the default score.

obj = Player(first_name='Max', last_name='Jhon')

print obj.first_name, obj.last_name, obj.score
1
Max Jhon 0


这取决于你想要的最终结果。如果您想创建一个类,在字典中定义属性,那么可以使用setattr。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Player:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)            


In [1]: player = Player(first_name='john', last_name='wayne', score=100)

In [2]: player.first_name
Out[2]: 'john'

In [3]: player.last_name
Out[3]: 'wayne'

In [4]: player.score
Out[4]: 100

In [5]: player.address
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-0f7ee474d904> in <module>()
----> 1 player.address

AttributeError: 'Player' object has no attribute 'address'

我能试试这个方法吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/python

class Player(object):
    def __init__(self, **kwargs):
        for key, val in kwargs.items():
            self.__dict__[key] = val

obj = Player(first_name='First', last_name='Last')
print obj.first_name
print obj.last_name

newobj = Player(first_name='First')
print newobj.first_name

输出:

1
2
3
First
Last
First