Python 3.x 在python中,将容器(列表/字典)传递给函数会有什么不同?

Python 3.x 在python中,将容器(列表/字典)传递给函数会有什么不同?,python-3.x,Python 3.x,我有一个数据结构/容器python列表/字典,我想根据一些计算更新它。我有几种想法: 一, 二, 三, 有人能解释一下这三个版本之间的区别吗。?从逻辑上讲,这三种方法都有效,甚至结果都是一样的!但我很想知道这些方法之间有什么区别,哪种更好 全球化是邪恶的。对于这个特定的示例,它可能会起作用。但如果您以后决定添加第二个列表,则必须重写代码或复制函数。为函数编写单元测试会更加复杂 总的来说,我认为这种方法没有错 这可能是口味的问题。返回对象在这里没有真正的用途,因为调用者已经拥有了对象。返回它可能会

我有一个数据结构/容器python列表/字典,我想根据一些计算更新它。我有几种想法:

一,

二,

三,

有人能解释一下这三个版本之间的区别吗。?从逻辑上讲,这三种方法都有效,甚至结果都是一样的!但我很想知道这些方法之间有什么区别,哪种更好

  • 全球化是邪恶的。对于这个特定的示例,它可能会起作用。但如果您以后决定添加第二个列表,则必须重写代码或复制函数。为函数编写单元测试会更加复杂

  • 总的来说,我认为这种方法没有错

  • 这可能是口味的问题。返回对象在这里没有真正的用途,因为调用者已经拥有了对象。返回它可能会给人一种印象,即返回的对象是另一个对象。所以就我个人而言,我不推荐这种方法。我认为这种模式更常用于其他一些高级面向对象编程语言,如Java(或者可能是C++),但我不认为它很像Python

  • 注:
    pass
    语句没有任何效果。你为什么要加这些


    更新:对有关参数如何传递(通过值或引用)以及如何影响代码的相关问题进行了一些扩展:

    在Python中,所有类型都是类,并通过引用传递。当您为局部变量(例如函数参数)赋值时,会进行新的引用,但调用方仍引用原始对象。但是,当您修改对象的内容时,调用者也会“看到”更改。简单地说,区别在于语句是否包含赋值运算符(
    =

    对于整数,您将始终使用赋值创建新的整数对象(例如
    x=3
    ,甚至
    x+=3
    )。字符串也是不可变的,因此不能在函数中修改字符串,只能创建新字符串(例如
    word=word.lower()

    如果使用列表的某个类方法(如
    list.append()
    )修改列表,则会更新原始对象。但是,如果创建并分配新列表,则不会更改原始列表。因此,要清除函数中的列表,可以使用
    container.clear()
    ,但不能使用
    container=[]
    。我希望下面的例子能够澄清这一点:

    def将数字添加到容器(容器):
    对于范围(5)中的i:
    container.append(一)
    def clear1(容器):
    容器=[]
    #这将创建一个新列表并将其分配给局部变量。
    #原始列表未被修改!
    def clear2(容器):
    容器。清除()
    #这将清除作为参数传递的列表。
    def main():
    新列表=[]
    打印(新列表)#[]
    将\u编号\u添加到\u容器(新\u列表)
    打印(新列表)#[0,1,2,3,4]
    clear1(新列表)
    打印(新列表)#仍然是[0,1,2,3,4]!
    clear2(新列表)
    打印(新列表)#[]
    如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
    main()
    
    另请注意:如果有许多函数/方法处理相同的数据,那么最好为其创建一个类。这有两个好处:您不必将列表传递给每个函数,但也不必创建全局变量。因此,您可以使用相同的代码轻松处理多个列表。请参见下面的示例代码

    方法4:

    class MyContainer:
    定义初始化(自):
    self.container=[]
    #在这里,使用空列表初始化容器。
    def添加_编号(自身、启动、停止):
    对于范围内的i(开始、停止):
    self.container.append(i)
    def清除(自):
    #以下两行都正确(只需要一行):
    self.container=[]
    self.container.clear()
    def打印(自):
    打印(自容器)
    def main():
    #您甚至可以创建多个独立的容器,并使用
    #每个对象具有相同的功能:
    container1=MyContainer()
    container2=MyContainer()
    container1.print()#[]
    container2.print()#[]
    容器1.添加_编号(0,5)
    集装箱2.添加_编号(5,8)
    container1.print()#[0,1,2,3,4]
    container2.print()#[5,6,7]
    容器1.清除()
    container1.print()#[]
    如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
    main()
    
  • 全球化是邪恶的。对于这个特定的示例,它可能会起作用。但如果您以后决定添加第二个列表,则必须重写代码或复制函数。为函数编写单元测试会更加复杂

  • 总的来说,我认为这种方法没有错

  • 这可能是口味的问题。返回对象在这里没有真正的用途,因为调用者已经拥有了对象。返回它可能会给人一种印象,即返回的对象是另一个对象。所以就我个人而言,我不推荐这种方法。我认为这种模式更常用于其他一些高级面向对象编程语言,如Java(或者可能是C++),但我不认为它很像Python

  • 注:
    pass
    语句没有任何效果。你为什么要加这些


    更新:对有关参数如何传递(通过值或引用)以及如何影响代码的相关问题进行了一些扩展:

    在Python中,所有类型都是类,并通过引用传递。当您为局部变量(例如函数参数)赋值时,会进行新的引用,但调用方仍引用原始对象。但是,当您修改对象的内容时,调用者也会“看到”更改。简单地说,区别在于国家是否
    new_list=list() # initialised globally!
    
    def func():
      for i in range(5):
        new_list.append(i) # updtaing here!
      print('in function:', new_list)
      pass
    
    def main():
      print('before:', new_list)
      func()
      print('after:',new_list)
    
    if __name__ == '__main__':
      main()
    
    def func(container):
      for i in range(5):
        container.append(i)
      print('in function:', container)
      pass
    
    def main():
      new_list=list()
      print('before:', new_list)
      func(new_list)
      print('after:',new_list)
    
    if __name__ == '__main__':
      main()
    
    def func(container):
      for i in range(5):
        container.append(i)
      print('in function:', container)
      return container
    
    def main():
      new_list=list()
      print('before:', new_list)
      new_list = func(new_list)
      print('after:',new_list)
    
    if __name__ == '__main__':
      main()