我是一个Python新手,我正在处理对象编程。
研究我的老师代码,我在self.items = list(items)
找到了一些奇怪的东西。
看一下整体代码:
class Truck():
'''
This class models a truck
'''
def __init__(self, plate_number, capacity, items):
'''
Constructor of an object of class Truck
:param plate_number: a unique number Identifying the truck
:param capacity: maximum weight that the truck can carry
:param items: list of objects of class Item carried by the truck
'''
self.plate_number = plate_number
self.capacity = capacity
self.items = list(items)
那么,我为什么要转换参数items
,而其他参数不需要这个操作?
答案 0 :(得分:4)
其他参数(plate_number
和capacity
)可能是不可变的(大概是字符串和int)。但是items
是一个可变的列表(如果我们要信任docstring)。
在Truck
的{{1}}中使用它会导致对__init__
的更改也会影响原始传递的truck_obj.items
列表(反之亦然) )。
调用items
会将新创建的列表分配给list(items)
。这也可以通过使用切片语法来实现:self.items
。
比较
self.items = items[:]
到
class A:
def __init__(self, items):
self.items = items
li = [1, 2]
obj = A(li)
li[0] = 9
print(obj.items)
# [9, 2] oops! we modified obj.items without intending to
答案 1 :(得分:0)
您的导师说:“我只能在班级items
工作,如果他们在list
”。这大致转换为“类items
的{{1}}属性必须是有序的,索引的和可变的集合”。
例如,某人可能会Truck
传递tuple
,例如,您需要在items
课程中添加或删除项目,不添加或删除Truck
中的项目(但您可以使用tuple
)。
转换为list
是明确的,如果不引发错误,则无论传递到list
的内容是什么,都保证是一个列表。这是我们所谓的“pythonic”的一部分。
编辑:要深入了解DeepSpace的一个非常好的观点,强制转换为items
也会创建一个要操作的列表的浅表副本,而不是列表本身。
答案 2 :(得分:0)
在此示例中,您的教师假设plate_number
和capacity
是两个不可变变量,而items
应表示为list
。
因此,在__init__()
方法中传递变量时,items
变量必须为iterable
,并且可以表示为list
。
您可以使用generator
:
class Truck():
def __init__(self, plate_number, capacity, items):
self.plate_number = plate_number
self.capacity = capacity
self.items = list(items)
def __repr__(self):
return "plate_number: %r\ncapacity: %r\nitems: %r" % (self.plate_number, self.capacity, self.items)
# Test
if __name__ == '__main__':
number = 12
capacity = 13
# Generator wich can be represented as a list
items = (k for k in [1,2,3,4])
app = Truck(number, capacity, items)
print(app)
# OR
#print(repr(app))
输出:
plate_number: 12
capacity: 13
items: [1, 2, 3, 4]