omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    A real newby question... Is shuffle a time travelling operation?

    Pythonista
    4
    8
    3724
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • adrius42
      adrius42 last edited by

      These four lines are in a def setup function

      self.emoji_original = self.emoji_names
      print(self.emoji_original)  # result is alphabetic as expected
      shuffle(self.emoji_names)
      print(self.emoji_names, self.emoji_original)```
      
      Why does the second print  show that both arrays have been shuffled?
      1 Reply Last reply Reply Quote 0
      • JonB
        JonB last edited by

        Lists in python are objects, so when you modify one, both references are affected, since they refer to the same object.

        x=[1,2,3]
        y=x
        print(id(y)==id(x)) 
        

        Use .copy() to get a new copy that won't affect the original

        z=x.copy()
        print(id(z)==id(x))
        
        1 Reply Last reply Reply Quote 0
        • adrius42
          adrius42 last edited by

          Aargh, this may explain some other faux pas I have been making.

          Why??! This feels very counter-intuitive changing the meaning of equals in this way.
          I guess way back in the mists of time the original Python developer had a reason!
          So actually the operator was the time traveller! (Or rather the temporal cloner!)

          so I was confident it had its own object id

          I am getting ever more convinced that I do not understand the operation of “self”
          Can you point me to some text that would help me... it feels like self is not always self, and often self is “not defined’ when I know it had been!?

          I would have preferred
          B = A transferred contents of A to B just thus once
          B == A results in B becoming the same as A for all time

          But then I am just wishing that the Python Language understood me, rather than me having to understand it!

          To be clear this only applies to lists right?

          A = 1
          B = A
          A = 2
          Won’t change B to 2

          So, are there any other types of variables where the operators change what they do?

          It would be useful to know now! Rather than be struggling with coding issues ;-)

          bennr01 1 Reply Last reply Reply Quote 0
          • bennr01
            bennr01 @adrius42 last edited by bennr01

            @adrius42 said:

            Why??! This feels very counter-intuitive changing the meaning of equals in this way.
            I guess way back in the mists of time the original Python developer had a reason!
            So actually the operator was the time traveller! (Or rather the temporal cloner!)

            IIRC, most languages do this. It allows some usefull stuff which would otherwise be impossible.
            For example, assume you had the following code:

            def add_defaults(l):
                """add some default values"""
                if "value_default" not in l:
                    l.append("value_default")
            
            
            def remove_invalid_values(l):
                """remove all invalid values from list"""
                ...
            
            some_values = ask_user_for_input()
            add_default_values(some_values)
            remove_invalid_values(some_values)
            print(some_values)
            

            Due to having the same list shared between the functions, we can avoid unneccessary assignments. This is both easier and way more efficient.

            But the more important reason is consistency: list are objects. This is the same in many programming languages due to the way they work. And all non-primitve objects (maybe there are some exceptions, but none important) are not directly assigned to a variable. Instead, when you say some_object = SomeObject(), SomeObject() is created somewhere in your RAM and a reference is created which points to SomeObject(). This reference is then assigned to some_object. When you use some_var = some_object, some_var actually gets a copy of the reference, like some_var = some_int would do, but the copy of the reference still points to the same object. Thus, even if some_var is a copy of the reference in some_object, it still points to the same object.
            Maybe this code can explain this a bit better:

            class SomeClass(object):
                """some class"""
                def __init__(self, v):
                    v = v
            
            int_var_a = 1  # int_var_a is directly assigned the integer 1
            int_var_b = int_var_a  # int_var_a is loaded, and the content is assigned to int_var_b
            print(int_var_a == int_var_b)  # True, both are equal
            int_var_a = 2
            print(int_var_a == int_var_b)  # False
            
            obj_var_a = SomeClass("value_1")  # an instance of SomeClass() is created and stored in the RAM. A reference pointing to SomeClass() is created and assigned to obj_var_a
            obj_var_b = obj_var_a  # the >reference< if obj_car_a is copied to obj_var_b
            print(obj_var_a.v == obj_var_b.v)  # True, because both obj_var_* point to the same object
            obj_var_b.v = "some other value"  # the object is modified, but both obj_var_* still point to the same object
            print(obj_var_a == obj_var_b)  # True, because both obj_var_* still point to the same object and both have been modified
            

            I am getting ever more convinced that I do not understand the operation of “self”
            Can you point me to some text that would help me... it feels like self is not always self, and often self is “not defined’ when I know it had been!?

            self is in fact not a operation, but a variable name without any real meaning.
            Here is some more code:

            
            class MyClass(object):
                def method_a(self, x):
                    # self points to the instance of MyClass() this method is called on. x is some other value
                    pass
            
                def method_b(foo, x):
                    # foo points to the instance of MyClass() this method is called on. x is some other value
                    # this is because the first parameter of a bound method is always the object
                    pass
            
                @staticmethod
                def some_static_method(x):
                    #This is a static method. self is not defined here. x is some other value passed to this method.
                    pass
            
                @classmethod
                def some_class_method(cls, x):
                    # This is a class method. cls is not pointing to the instance of the object this is called on, but instead pointing to the class this is called on.
                    # this is useful for alternative constructors
            

            In other words: self is always defined if you name the first parameter/argument of a bound (more about that later) method self. If you name the first parameter/argument of a bound method foo, then foo would be the equivalent of self.
            A bound method is a normal method of an instance of a class. In the above example, MyClass().method_a and MyClass().method_b are bound methods, because they are "normal" methods (not modified by @staticmethod or @classmethod) of an instance (MyClass()).
            If you use MyClass.method_a or MyClass.method_b (please note the missing (), this is the class, not instances of the class), these are unbound methods, as they are not part of an instance. In this case, self must be specifically passed to the method.

            Also, about self: you can think about self as some sort of namespace. self is unique per instance of a class. Changes to self persist between methods of the same instance, but not between methods of different instances.

            I would have preferred
            B = A transferred contents of A to B just thus once
            B == A results in B becoming the same as A for all time

            In python, == means a comparsion of equality.

            But then I am just wishing that the Python Language understood me, rather than me having to understand it!

            Dont worry, you are not the only one...

            To be clear this only applies to lists right?

            A = 1
            B = A
            A = 2
            Won’t change B to 2

            So, are there any other types of variables where the operators change what they do?

            This behavior applies to all non-primitive types.
            Some example of primitive types are int, long and float.
            Non-primitive types are basically everything else, mostly instances of classes.
            So, a={}; b=a; b["a"] = 2 would also modify a.
            a=1; b=a; b=2 would not change a, because both b and a are primitive.
            Strings are interesting. They are objects, but immutable. a=""; b=a; some_change(b) would change a too, but since neither a nor b can be changed, this is not a problem.

            Small disclaimer: I am not involved with the development of python and can thus not guarantee that the above information is correct, but it should be.

            Sorry for my bad english, it is not my native language. I still hope that this may be of help for you.

            1 Reply Last reply Reply Quote 1
            • JonB
              JonB last edited by

              Out of curiosity, do you come from a Matlab background? Matlab is a little unique in that matricies act like primitives, not objects, and so assigning a matrix to another variable creates a copy (though, a sort of delayed copy that only takes the performance penalty if you modify it).

              This for me led to many mistakes when first learning python.

              1 Reply Last reply Reply Quote 0
              • adrius42
                adrius42 last edited by

                Much older! Algol then, Basic. More recently Arduino and Sphero!
                I am restarting my coding activities and try to keep my brain active!
                And to get ahead of my grandchildren for a millisecond or two!

                cvp 1 Reply Last reply Reply Quote 0
                • adrius42
                  adrius42 last edited by

                  @bennr01 Thank you muchly for taking the time to answer my musings.

                  I assure you, that your English is not the problem, in my comprehension of these concepts, it is much more my lack of understanding!

                  I will spend the time to extract the wisdom from your response. Thankyou!

                  1 Reply Last reply Reply Quote 0
                  • cvp
                    cvp @adrius42 last edited by

                    @adrius42 Very old, indeed. I knew also Algol, like Fortran, Pl/1, Cobol, Apl and all IBM Main frames languages, all were not object oriented, thus all variables were "native", thus this difference did not exist.
                    Welcome in the world of Pythonista, marvelous app for retired people 😂

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post
                    Powered by NodeBB Forums | Contributors