Learn a basic understanding of Python references and class attributes from zero

  • 2020-04-02 13:38:02
  • OfStack

Python is an interpreted, object-oriented, dynamic data type high-level programming language. Since the birth of Python in the early 1990s, it has been widely used to handle system administration tasks and Web programming. Python has become one of the most popular programming languages. In January 2011, it was named the 2010 language of the year by the TIOBE programming languages rankings. Since 2004, python usage has increased linearly.

Python's insistence on a clear, uniform design makes it a versatile language that is easy to read, easy to maintain, and popular with a large number of users.

In view of the above advantages, I couldn't help but learn some Python, a little harvest, to share with you.

I recently did a little research on Python's object reference mechanism, leaving notes for reference.

The first thing is clear: "everything in Python is an object."

So what does this mean?

The following code:


#!/usr/bin/env python
a = [0, 1, 2] #  Let's have a simple one list
#  At first, list  And each of its elements id  That's right. 
print 'origin'
print id(a),a
for x in a:
    print id(x), x
print '----------------------'
#  Let's change the first element 
print 'after change a[0]'
a[0] = 4
print id(a),a
for x in a:
    print id(x), x
print '----------------------'
#  Let's change the second element 
print 'after change a[1]'
a[1] = 5
print id(a),a
for x in a:
    print id(x), x
print '----------------------'
#  So let's go back and write it down 0  . id How much is the 
print 'how about const 0?'
print id(0), 0

The operation results are as follows:


PastgiftMacbookPro:python pastgift$ ./refTest.py 
Origin
[0, 1, 2]
0
1
2
----------------------
after change a[0]
[4, 1, 2]
4
1
2
----------------------
after change a[1]
[4, 5, 2]
4
5
2
----------------------
how about const 0?
0

From the "Origin" section, the addresses of each element in the list are exactly 24 apart, pointing to their respective data -- which brings me to arrays.

When the value of a[0] is modified, the address of a[0] is changed. In other words, the assignment statement simply redirects a[0] to another object. In addition, it was noted that the difference between the address of a[0] and that of a[2] was 48 (two 24).

When a[1] is modified again, the address of a[1] also changes. Interestingly, this time the address of a[1] and the address of a[0] are 24 different from each other, and 72 different from the original a[2].

Finally, when you print out the address of the number 0 directly, you find that the address is exactly the same as the address of the original a[0].

At this point, it's basically clear that even elements in a list are references. By modifying the elements in the list, you are actually modifying the reference.

 

As for class attributes in Python, someone mentioned that "class attributes are Shared between the same class and its subclasses, and modifying class attributes affects all objects in the same class and its subclasses."

It sounds scary, but on closer inspection, it's not a big deal.

The following code:


#!/usr/bin/env python
class Bird(object):
    name = 'bird'
    talent = ['fly']
class Chicken(Bird):
    pass
bird = Bird();
bird2 = Bird(); #  The same instance 
chicken = Chicken(); #  The subclass instance 
#  It started out like this 
print 'Original attr'
print id(bird.name),      bird.name
print id(bird.talent),    bird.talent
print id(bird2.name),     bird2.name
print id(bird2.talent),   bird2.talent
print id(chicken.name),   chicken.name
print id(chicken.talent), chicken.talent
print '----------------------------'
#  Let's see under a different name 
bird.name = 'bird name changed!'
print 'after changing name'
print id(bird.name),      bird.name
print id(bird.talent),    bird.talent
print id(bird2.name),     bird2.name
print id(bird2.talent),   bird2.talent
print id(chicken.name),   chicken.name
print id(chicken.talent), chicken.talent
print '----------------------------'
#  Try a talent (modifies an element in a class attribute) 
bird.talent[0] = 'walk'
print 'after changing talent(a list)'
print id(bird.name),      bird.name
print id(bird.talent),    bird.talent
print id(bird2.name),     bird2.name
print id(bird2.talent),   bird2.talent
print id(chicken.name),   chicken.name
print id(chicken.talent), chicken.talent
print '----------------------------'
#  New talent tree (entire class attribute changed) 
bird.talent = ['swim']
print 'after reassign talent'
print id(bird.name),      bird.name
print id(bird.talent),    bird.talent
print id(bird2.name),     bird2.name
print id(bird2.talent),   bird2.talent
print id(chicken.name),   chicken.name
print id(chicken.talent), chicken.talent
print '----------------------------'
#  Washing out the new talent tree (modifying elements in the new class attribute) 
bird.talent[0] = 'dance'
print 'changing element after reassigning talent'
print id(bird.name),      bird.name
print id(bird.talent),    bird.talent
print id(bird2.name),     bird2.name
print id(bird2.talent),   bird2.talent
print id(chicken.name),   chicken.name
print id(chicken.talent), chicken.talent
print '----------------------------'

Operation results:


PastgiftMacbookPro:python pastgift$ ./changeAttributeTest.py 
Original attr
bird
['fly']
bird
['fly']
bird
['fly']
----------------------------
after changing name
bird name changed!
['fly']
bird
['fly']
bird
['fly']
----------------------------
after changing talent(a list)
bird name changed!
['walk']
bird
['walk']
bird
['walk']
----------------------------
after reassign talent
bird name changed!
['swim']
bird
['walk']
bird
['walk']
----------------------------
changing element after reassigning talent
bird name changed!
['dance']
bird
['walk']
bird
['walk']
----------------------------

In "Origin," the same class properties of the same class of objects and the same class properties of the subclass objects are all addressed in the same way -- this is called "sharing."

After changing the name, only the modified object name property changes. This is because the assignment to name is essentially changing a string and re-referencing it. The string itself has not changed. So there's no interaction between classes and subclasses.

Next, modify the elements in the talent. At this point, the situation changes: the talent attributes of the class and its subclasses all change along with it -- which makes sense because they both refer to the same memory address and refer to the same object.

Next, reassign talent to refer to another object. The result is that only the talent attribute of this instance has changed. As you can see from the memory address, the talent attribute of this instance and other instances no longer points to the same object. That is to say, "so far, this example is an outsider."

Then, it is easy to understand the result that when you finally modify the elements in talent again, it will have no impact on other instances. Because already is "outsider person", I again how toss about also is own affair.

So, "class properties interact with each other among classes and their subclasses" must be based on the premise that the class properties are never reassigned after the instance is created, that the class properties still point to the memory address they originally pointed to.

Finally, object properties

The following code:


#!/usr/bin/env python
class Bird(object):
    def __init__(self):
        self.talent = ['fly']
bird = Bird()
bird2 = Bird()
#  That's the beginning 
print 'Origin'
print id(bird.talent), bird.talent
print id(bird2.talent), bird2.talent
print '--------------------'
#  Modify the properties of one of the objects 
bird.talent[0] = 'walk'
print 'after changing attribute'
print id(bird.talent), bird.talent
print id(bird2.talent), bird2.talent
print '--------------------'
#  Dead: properties of two objects point to the same memory address and are modified 
bird.talent = bird2.talent
bird.talent[0] = 'swim'
print 'assign to another attribute and change it'
print id(bird.talent), bird.talent
print id(bird2.talent), bird2.talent
print '--------------------'

Operation results:


PastgiftMacbookPro:python pastgift$ ./changeAttributeTest2.py 
Origin
['fly']
['fly']
--------------------
after changing attribute
['walk']
['fly']
--------------------
assign to another attribute and change it
['swim']
['swim']
--------------------

Because object attributes are assigned to completely different memory addresses even if they have exactly the same content (which is usually the same after the initial initialization). So there is no "peer to peer effect."

But if the attributes of one object and another object point to the same address, the two (but only between them) are again implicated.


Related articles: