Why do lists (arrays) behave differently than common variables in Python?

Asked

Viewed 112 times

1

Two examples that I think defines my question well, the first is the function:

a = [1, 2, 3, 4, 5]

def soma(l_item):
  l_item[0] += 10

soma(a)
print(a)

>>> [11, 2, 3, 4, 5]

It is changed by functions.

The second is the copy:

a = [1, 2, 3, 4, 5]
a.remove(1)

b = a

print(b)

>>> [2, 3, 4, 5]

In fact I know how to copy a list, and I’ve even heard a little bit about memory addressing, but unfortunately I can’t quite understand why.

  • Did the answer solve your question? Do you think you can accept it? See [tour] if you don’t know how you do it. This would help a lot to indicate that the solution was useful for you. You can also vote on any question or answer you find useful on the entire site (when you have 15 points).

1 answer

2

First, the title says something wrong.

lists (arrays) behave differently than common variables

List is a type of data and variable is a name that defines a memory position, so comparing the two things makes no sense. One of the reasons I see that people have difficulty programming correctly these days, and almost everyone who enters the area has had a lot of difficulty, is that they don’t really understand what things are. There’s no way to do it right without a deep understanding, there’s a way to make it work, which is different than being right. In programming the only easy thing is to do something wrong and still work and the person thinks he is right.

Fiat 147 todo detonado andando pelas ruas

The rest of the question seems to ignore the title. It seems to want to know the difference of a list and a type of scalar data, ie, not composed. Or better yet I wouldn’t know the difference right now data type by value or by reference. If you don’t understand what is a reference, has asked question.

Type by value and by reference

At least we’re talking about semantics, because Python uses everything by reference, when we talk about being by reference is a new indirect and has case that maintain a semantic value, as is string.

So lists, dictionaries and objects defined by the programmer are considered semantics by reference, in general because they’re large and changeable, so you want an object transport to be cheap, And because it’s big, it’ll almost always cost a lot of money to use the indirect to just copy the address of where the object is and keep a single object without actually copying it. In addition to this gain if you move the object in a variable is always moving the same object, which in mutable objects this is desirable in the overwhelming majority of cases.

The objects you call normal are immutable and small and they exist by themselves and are stored directly in the variable (in Python this is not quite true, but for all intents and purposes this may be that someone comes to speak that is different, but does not change anything in practice, only everything has extra indirect that makes the language inefficient). So every reference to the object is unique, when you copy the data is copying the object itself and not its reference.

Your example

So in the first example the reference of a is being copied to l_item when it calls the function, and the object is the same, it now has only two references to it. One of these references is lost when the function ends since the parameter is a local variable that has its lifespan linked to the function. The lifespan object is bound to have at least one reference to it (Python has a Garbage Collector which erases the object when it has no reference to it anymore).

So if you have two references and the object is the same any change in the object reflects to all variables that are the reference to it.

The same happens in the second example. You are doing the same thing when you copy the value of a for b is copying the reference to the object and not the object, and any change made through one variable will be reflected in the other variable because the object is the same, it is not it that is copied.

So in function the two are copies and act alike, just because one of them does not have the equal sign (assignment) does not mean that it is not assigning and is not a copy. But all decent languages always copy the value of the variable, and types by reference its value is not object but the reference, this is copied.

If you really want to have two list objects, and almost always this is an error in types by reference, you need to create a new object and copy element by element from it to the other object. The method is ready copy() the type of list and the operator of Slice ([:]) also.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.