框架和对象之间有什么区别?何时应在一个框架上修改另一个框架? [英] What is the difference between a frame and object, and when should I modify one over the other?

查看:82
本文介绍了框架和对象之间有什么区别?何时应在一个框架上修改另一个框架?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在全局框架中,即使它们是不同的变量,它们也指向相同的对象;如果行

  l2 + = [项目] 

代替

  l2 = l2 + [项目] 

然后,当该行运行时, l2成为一个单独的对象。我最大的问题是,何时要让变量指向单独的对象?另外,为什么以及何时要将它们指向同一对象?



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

解决方案

frame 对象并不意味着您认为它们是什么意思。



在编程中,您有一个堆栈。在Python中,调用函数时会创建一个称为堆栈框架的东西。该框架(如您在示例中所示)基本上只是函数本地所有变量的表。



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

  def say_hello():
name = input(您叫什么名字? )
print('Hello,{}'。format(name))

您的全局变量框架仅保留一个参考: say_hello 。您可以通过检查本地名称空间中的内容来看到(在Python中,名称空间,范围和堆栈框架之间几乎具有1:1的关系):

  print(locals())

您会看到一些看起来像的东西像这样:

  {'__ name__':'__main__','__doc__':无,'__package__':无,'__loader__ ':< _frozen_importlib_external.SourceFileLoader对象位于0x1019bb320> ;,'__spec__':无,'__annotations__':{},'__builtins__':<模块'builtins'(内置)> ;,'__file__':'/ private /tmp/fun.py'、'__cached__':无,'say_hello':<函数在0x101962d90上的say_hello>} 

请注意dunder(双下划线双下划线的缩写)名称-这些名称是自动提供的,出于我们讨论的目的,您可以忽略它们。这就给我们留下了

  {'say_hello':< function say_hello at 0x101962d90>} 

0x 位是函数本身所在的内存地址。因此,在这里,我们的全局堆栈/框架仅包含该值。如果调用函数,然后再次检查 locals(),则会看到 name 不存在。那是因为当您调用函数时,会创建一个新的堆栈框架,并在其中分配变量。您可以通过在函数末尾添加 print(locals())来证明这一点。然后您将看到类似这样的内容:

  {'name':'英国国王阿瑟,'} 

这里没有小标题。您还要注意,它没有显示内存地址。如果您想知道此值的位置,则有一个函数。

  def say_hello():
名称= input('您叫什么名字?')
print('hello {}'。format(name))
print(locals())
print(id(name))
返回名称

print(id(say_hello()))

这就是示例在谈论框架时的意思。



但是对象呢?嗯,在Python中,一切是一个对象。只需尝试一下:

 >> isinstance(3,object)

>> isinstance(无,对象)

>> isinstance(‘hello’,对象)

>>> isinstance(13.2,object)

>> isinstance(3j,object)

>> def fun():
...打印( hello)
...
>>> isinstance(乐趣,对象)

>> class Cool:通过
...
>> isinstance(酷,对象)

>>> isinstance(Cool(),object)

>>> isinstance(对象,对象)

>>> isinstance(isinstance,object)

>> isinstance(真对象)

它们都是全部对象。但是它们可能是不同的对象。你怎么知道?使用 id

 >> id(3)
4297619904
>> id(无)
4297303920
>> id(‘hello’)
4325843048
>>> id(‘hello’)
4325843048
>>> id(13.2)
4322300216
>> id(3j)
4325518960
>> id(13.2)
4322300216
>> id(fun)
4322635152
>> id(instance)
4298988640
>> id(True)
4297228640
>> id(False)
4297228608
>> id(无)
4297303920
>> id(Cool)
4302561896

请注意,您还可以比较两个对象是否为使用 same 对象是

 >>>真是假

>>> True是True
True
>>> hello world是 hello world
True
>>> hello world是(‘hello’+‘world’)
False
>>> 512是(500 + 12)

>> 23是(20 + 3)

Ehhhhh ...?等一下,那里发生了什么?好吧,事实证明, python (即CPython)缓存小整数。因此对象 512 与对象 500 添加到对象<$ c的结果不同$ c> 12 。



要注意的重要一点是赋值运算符 = 总是相同对象分配一个新名称。例如:

 >> x = 592 
>> y = 592
>> x是y
False
>> x == y

>> x = y
>> x是y

>> x == y

输入多少个其他名称都没有关系对象,或者即使您将对象绕到不同的框架 ,您仍然有相同的对象。



但是当您开始收集时,了解更改和对象和产生 new 对象的操作。一般来说,您在Python中有一个很少不变类型,对其进行操作会产生一个新对象。



关于您的问题,您什么时候想要更改对象,什么时候想要保持它们不变,实际上是在错误地看待它。您想在更改内容时使用可变类型,而在不想更改时使用不可变类型。



例如,说您有一个群组,并且您想要将成员添加到群组中。您可以使用可变类型(例如列表)来跟踪组,并使用不可变类型(例如字符串)来表示成员。像这样:

 >>组= [] 
>> id(group)
4325836488
>> group.append('Sir Lancelot')
>>> group.append('Sir Gallahad')
>>> group.append(’Sir Robin’)
>>> group.append( Robin’s Minstrels)
>>> group.append(亚瑟王)
>>>组
[兰斯洛特爵士,加拉哈德爵士,罗宾爵士,罗宾·明斯特尔斯,亚瑟王]

该小组成员被吃掉会发生什么?

 >>> ; del group [-2]#并且
>>> id(group)
4325836488
>>组
[兰斯洛特爵士,加拉哈德爵士,罗宾爵士,亚瑟王]

您会注意到您仍然具有相同的组,只是成员已更改。


I started reading about python's += syntax and stumbled onto the following post/answer: Interactive code about +=

So what I noticed was that there seems to be a difference between frames and objects.

In the global frame, they point to the same object even though they're different variables; if the line

l2 += [item]

was instead

l2 = l2 + [item]

then 'l2' becomes a separate object when that line runs. My biggest question is when would you want a variable to point to a separate object? Also, why and when would you want to keep them pointed at the same object?

Any explanation or use cases would be greatly appreciated! Extra thanks if you can mention anything relevant to data science :)

解决方案

frame and object don't mean what you think they mean.

In programming you have something called a stack. In Python, when you call a function you create something called a stack frame. This frame is (as you see in your example) basically just a table of all of the variables that are local to your function.

Note that defining a function doesn't create a new stack frame, it's the calling a function. For instance something like this:

def say_hello():
    name = input('What is your name?')
    print('Hello, {}'.format(name))

Your global frame is just going to hold one reference: say_hello. You can see that by checking out what's in the local namespace (in Python you pretty much have a 1:1 relationship between namespace, scope, and stack frames):

print(locals())

You'll see something that looks like this:

{'__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>}

Note the dunder (short for double underscore double underscore) names - those are automagically provided, and for the purposes of our discussion you can ignore them. That leaves us with:

{'say_hello': <function say_hello at 0x101962d90>}

That 0x bit is the memory address where the function itself lives. So here, our global stack/frame contains just that one value. If you call your function and then check locals() again, you'll see that name isn't there. That's because when you call the function you create a new stack frame and the variable is assigned there. You can prove this by adding print(locals()) at the end of your function. Then you'll see something like this:

{'name': 'Arthur, King of the Brits'}

No dunder names here. You'll also note that this doesn't show a memory address. If you want to know where this value lives, there's a function for that.

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

print(id(say_hello()))

That's what the example means when it's talking about a frame.

But what about objects? Well, in Python, everything is an object. Just try it:

>>> 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

They're all objects. But they may be different objects. And how can you tell? With 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

Note that you also can compare whether or not two objects are the same object by using 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

Ehhhhh...? Wait a minute, what happened there? Well, as it turns out, python(that is, CPython) caches small integers. So the object 512 is different from the object that is the result of the object 500 added to the object 12.

One important thing to note is that the assignment operator = always assigns a new name to the same object. For example:

>>> x = 592
>>> y = 592
>>> x is y
False
>>> x == y
True
>>> x = y
>>> x is y
True
>>> x == y
True

And it doesn't matter how many other names you give an object, or even if you pass the object around to different frames, you still have the same object.

But as you're starting to gather, it's important to understand the difference between operations that change an object and operations that produce a new object. Generally speaking you have a few immutable types in Python, and operations on them will produce a new object.

As for your question, when do you want to change objects and when do you want to keep them the same is actually looking at it the wrong way. You want to use a mutable type when you want to change things, and you want to use an immutable type if you don't want things to change.

For instance, say you've got a group, and you want to add members to the group. You might use a mutable type like a list to keep track of the group, and an immutable type like strings to represent the members. Like this:

>>> 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']

What happens when a member of the group is eaten?

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

You'll notice that you still have the same group, just the members have changed.

这篇关于框架和对象之间有什么区别?何时应在一个框架上修改另一个框架?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆