2016-07-20 4 views
0

Мое понимание изменчивой функции python для классов/объектов заключается в том, что если вы выполняете присваивание, то любое изменение в оригинале также изменяет назначенную переменную/объект. Я смутился об этом piece of code below.Когда изменчивость объектов класса python влияет на присвоения?

# Recursive solution to Flatten Binary Tree to Linked List by LeetCode 

# Definition for a binary tree node 
# class TreeNode: 
#  def __init__(self, x): 
#   self.val = x 
#   self.left = None 
#   self.right = None 

class Solution: 
    # @param root, a tree node 
    # @return root, a tree node 
    def flattenHelper(self, root): 
     if root == None: 
      return None 
     else: 
      left = root.left 
      right = root.right 
      root.left = None # Truncate the left subtree 
      current = root 

      # Flatten the left subtree 
      current.right = self.flattenHelper(left) 
      while current.right != None: current = current.right 

      # Flatten the right subtree 
      current.right = self.flattenHelper(right) 
      return root 

    # @param root, a tree node 
    # @return nothing, do it in place 
    def flatten(self, root): 
     self.flattenHelper(root) 
     return 

Вопрос: Каким образом переменная left автоматически не приготовьтесь к None раз root.left = None выполняется?

+1

root.left = None устанавливает имя root.left для привязки к None. Это не изменяет то, что осталось. Таким образом, узел все еще существует, поскольку что-то ссылается на него. это просто, что root.left больше не ссылается на него –

+0

@joelgoldstick Спасибо, но я все еще смущен: если я делаю следующее: test = root, root.left = TreeNode (5), test.left .val теперь будет 5 Почему одно и то же не происходит выше? – user6175310

+0

@joelgoldstick Я думал, что здесь происходит что-то похожее на изменчивость списков: если у меня есть a = [1,2,3], тогда определите b = a, теперь, если я изменю a [0] = 0, b [0] будет автоматически меняются. Я попробовал это с объектами, как в примере выше, и подобное произошло. Я не понимаю, что отличается от реализации этого кода, и он не получает значение None автоматически. – user6175310

ответ

2

Назначение в Python всегда работает одинаково. Он меняет предмет в левой части знака =, чтобы узнать значение выражения в правой части. Существует абсолютно ничего, кроме «разные в реализации», как вы спрашиваете в комментарии.

Иногда элемент с левой стороны является слотом в контейнере (список, словарь, объект). Эти объекты изменяются (могут быть изменены), поэтому вы можете изменить их слоты. Когда вы делаете, например:

a = b = [0] 

Теперь a и b два разных названия одного и того же объекта. Если вы делаете a[0] = 1, то b[0] также становится 1, потому что a и b - это один и тот же объект, и присваивание не изменит его, поскольку вы назначаете слот 0 в объекте, на который ссылается a; вы не меняете то, что относится к a. Но если вы вместо этого делаете a = [1], то b[0] остается 0, потому что a теперь указывает на другой список от b.

Это то, что происходит в вашем примере. Имена left и root.left первоначально относятся к одному и тому же объекту. Когда вы меняете root.left, чтобы указать на другой объект, он не меняет left, чтобы указать на тот же объект. Чтобы это произошло, left должен был быть контейнером, и он должен был быть тем же контейнером, что и root, неroot.left, и что изменилось бы left.left, а не left. Потому что вы не можете изменить значение имени любым способом, кроме как назначить ему.

+0

Спасибо! Таким образом, в основном, если вместо назначения root.left None, некоторые изменения были внесены в объект (например, 'root.left.left = None', тогда это изменилось бы налево --->' left.left' также стало бы «Нет» ') Это правильно? – user6175310

+0

Что-то в этом роде. Эмпирическое правило состоит в том, что вы только увидите изменение одного объекта, отраженного в другом объекте, когда назначение относится к слоту внутри объекта (например, к элементу списка или словаря или атрибуту объекта), и только тогда, если другая ссылка относится к тому же содержащему объект (или родительскому объекту, который должен быть полным). – kindall

+0

Большое вам спасибо !!! Ваши примеры и объяснения настолько ясны и полезны! – user6175310