Python类设计:显式关键字参数vs.** kwargs vs. @ property [英] Python class design: explicit keyword arguments vs. **kwargs vs. @property

查看:60
本文介绍了Python类设计:显式关键字参数vs.** kwargs vs. @ property的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否存在创建其实例将具有许多(非默认值)变量的类的普遍接受的最佳实践?

Is there a generally accepted best practice for creating a class whose instances will have many (non-defaultable) variables?

例如,通过显式参数:

class Circle(object):
    def __init__(self,x,y,radius):
        self.x = x
        self.y = y
        self.radius = radius

使用** kwargs:

using **kwargs:

class Circle(object):
    def __init__(self, **kwargs):
        if 'x' in kwargs:
            self.x = kwargs['x']
        if 'y' in kwargs:
            self.y = kwargs['y']
        if 'radius' in kwargs:
            self.radius = kwargs['radius']

或使用属性:

class Circle(object):
    def __init__(self):
        pass

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        self._y = value

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = value

对于实现少量实例变量的类(如上面的示例),似乎自然的解决方案是使用显式参数,但是随着变量数量的增加,这种方法很快变得不规则.当实例变量的数量变长时,有没有一种首选的方法?

For classes which implement a small number of instance variables (like the example above), it seems like the natural solution is to use explicit arguments, but this approach quickly becomes unruly as the number of variables grows. Is there a preferred approach when the number of instance variables grows lengthy?

推荐答案

在不真正了解您情况的细节的情况下,经典的答案是:如果您的类初始化程序需要一堆参数,那么它可能是做得太多,应该将其分解为几个类.

Without really knowing the particulars of your situation, the classic answer is this: if your class initializer requires a whole bunch of arguments, then it is probably doing too much, and it should be factored into several classes.

采用这样定义的 Car 类:

class Car:
    def __init__(self, tire_size, tire_tread, tire_age, paint_color, 
                 paint_condition, engine_size, engine_horsepower):
        self.tire_size = tire_size
        self.tire_tread = tire_tread
        # ...
        self.engine_horsepower = engine_horsepower

显然,更好的方法是定义 Engine Tire Paint 类(或 namedtuple s)并将这些的实例传递到 Car():

Clearly a better approach would be to define Engine, Tire, and Paint classes (or namedtuples) and pass instances of these into Car():

class Car:
    def __init__(self, tire, paint, engine):
        self.tire = tire
        self.paint = paint
        self.engine = engine

如果需要 来创建类的实例,例如 Circle 类中的 radius ,则应为必填项 __ init __ 的参数(或分解为较小的类,然后传递给 __ init __ 或由其他构造函数设置).原因是:IDE,自动文档生成器,代码自动完成器,lints等可以读取方法的参数列表.如果只是 ** kwargs ,则那里没有任何信息.但是,如果它具有您期望的参数名称,那么这些工具就可以完成工作.

If something is required to make an instance of a class, for example, radius in your Circle class, it should be a required argument to __init__ (or factored into a smaller class which is passed into __init__, or set by an alternative constructor). The reason is this: IDEs, automatic documentation generators, code autocompleters, linters, and the like can read a method's argument list. If it's just **kwargs, there's no information there. But if it has the names of the arguments you expect, then these tools can do their work.

现在,属性非常酷,但是我会犹豫是否要使用它们,直到必要时为止(您会知道何时需要它们).保持您的属性不变,并允许人们直接访问它们.如果不应该设置或更改它们,请记录下来.

Now, properties are pretty cool, but I'd hesitate to use them until necessary (and you'll know when they are necessary). Leave your attributes as they are and allow people to access them directly. If they shouldn't be set or changed, document it.

最后,如果您确实必须有很多参数,但又不想在 __ init __ 中编写一堆分配,您可能会感兴趣亚历克斯·马丁里(Alex Martelli)的

Lastly, if you really must have a whole bunch of arguments, but don't want to write a bunch of assignments in your __init__, you might be interested in Alex Martelli's answer to a related question.

这篇关于Python类设计:显式关键字参数vs.** kwargs vs. @ property的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆