Python NoneType object not working as expected

I am trying to pass a value over an objectNone

in the hopes of reassigning it to the actual value. Can someone explain why this is not working? I thought since None

is NoneType

that it will be passed by reference and when I use the passed variable I would change the original object None

. This is not true? I have provided the snippet below to demonstrate my case:

class MyClass:
    def __init__(self):
        self.value = None

    def assign(self, object):
        object = OtherClass()

example = MyClass()
example.assign(example.value)

      

The result example.value

is still None

. Why is this? I have read several SO posts , but none of them is clear in explaining this.

EDIT: Not a duplicate because I wanted to know why it behaves like a pass by value when I thought it should be traversed by reference. In conclusion, I came to the conclusion that objects are immutable and therefore always passed by value. I will need to use a type object or something mutable. NoneType

list

EDIT again: my example code is just a general case. I was trying to implement BST and my initial root node was None

, and when I assigned the root node to be an object Node

, it will still be NoneType

, which made me confused and was the cause of this question.

Last edit: The answer below gives a very good summary of tl; dr about passing through the object. I couldn't figure it out just browsing / reading the forums.

+3


source to share


2 answers


This is exactly the case when calling by object (Python rules) is different from calling by reference (C ++ reference semantics).

The difference is that assigning an unqualified name double-checks the name, it has no effect on what was previously associated with the name (other than possibly being destroyed if no other references remain). The name has nothing to do with any other names that may refer to the same object, so these other names are not changed.

So, in this case, it is object

initially set to the same object example.value

it points to. But on the next line, you retype object

(unqualified name assignment) and points to a whole different object.

In contrast:

def assign_value(self, object):
    object.value = OtherClass()

      

and called it with:

example.assign(example)

      

then example

both object

will refer to the same object, and your qualified name assignment will replace value

that one object.

All that said, your use case here does not need such changes. The call example.assign(example.value)

doesn't make any sense as it self

is passed implicitly and automatically gives you access to value

(qualified access at least). It sounds like what you really wanted is just lazy initialization when requested without any arguments:



def assign(self):
    self.value = OtherClass()

      

called:

example.assign()

      

In response to your changes: Python explicitly describes this calling behavior :

The actual parameters (arguments) for calling the function are entered in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where value is always an object reference, not the value of an object). [1]

In note 1 of the explanation:

[1] In fact, calling by object reference would be a better description, because if a mutable object is passed, the caller will see any changes the callee makes to it (the items inserted into the list).

This is intended; C ++ reference semantics don't work unless you have other semantics available, because there is no obvious way to abandon it, which means that every variable along the huge chain of calls ends up with a reference to the same object, causing tons of -distance actions.

+2


source


The problem is that the function is calling pass values, not references. Specifically, a reference passed to a function remains unchanged until it bounces (this value is not set), after which a copy is made locally for that function. Any line of the form other = ...

will cause this to happen. If you want this behavior, you need to use a mutable object like a list. For example:

class MyClass:
    def __init__(self):
        self.value = [None]

    def assign(self, object):
        object[0] = OtherClass()

example = MyClass()
example.assign(example.value)

      



Hope this helps!

0


source







All Articles