简体   繁体   English

强制定义类的属性?

[英]Casting in defining attributes of a Class?

I'm a Python newbie and I'm dealing with Object Programming. 我是Python新手,正在处理对象编程。 Studying my teacher code, I've found something strange at self.items = list(items) . 通过研究我的老师代码,我发现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? 那么,为什么我应该强制转换参数items ,而其他参数则不需要此操作呢?

The other parameters ( plate_number and capacity ) are probably immutable (a string and an int presumably). 其它参数( plate_numbercapacity )可能是不可变的(字符串和一个int大概)。 However items is a list (if we are to trust the docstring) which is mutable. 但是items是一个可变的列表(如果我们要信任文档字符串)。

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). 按原样在Truck__init__使用它会导致对truck_obj.items更改也影响原始传递的items列表(反之亦然)。

Calling list(items) results in a newly created list being assigned to self.items . 调用list(items)导致将一个新创建的列表分配给self.items This can also be achieved by using slicing syntax: self.items = items[:] . 这也可以通过使用切片语法来实现: 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 ". 您的老师说:“如果listitems ,我只能使用该items ”。 What this roughly translates to is, "The items attribute of class Truck must be an ordered, indexed, and mutable collection". 大致的翻译是,“ Truck类的items属性必须是有序,可索引且可变的集合”。

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 ). 例如,某人可能会传入一个tuple来存储items ,例如,如果您需要在Truck类中添加或删除项目,则不能在tuple添加或删除项目(但是可以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 . 铸造一个list是明确的,而应该把它不会引发错误,是保证无论什么被传递到列表中items This is a part of what we call "pythonic". 这是我们所谓的“ 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. 编辑:为了通过DeepSpace收回一个很好的点,强制转换为list还会创建要操作的列表的浅表副本,而不是列表本身。

In this example your teacher is assuming that plate_number and capacity are two immutable variables and items should be represented as a list . 在这个例子中你的老师是假设plate_numbercapacity是两个不变的变量, items应该被表示为一个list

So, when passing variables in __init__() method your items variables must be an iterable and can be represented as a list . 因此,当在__init__()方法中传递变量时,您的items变量必须是iterable并且可以表示为list

You can see this example with a generator : 您可以使用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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 定义Python类实例属性 - Defining Python class instance attributes Python:使用相关属性定义类 - Python: Defining class with dependent attributes 定义具有许多属性的Python类 - 样式 - Defining a Python class with lots of attributes - style 在从dict继承的类定义中,为什么定义属性有区别? - In class definition inherited from dict why is there a difference in defining attributes? 元类,使用字典定义__init__以传递实例的属性(而不是类的属性) - metaclassing, defining __init__ to pass attributes for the instances (not for the class) using a dictionary Python-帮助根据参数定义具有可变数量属性的类 - Python - Help defining a class with a variable number of attributes depending on the argument Python:定义后未找到 class 属性 - Python: class attributes haven't been found after defining 定义在初始化时按顺序计算属性的类的最佳实践 - Best practice for defining a class that computes attributes in order when initialized python 2.7定义一个类,如果不带参数调用该类将显示其属性 - python 2.7 defining a class that will show their attributes if called with no arguments Python 2.7,定义具有属性的基类,具有init构造函数的id - Python 2.7, defining a base class with attributes, id with init constructor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM