简化数据结构的初始化过程
我们编写了许多类, 把它们当作数据结构用。但是我们厌倦了编写高度重复且样式相同的 init () 函数。
解决方案
通常我们可以将初始化数据结构的步骤归纳到一个单独的 init()函数中,并将其定义在一个公共的基类中。示例如下:
class Structure:
# Class variable that speicifies expected fields
_fields = []
def __init__(self, *args):
if len(args) != len(self._fields):
raise TypeError('Expected {} arguments'.format(len(self._fields)))
# Set the arguments
for name, value in zip(self._fields, args):
setattr(self, name, value)
# Example class definitions
import math
if __name__ == '__main__':
class Stock(Structure):
_fields = ['name', 'shares', 'price']
class Point(Structure):
_fields = ['x', 'y']
class Circle(Structure):
_fields = ['radius']
def area(self):
return math.pi * self.radius ** 2
s = Stock('ACME', 50, 91.1)
p = Point(2, 3)
c = Circle(4.5)
print('圆c的面积是:{:.2f}'.format(c.area()))
s2 = Stock('ACME', 50)
如果使用这些类, 就会发现它们非常易于构建。结果如下:
D:\Python39\python.exe D:/My_Project/example1.py
Traceback (most recent call last):
File "D:\My_Project\example1.py", line 33, in <module>
s2 = Stock('ACME', 50)
File "D:\My_Project\example1.py", line 7, in __init__
raise TypeError('Expected {} arguments'.format(len(self._fields)))
TypeError: Expected 3 arguments
圆c的面积是:63.62
Process finished with exit code 1
我们应该提供对关键字参数的支持,这里有几种设计上的选择。一种选择是对关键字参数做映射,这样它们就只对应与定义在_fields中的属性名。示例如下:
class Structure:
_fields = []
def __init__(self, *args, **kwargs):
if len(args) > len(self._fields):
raise TypeError('Expected {} arguments'.format(len(self._fields)))
# Set all of the positional arguments
for name, value in zip(self._fields, args):
setattr(self, name, value)
# Set the remaining keyword arguments
for name in self._fields[len(args):]:
setattr(self, name, kwargs.pop(name))
# Check for any remaining unknown arguments
if kwargs:
raise TypeError('Invalid argumen(s): {}'.foramt(','.join(kwargs)))
# Example use
if __name__ == '__main__':
class Stock(Structure):
_fields = ['name', 'shares', 'price']
s1 = Stock('ACME', 50, 91.1)
s2 = Stock('ACME', 50, price=91.1)
s3 = Stock('ACME', shares=50, price=91.1)
s4 = Stock('ACME', 40, 81.1, 88) # 多一个参数,会产生报错