Python 框架和对象之间的区别是什么,何时应该修改一个而不是另一个?

Python 框架和对象之间的区别是什么,何时应该修改一个而不是另一个?,python,python-3.x,object,dataframe,Python,Python 3.x,Object,Dataframe,我开始阅读python的+=语法,偶然发现了以下帖子/答案: 所以我注意到,画面和物体之间似乎有区别 在全局框架中,它们指向同一个对象,即使它们是不同的变量;如果这条线 l2 += [item] 而是 l2 = l2 + [item] 然后,当该行运行时,“l2”成为一个单独的对象。我最大的问题是什么时候希望变量指向一个单独的对象?还有,为什么以及什么时候要让它们指向同一个对象 任何解释或用例都将不胜感激!如果您能提及任何与数据科学相关的内容,请格外感谢:)frame和object并不是

我开始阅读python的+=语法,偶然发现了以下帖子/答案:

所以我注意到,画面和物体之间似乎有区别

在全局框架中,它们指向同一个对象,即使它们是不同的变量;如果这条线

l2 += [item]
而是

l2 = l2 + [item]
然后,当该行运行时,“l2”成为一个单独的对象。我最大的问题是什么时候希望变量指向一个单独的对象?还有,为什么以及什么时候要让它们指向同一个对象


任何解释或用例都将不胜感激!如果您能提及任何与数据科学相关的内容,请格外感谢:)

frame
object
并不是您所认为的意思

在编程中,有一种称为堆栈的东西。在Python中,当您调用一个函数时,您会创建一个称为堆栈帧的东西。这个框架(正如您在示例中看到的)基本上只是一个包含所有函数局部变量的表

请注意,定义函数并不会创建新的堆栈框架,而是调用函数。例如这样的事情:

def say_hello():
    name = input('What is your name?')
    print('Hello, {}'.format(name))
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1019bb320>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/private/tmp/fun.py', '__cached__': None, 'say_hello': <function say_hello at 0x101962d90>}
{'name': 'Arthur, King of the Brits'}
您的全局框架只包含一个引用:
say_hello
。通过检查本地名称空间中的内容,您可以看到这一点(在Python中,名称空间、范围和堆栈框架之间几乎是1:1的关系):

您将看到如下内容:

def say_hello():
    name = input('What is your name?')
    print('Hello, {}'.format(name))
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1019bb320>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/private/tmp/fun.py', '__cached__': None, 'say_hello': <function say_hello at 0x101962d90>}
{'name': 'Arthur, King of the Brits'}
这里没有邓德的名字。您还将注意到,这并不显示内存地址。如果你想知道这个值的位置,这里有一个函数

def say_hello():
    name = input('What is your name?')
    print('hello {}'.format(name))
    print(locals())
    print(id(name))
    return name

print(id(say_hello()))
这就是示例在讨论帧时的含义

但是物体呢?在Python中,一切都是对象。试试看:

>>> isinstance(3, object)
True
>>> isinstance(None, object)
True
>>> isinstance('hello', object)
True
>>> isinstance(13.2, object)
True
>>> isinstance(3j, object)
True
>>> def fun():
...  print('hello')
... 
>>> isinstance(fun, object)
True
>>> class Cool: pass
... 
>>> isinstance(Cool, object)
True
>>> isinstance(Cool(), object)
True
>>> isinstance(object, object)
True
>>> isinstance(isinstance, object)
True
>>> isinstance(True, object)
True
它们都是物体。但它们可能是不同的对象。你怎么知道?使用
id

>>> id(3)
4297619904
>>> id(None)
4297303920
>>> id('hello')
4325843048
>>> id('hello')
4325843048
>>> id(13.2)
4322300216
>>> id(3j)
4325518960
>>> id(13.2)
4322300216
>>> id(fun)
4322635152
>>> id(isinstance)
4298988640
>>> id(True)
4297228640
>>> id(False)
4297228608
>>> id(None)
4297303920
>>> id(Cool)
4302561896
请注意,您还可以使用
is
比较两个对象是否为同一对象

>>> True is False
False
>>> True is True
True
>>> 'hello world' is 'hello world'
True
>>> 'hello world' is ('hello ' + 'world')
False
>>> 512 is (500+12)
False
>>> 23 is (20+3)
True
呃。。。?等等,那里发生了什么事?事实证明,
python
(即CPython)。因此,对象
512
与添加到对象
12
的对象
500
的结果不同

需要注意的一件重要事情是赋值操作符
=
始终为同一对象指定一个新名称。例如:

>>> x = 592
>>> y = 592
>>> x is y
False
>>> x == y
True
>>> x = y
>>> x is y
True
>>> x == y
True
不管你给一个对象起了多少个名字,或者即使你通过了,你仍然拥有相同的对象

但是,当您开始收集时,了解更改对象的操作和生成新对象的操作之间的区别是很重要的。一般来说,Python中有一个对象,对它们的操作将生成一个新对象

至于你的问题,什么时候你想改变对象,什么时候你想保持它们不变,实际上是以错误的方式看待它。当您想要更改内容时,您希望使用可变类型;如果您不想更改内容,您希望使用不可变类型

例如,假设您有一个组,并且希望向该组添加成员。您可以使用可变类型(如列表)来跟踪组,使用不可变类型(如字符串)来表示成员。像这样:

>>> group = []
>>> id(group)
4325836488
>>> group.append('Sir Lancelot')
>>> group.append('Sir Gallahad')
>>> group.append('Sir Robin')
>>> group.append("Robin's Minstrels")
>>> group.append('King Arthur')
>>> group
['Sir Lancelot', 'Sir Gallahad', 'Sir Robin', "Robin's Minstrels", 'King Arthur']
当团队成员被吃掉时会发生什么

>>> del group[-2]  # And there was much rejoicing
>>> id(group)
4325836488
>>> group
['Sir Lancelot', 'Sir Gallahad', 'Sir Robin', 'King Arthur']

您会注意到,您仍然拥有相同的组,只是成员发生了更改。

如果我们讨论的是调用堆栈,则a是包含最直接作用域的所有本地创建对象的对象。在屏幕截图中,整个蓝色框为一帧,包含与名称
l1
l2
项相关的对象。你不能直接控制画面;你只能控制对象和它们的名称。非常有启发性的回答。后续问题:所有对象都存在于堆上吗?