English 中文(简体)
如何在皮顿呼叫工作?
原标题:How Does Calling Work In Python? [duplicate]
  • 时间:2012-05-22 01:11:37
  •  标签:
  • python

对于我正在研究的一个项目,我正在执行一个链接清单数据结构,它基于一对概念,我将其定义为:

class Pair:
    def __init__(self, name, prefs, score):
        self.name = name
        self.score = score
        self.preferences = prefs
        self.next_pair = 0
        self.prev_pair = 0

此处 self.next_pair self.prev_pair 分别指向上一个和下一个链接。

要设置链接列表, 我有一个安装功能, 看起来像这个 。

def install(i, pair):
    flag = 0
    try:
        old_pair = pair_array[i]
        while old_pair.next_pair != 0:
            if old_pair == pair:
                #if pair in remainders: remainders.remove(pair)
                return 0
            if old_pair.score < pair.score:
                flag = 1
                if old_pair.prev_pair == 0: # we are at the beginning
                    old_pair.prev_pair = pair
                    pair.next_pair = old_pair
                    pair_array[i] = pair
                    break
                else: # we are not at the beginning
                    pair.prev_pair = old_pair.prev_pair
                    pair.next_pair = old_pair
                    old_pair.prev_pair = pair
                    pair.prev_pair.next_pair = pair
                    break
            else:
                old_pair = old_pair.next_pair
        if flag==0:
            if old_pair == pair:
                #if pair in remainders: remainders.remove(pair)
                return 0
            if old_pair.score < pair.score:
                if old_pair.prev_pair==0:
                    old_pair.prev_pair = pair
                    pair.next_pair = old_pair
                    pair_array[i] = pair
                else:
                    pair.prev_pair = old_pair.prev_pair
                    pair.next_pair = old_pair
                    old_pair.prev_pair = pair
                    pair.prev_pair.next_pair = pair
            else:
                old_pair.next_pair = pair
                pair.prev_pair = old_pair
        except KeyError:
            pair_array[i] = pair
            pair.prev_pair = 0
            pair.next_pair = 0

在程序过程中,我正在建立一套这些链接列表的字典,并且将一些链接从一些链接中取出,并在另一些链接中添加。在被修剪和重新安装之间,链接被存储在一个中间阵列中。

在调试这个程序的过程中, 我意识到我对 Python 将争论传递到函数的方式的理解有缺陷。

def test_install():
    p = Pair(20000, [3, 1, 2, 50], 45)
    print p.next_pair
    print p.prev_pair
    parse_and_get(g)
    first_run()
    rat = len(juggler_array)/len(circuit_array)
    pref_size = get_pref_size()
    print pref_size
    print install(3, p)
    print p.next_pair.name
    print p.prev_pair             

当我做这个测试时,我得到以下结果。

0
0
10
None
10108
0

我不明白的是,为什么第二个呼叫 p.next_pair 产生不同于第一个呼叫( 0 )的结果( 10108 )。 s>安装 没有返回一个能够覆盖所通过对象的 pair 对象(它返回 none ),它也不像我通过 安装 一个指针。

我对呼呼逐个价值的理解是 口译员会复制通过到一个函数的值, 留下调用者变量不变。 例如, 如果我说

def foo(x):
     x = x+1
     return x

baz = 2
y = foo(baz)
print y
print baz

然后应该分别打印 3 2 。 事实上,当我在 Python 解释器中测试时, 情况就是这样 。

我真的很感激 如果有人能指示我 正确的方向在这里。

最佳回答

在 Python 中, 所有的东西都是对象。 简单的指派 < em> 存储指定名称中指定对象的引用 < / em> 。 因此, 将 Python 变量视为指定对象的名称, 而不是存储在指定地点的物体, 比较简单 。

例如:

baz = 2

...在 baz 中存储一个指针或指针,或引用存放在别处的整数对象 2 。 (由于该类型 int 是不可更改的, Python实际上拥有一个小整数库, 并随处再使用同样的 2 对象, 但这是一个执行细节, 我们不需要太多关注 。 )

当您调用 foo(baz) < foo>, s s local evol >>>>>x 也指向整数对象 2 > 。 也就是说, - 当地名称 > > 和全球名称 是同一对象的名称, 2 。 然后, x=x+1 被执行。这些更改 指向不同的对象: 3

重要的是要理解: >x 不是一个持有 2 的框,而 2>2 则被加到 3 。No, 最初指向 2 ,然后该指针被修改为 3 。自然,由于我们没有更改对象 baz 指向,它仍然指向 2

另一种解释方式是,在 Python 中,所有参数的通过都是按价值进行的,但所有数值都指向对象。

反直觉的结果是,如果一个对象可变,可以通过任何引用加以修改,所有引用都将“看到”修改。例如,考虑这一点:

baz = [1, 2, 3]

def foo(x):
   x[0] = x[0] + 1

foo(baz)
print baz
>>> [2, 2, 3]

这个 seems 与我们的第一个示例大不相同。 但实际上,这个参数被同样的方式传递。 foo () baz 的名称下接收一个指向 baz 的指向 baz ,然后对它进行操作,更改它(在此情况下,列表的第一个元素指向不同的 int 对象)。区别在于:名称 x < /code > 从未指向一个新对象;因此, x[0] 被修改为指向另一个不同的对象。 x 本身仍然指向与 baz 相同的对象。 (事实上,在“code > x[0] 的指定下,列表的任务变成一种方法调: x > x.__setution_( < < decodebaz > > > > > > > >) < a? 因此 < decodebaz > "se> " sees "se> "se> "se> "se "se" 如何 "se "

您看不到这种使用整数和字符串的行为, 因为您无法更改整数或字符串; 它们是不可变的类型, 当您修改它们时( 例如 < code> x = x + 1 < / code > ), 您实际上并没有修改它们, 而是将变量名称绑在完全不同的对象上。 如果您将 < code> baz 换成一个 tuple, 比如 < code> baz = 1, 2, 3, , 您会发现 < code> foo () < / code> 给您一个错误, 因为您无法指定 tuple 的元素; tuples 是另一个不可变的类型 。 “ 更改” a tuple 需要创建新对象, 然后指定该变量指向新对象 。

您定义的分类对象具有可变性, 因此您的 < code> pair 实例可以通过它被传递到的任何函数来修改 -- 也就是说, 属性可以添加、 删除或重新指定到其他对象。 这些物件不会重新组合指向您对象的任何名称, 因此当前指向它的所有名称都将“ 查看” 更改 。

问题回答

Python 在将变量传送到函数时不复制任何变量。 它既不是按值调用,也不是按值调用, 也不是按值调用, 但是在这两个函数中, 它更类似于按值调用。 您可以把它看作是“ 按值调用, 但值是一个参照值 ” 。

如果您将一个 < 坚固的 > 可变性 < / 强性 > 对象传递给一个函数,那么在函数中修改该对象将会影响到它所显示的每个对象。 (如果您将一个 < 坚固的 > 不可变性 < /强性 > 对象传递给一个函数,比如字符串或整数,那么根据定义,您根本无法修改该对象。 )

这并不是技术上的过路引用, 原因是您可以“ em>rebind

在您的第一个示例中,有 Pair 对象,您正在修改对象,因此您可以看到函数外的效果。

在您的第二个示例中,您没有修改任何对象, 您只是将名称与其他对象( 在此情况下的其他整数) 重新绑定。 baz 是指向一个值为 2. 的整数对象( 在 Python 中, 所有事物都是一个对象, 甚至整数) 的名称。 但是, 当您通过 baz 到 < code> foo( x) 到 < code > 到 < code > 到 < code> < foo < / code >, 的名称是本地在堆中创建的 < code> foo < / code > 函数中创建的, 而 < baz < /code > 的名称是设置在本地创建的, 在 < code> x= x+1 < / code > 线上, < code > 将设置到传递到该函数的整数为 3 。

如果您重写第一个示例, 以在您函数中根据从对等对象传递到它的信息( 无论这是您随后修改的复制件, 或者如果您制造一个构建器来修改构建数据) 创建一个新的对等对象, 您的函数不会产生改变通过对象的副作用 。

编辑 : 在 Python 中, 您应该使用 < code> 0 作为占位符, 意思是 " I don't have a value" -- -- 使用 noone 。 同样, 您也应该使用 0 来表示 < false , 就像您似乎在 flag 中所做的那样 。 但所有 > 0 < /code > 、 < code > 和 False 都用来评估布林表达中的 < code> False , 所以不管你使用什么方法, 您可以说, 如 if not lag 而不是 旗 = 0

我建议您忘记执行链接列表, 只需使用 Python < code> list 实例。 如果您需要的不是默认的 Python < code> list , 或许您可以从 Python 模块中使用某种东西, 如 < code> collects

跟踪链接列表中的链接的 Python 环将使用 Python 解释器速度运行, 也就是说, 慢速。 如果您只是使用嵌入的 < code> list 类, 您的列表操作将在 Python S C 代码中进行, 您将会获得速度 。

如果您需要列表, 但需要快速插入并快速删除, 您能否做一个 < code> dicit 工作? 如果有某种 ID 值( 字符串或整数或任何) 可用于对您的值强制排序, 您可以将它作为关键值使用, 并获得闪电快速插入和删除值。 如果您需要按顺序提取值, 您可以使用 < code> dict. keys () 方法函数来获取关键值列表并使用它 。

但如果您真的需要链接列表, 我建议您找到由他人写入和调试的代码, 并按您的需要进行调适。 Google 搜索“ python 链接列表配方 ” 或“ python 链接列表模块 ” 。

我要提出一个稍微复杂的因素:

>>> def foo(x):
...   x *= 2
...   return x
... 

使用数字、列表和字符串支持我所知道的方法定义略微不同的函数 。

首先,用弦调用它:

>>> baz = "hello"
>>> y = foo(baz)
>>> y
 hellohello 
>>> baz
 hello 

接下来,用名单称呼它:

>>> baz=[1,2,2]
>>> y = foo(baz)
>>> y
[1, 2, 2, 1, 2, 2]
>>> baz
[1, 2, 2, 1, 2, 2]
>>> 

使用字符串, 参数不会修改。 使用列表, 参数会修改 。

如果是我的话,我会避免在方法上修改论点。





相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...