初始化实例变量:惯用语

时间:2014-09-09 14:08:25

标签: python

在Python中,初始化Python实例变量的惯用方法是什么:

class Test:

    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d

或者

class Test2:

    def __init__(self, data):
        self.a = data[0]
        self.b = data[1]
        self.c = data[2]
        self.d = data[3]

更新:我有一个名为Link的类的大约20个实例变量:

self.street 
self.anode 
self.bnode 
self.length 
self.setbackA 
self.setbackB 
self.bearingA 
self.bearingB 
self.ltype 
self.lanesAB 
self.leftAB 
self.rightAB 
self.speedAB 
self.fspdAB 
self.capacityAB 
self.lanesBA 
self.leftBA 
self.rightBA 
self.speedBA 
self.fspdBA 
self.capacityBA 
self.use 

每个变量都与类Link相关。是否有推荐的重构方法?

2 个答案:

答案 0 :(得分:4)

前者,因为它更清楚地知道参数是什么以及对象需要什么。

如果您 需要将数据作为元组传递,那么您可以使用快捷方式。而不是做后者,或类似的东西:

test = Test(data[0], data[1], data[2], data[3])

您可以解压缩列表/元组并执行:

test = Test(*data)

如果你需要传递一堆数据(超过4-5),你应该研究使用可选/关键字参数,创建一个自定义对象来保存一些数据,或使用字典:

config = Config(a, b, c, d)
test = Test(e, f, config, foo=13, bar=True)

我可能会重构你的Link类看起来像这样:

class Node(object):
    def __init__(self, node, setback, bearing):
        self.node = node
        self.setback = setback 
        self.bearing = bearing 

class Connection(object):
    def __init__(self, lanes, left, right, speed, fspd, capacity):
        self.lanes = lanes 
        self.left = left 
        self.right = right 
        self.speed = speed 
        self.fspd = fspd 
        self.capacity = capacity 

class Link(object):
    def __init__(self, street, length, ltype, use, a, b, ab, ba):
        self.street = street 
        self.length = length 
        self.ltype = ltype 
        self.use = use 

        self.a = a 
        self.b = b 
        self.ab = ab 
        self.ba = ba 

我看到你有一些重复的数据,所以将它们拉到一个单独的对象中。虽然这并没有减少你拥有的字段数量,但总的来说,它确实使你需要传递的参数更小。

拥有大量字段并不是很糟糕,但通常有大量参数。如果您可以通过将数据捆绑在一起而不需要大量参数的方式编写方法,那么您拥有的字段数并不重要。

答案 1 :(得分:2)

将一个数组打包成一堆命名变量表明你应该首先使用命名变量开始 - 坚持使用第一个。

这里只有一个原因你可能想要第二个 - 你有一些东西是无意义地产生列表而不是对象。如果确实发生了这种情况:

data = get_data_in_list_form()
actual_data = Test(*data)

您可以将部分数据分组:

self.street
self.ltype
self.use
self.length

# .a and .b can be instances of NodeConnection
self.a.setback
self.a.bearing

self.b.setback
self.b.bearing
self.b.node

# .ab and .ba can be a separate class, "UniDirectionalLink
self.ab.lanes
self.ab.left
self.ab.right
self.ab.speed
self.ab.fspd
self.ab.capacity

self.ba.lanes
self.ba.left
self.ba.right
self.ba.speed
self.ba.fspd
self.ba.capacity

这里没有必要在构造函数中执行所有操作:

link = (
    Link(street=..., ltype=..., use=..., length=...)
        .starting_at(node_a, bearing=..., setback=...)
        .finishing_at(node_b, bearing=..., setback=...)
        .forward_route(lanes, left, right, speed, fspd, capacity)
        .reverse_route(lanes, left, right, speed, fspd, capacity)
)