I'm a Python newbie and I'm dealing with Object Programming. Studying my teacher code, I've found something strange at self.items = list(items)
. Look at the overall code:
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)
So, why should I cast the parameter items
, whereas the other parameters don't need this operation?
The other parameters ( plate_number
and capacity
) are probably immutable (a string and an int presumably). However items
is a list (if we are to trust the docstring) which is mutable.
Using it as it is in Truck
's __init__
would have resulted in changes made to truck_obj.items
affecting the original passed items
list as well (and vice-versa).
Calling list(items)
results in a newly created list being assigned to self.items
. This can also be achieved by using slicing syntax: self.items = items[:]
.
Compare:
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
to
class A:
def __init__(self, items):
self.items = list(items) # or items[:]
li = [1, 2]
obj = A(li)
li[0] = 9
print(obj.items)
# [1, 2]
Your instructor is saying "I can only work with items
in the class, if they're in a list
". What this roughly translates to is, "The items
attribute of class Truck
must be an ordered, indexed, and mutable collection".
For example, there is a chance that someone passes in a tuple
for items
, and if for example, you needed to add or remove items in the Truck
class, you can't add or remove items from a tuple
(but you can with a list
).
Casting to a list
is explicit, and should it not raise an error, is guaranteed to be a list regardless of what gets passed into items
. This is a part of what we call "pythonic".
EDIT: To piggy back off of a very good point by DeepSpace, casting to list
also creates a shallow copy of the list to manipulate, as opposed to the list itself.
In this example your teacher is assuming that plate_number
and capacity
are two immutable variables and items
should be represented as a list
.
So, when passing variables in __init__()
method your items
variables must be an iterable
and can be represented as a list
.
You can see this example with a 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))
Output:
plate_number: 12
capacity: 13
items: [1, 2, 3, 4]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.