简体   繁体   中英

Casting in defining attributes of a Class?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM