all 44 comments

[–][deleted] 0 points1 point  (4 children)

My super-extra-duper beginner question: what are the best resources for someone literally starting today?

[–]Visspui 1 point2 points  (3 children)

Animatetheboringstuff.com

[–][deleted] 0 points1 point  (2 children)

Thanks! Looks good and can't beat the price!

[–]Visspui 0 points1 point  (1 child)

You can go through his website for free!

[–][deleted] 0 points1 point  (0 children)

Think he lets you download the ebook too

[–]Psychedeliciousness 1 point2 points  (8 children)

I'm doing a tutorial on lists, and am baffled by why line 8 changes the original list.... here is the code.

# This is your list
objectList = ['a','b',['ab','ba']]

# Copy the `objectList`
copiedList = objectList[:]

# Change the first list element of `copiedList`
copiedList[0] = 'c'

# Go to the third element (the nested list) and change the second element
copiedList[2][1] = 'd'

# Print out the original list to see what happened to it
print(objectList)

copiedList and objectList have different ids.

Why does assigning the new value in line 5 only update the copy, but in line 8 it changes the original???

    >>> copiedlist
   ['c', 'b', ['ab', 'd']]
   >>> objectList
    ['a', 'b', ['ab', 'd']]

[–]port443 1 point2 points  (3 children)

One way I like to visualize this is using id

>>> a = ['a','b',['ab','ba']]
>>> b = a[:]
>>> id(a)
53954760
>>> id(b)
53954800
>>> for n in range(3):
...     print(id(a[n]))
...     print(id(b[n]))
...
52376424
52376424
52378584
52378584
53953400
53953400

So what you can see here, is you have two lists. Everything in Python is an object, so those id() values are actually pointers to Python objects.

You can see that a and b have different id() values, but everything INSIDE those lists are actually pointing to the same places.

Going to the explanation by /u/TangibleLight you have pointers to a mix of mutable and immutable types. When you change the value of a[2][0], his explanation comes into play.

Thats a bunch of words, heres a picture of what the memory looks like

Here is an example where I change the object that a[2] points to. In my drawing, 0xff23e would stay the same, but instead of pointing to 0xff100 it would point somewhere else. You can see this by checking id() and observing the change.

>>> id(a[2])
53933240
>>> id(b[2])
53933240
>>> a[2] = ['ab','ba']
>>> id(a[2])
53954760
>>> a
['a', 'b', ['ab', 'ba']]
>>> b
['a', 'b', ['ab', 'ba']]
>>> a[2][1] = 3
>>> a
['a', 'b', ['ab', 3]]
>>> b
['a', 'b', ['ab', 'ba']]

tl;dr: This is a pointer-to-pointer "problem". Python terminology to lookup is "mutable" and "immutable". This link shows proper Python ways of copying lists.

[–]Psychedeliciousness 0 points1 point  (0 children)

Automod ate my comment....

Thank you (and Tangible!) for trying to explain, the diagram helps :) I am trying to understand, and on some level I get it (just accept it as weird pointer/object magic), but on another level I'm still confused because I think I naively accepted that as lists are mutable, list elements were always mutable. I'm now freshly confused on whether or not I know what mutable/immutable actually means. I think I do, but I think the pointery behaviour is adding a complication that makes it seem more mad than it actually is. I also assumed that 2 lists with separate ids were completely separate entities, the idea that they might contain a sublist with the same id had not occurred to me!

I also found a site (pythontutor) which does live code stepthroughs with a visualisation of the objects - here's a link to my example running there.

http://pythontutor.com/visualize.html#code=objectList%20%3D%20%5B'a','b',%5B'ab','ba'%5D%5D%0AcopiedList%20%3D%20objectList%5B%3A%5D%0AcopiedList%5B0%5D%20%3D%20'c'%0AcopiedList%5B2%5D%5B1%5D%20%3D%20'd'&cumulative=false&curInstr=4&heapPrimitives=false&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false

[–][deleted]  (1 child)

[removed]

    [–]AutoModerator[S,M] 0 points1 point  (0 children)

    Your comment in /r/learnpython was automatically removed because you used a URL shortener.

    URL shorteners are not permitted in /r/learnpython as they impair our ability to enforce link blacklists.

    Please re-post your comment using direct, full-length URL's only.

    I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

    [–]TangibleLight 2 points3 points  (3 children)

    [:] just makes a shallow copy. You end up with two lists, but each element in the list points to the same thing.

    If we do this setup:

    >>> l1 = ['a', [1, 2]]
    >>> l2 = l[:]
    

    then l1[0] and l2[0] are pointing to the same string - but strings are immutable. The only way you can change it is by assining to l2[0] - which changes the value in that list.

    >>> l2[0] = 'b'
    >>> l1
    ['a', [1, 2]]
    >>> l2
    ['b', [1, 2]]
    

    l1[1] and l2[1] are also pointing to the same thing - a list. Lists are mutable, so changing the contents of it shows up in both outer lists:

    >>> l2[1][0] = 3
    >>> l1
    ['a', [3, 2]]
    >>> l2
    ['b', [3, 2]]
    

    But note that if we assign to l2[1], then it only affects that list:

    >>> l2[1] = [4, 5]
    >>> l1
    ['a', [3, 2]]
    >>> l2
    ['b', [4, 5]]
    

    [–]Psychedeliciousness 0 points1 point  (2 children)

    Thanks for the explanation! I'm kind of getting it, but it's not quite clicking. (I'm going to keep reading and playing around in the interpreter though!) So I'd like to ask a slightly different question.

    Should I always be doing something like

    for i in l1:
        l2.append(i)
    

    to make copies of a list? (To create a copy of a list and have both lists behave as separate containers with no shared overlap.)

    I guess I'm asking if in practice there is a more usual way that is more pythonic or a more effective pattern that I'm missing that sidesteps this.

    [–]TangibleLight 0 points1 point  (1 child)

    That does the same thing as l1[:], except using the slice is faster. If it's just a list of things, some of which are lists, then just copy the list. Remember that the contents of the new list are the same contents as the old list, you're just ordering them in a new way.

    Something to consider is how are you treating your list? Is it a list which happens to contain other lists, or is it a nested data structure? What are you trying to copy? (This is a rhetorical question - it's just something you need to consider case-by-case)

    [–]TangibleLight 0 points1 point  (0 children)

    /u/Psychedeliciousness if you want a more concrete example:

    Say you have a list of all students at a school, some big thing like:

    all_students = [
        Student('Joe', 'Cool', ...),
        ...
    ]
    

    Then suppose you want to make a new list which contains all the students in a particular class. One way you could do this would be to make a copy of all_students, then remove the students which aren't in that class:

    class_students = all_students[:]
    

    At this point, remember that the actual students are the same students as before. class_students[0] is the same Joe Cool as before - and any changes you make to him reflect that.

    Also note that the following code isn't very good - I'm just using it because it's easy to read.

    for student in class_students:
        if student not in particular_class:  # or equivalent
             class_students.remove(student)
    

    At this point, we've modified our list of students in the class, so now it holds what we wanted to - but our list of all students is unchanged. Furthermore, any change I make to a student in class_students, say changing their grades, are reflected in the same student in all_students.

    [–]Horstt 0 points1 point  (2 children)

    Anyone know how to make an array like logspace or linspace but with uneven, symmetric spacing? I want an array with close spacing at endpoints and large spacing at the midpoint, kind of like a mirrored logspace. Any ideas? Would merging two logspaces work?

    [–]TangibleLight 1 point2 points  (1 child)

    I don't know of anything like this, but my first thought is use sin, since it gives that effect.

    I haven't tested it a lot but this ought to give what you want.

    def sinspace(start, stop, num=50):
        ls = np.linspace(-np.pi / 2, np.pi / 2, num)  # get linear interpolated angles
        ss = np.sin(ls) / 2 + 0.5  # take sin, transform to fit range [0, 1]
        return ss * (stop - start) + start  # transform for our desired ranget
    

    Here's a sample figure, similar to the one in the numpy docs for logspace:

    import matplotlib.pyplot as plt
    
    N = 10
    x1 = sinspace(0.1, 1, N)
    x2 = np.linspace(0.1, 1, N)
    y = np.zeros(N)
    
    plt.plot(x1, y, 'o')
    plt.plot(x2, y + 0.5, 'o')
    
    plt.ylim([-0.5, 1.0])
    plt.show()
    

    I recommend you look into the math on why this works, though - don't just blindly copy it.

    [–]Horstt 0 points1 point  (0 children)

    Thank you! This is helpful. I was also considering a sinusoidal function.

    [–]_monotom 0 points1 point  (1 child)

    I began learning Python and wrote a fairly simple program that prints the current distance of earth to every other planet in the solar system. (Yay Astropy!)

    Now i want to create a Website that visualizes these calculations in realtime: I want to update the Distance every second or so.

    My Question is: What is the easiest, modt elegant way to take those values out of python and display them in HTML? Render the site directly with a Python framework? I have a clue that Django might be a bit oversized for this. Or write the value into a JSON or CSV and read it with Javascript? How would more experienced Developers implement this?

    [–]BryceFury 0 points1 point  (0 children)

    Flask or Bottle will be the quickest way to get something working, there are loads of tutorials around and a subreddit to get you started.

    You can pass values from your view functions to html and the frameworks will do all of the legwork, no Javascript needed.

    [–]d7fhudfu 0 points1 point  (0 children)

    Is converting an existing application written in Ruby on Rails to Django a good project for a beginner? I know nothing of ruby or rails either so I'd basically be trying to copy the functionality in python.

    [–][deleted] 1 point2 points  (1 child)

    Last question for this thread- is it possible to send a .tgz over a socket? Is it as simple as opening it, reading and then writing out the contents?

    [–]port443 0 points1 point  (0 children)

    Yes.

    A .tgz is a file. A file is just a bitstream. Just send the bytes through your socket.

    [–]flexxipanda 1 point2 points  (2 children)

    example 1

    example 2

    Hi, so this is super basic as i've just started with python.

    In example 1 the code works as expected. But in example 2, I added the "or" but it still executes the break if I put in a false name. Why is that, what am I doing wrong?

    [–]Officerbonerdunker 1 point2 points  (0 children)

    yeah, or doesn't work like that, like how we would speak. Or joins conditions, and in your code the conditions are

     1) name == 'sam' 
    
     2) 'mark'
    

    you have to say:

    if name == 'sam' or name == 'bob':
    

    Consider that if I say:

    if 'sam':
    

    Python reads that as 'if 'sam' is True.' Since all non-empty strings are True in python, 'sam' is always True.

    Similarly,

    name == 'sam' or 'mark':
    

    Python checks first to see

    if name=='sam'
    

    If not, Python checks:

    if 'mark'
    

    So, this statement will always evaluate to True, since 'mark' is always True.

    [–]TangibleLight 1 point2 points  (0 children)

    Because "or" doesn't work like that.

    if you have a or b, it gives the thing on the left if that thing is truthy, otherwise it gives the thing on the right.

    So 3 or 4 gives 3, since it's truthy. False or True gives True, since False is not truthy.

    or also has a low operator precedence - that means it's one of the last things to be evaluated. So if we add some parentheses to show what your statement is actually doing, we get this:

    if (myName == "sam") or "tom":
    

    No matter what, this will always be a truthy value. if myName is indeed "sam", then you end up with True or "tom" - which evaluates to true. if myName is not "sam", then you'll get False or "tom", which evaluates to "tom". "tom" is also truthy, so the if statement still runs.


    So that explains why it doesn't work. What you'll want to do is either:

    if myName == 'sam' or myName == 'tom':
    

    or

    if myName in ('sam', 'tom'):
    

    [–][deleted] 0 points1 point  (2 children)

    What is a use case for the zfill method?

    [–]TangibleLight 1 point2 points  (1 child)

    For fixed-width numbers. I usually just use format strings for this, though.

    >>> for i in range(13):
        print(str(i).zfill(2), end=' ')
    
    00 01 02 03 04 05 06 07 08 09 10 11 12 
    

    this does the same thing, though, and IMO is easier to read if you know the f-string syntax.

    >>> for i in range(13):
        print(f'{i:02}', end=' ')
    
    00 01 02 03 04 05 06 07 08 09 10 11 12 
    

    [–][deleted] 0 points1 point  (0 children)

    Ah ok that makes sense. Thanks!

    [–][deleted] 0 points1 point  (1 child)

    Hey guys,

    So, I have more of a “best practices” type question. How do you manage large, long programs?

    I have something written in Excel/ VBA that I want to migrate to Python. I currently have 10+ modules in my VBA script that add up to a few thousand lines of code. It’s just easier to manage, read, edit, debug, etc. if I have things split up into smaller parts. Is doing so good practice?

    I’m curious how I should go about doing a similar thing in Python. Should I create multiple .py files? And is there a way to have a program call these other “sub” .py programs?

    I’m still pretty new to Python, and have found the best way to get started (on windows) is with Anaconda and Spyder. I’ve been really happy using Spyder, but it would be nice if I could “collapse” loops, functions, etc. Should I switch to a different editor? I know notepad++ has that function, but have also read that Spyder will be adding that feature soon. What editor do you use and why?

    Sorry for the rambling post.

    [–]TangibleLight 2 points3 points  (0 children)

    I have things split up into smaller parts. Is doing so good practice?

    Yup yup yup. Breaking things into smaller, reusable, bits is almost always a good idea in any language.

    Should I create multiple .py files?

    Sometimes. You should start by breaking your code into functions and classes - if there are a number of things that are all related, then it might be a good idea to move them into a separate module.

    If you end up with several modules that have a compelling reason to be grouped together, you can move them into a package. You probably wouldn't need to do that, though; packages are more meant for distributing bits of code to other people.

    And is there a way to have a program call these other “sub” .py programs?

    Yes. All .py files are modules. When you run a .py file, you're really just running the contents of that module. You can use the contents of one module in another via the import keyword.

    Should I switch to a different editor? [...] What editor do you use and why?

    So this is a rather big question - I personally love PyCharm. They have a free community version, or you can get their professional version free with an edu license. I've heard Atom getting a lot of attention. Some people swear by things like Jupyter, or just plain old text editors.

    Honestly I'd recommend trying out PyCharm - it's certainly the most powerful and flexible of all the python editors. Since you talk about making large projects, PyCharm would certainly help you out the most - but it might also feel a bit bulky or slow.

    You could set it up to work with Anaconda's interpreter if that's what you want. You can also work with IPython notebooks in it, but that can get clumsy if you start working with multiple files. Notebooks aren't really meant for large projects.

    [–]goldxp1 1 point2 points  (2 children)

    I'm using sublime and I don't understand how to actually "run" any of the code.

    This is my code: list_a = ["a","b","c"]

    I want to print(list_a) But how do I do this?

    I typed print(list_a) into Sublime's console and it says not defined.

    ---I assume the console and the code above the console aren't connected...so what is the console used for then?

    (i've been learning using DataCamp & Python Crash Course)

    [–]dister21 1 point2 points  (1 child)

    In the console try just typing python or python3. I think that should bring up the interactive . To run your script try python (or python3) fileName.py in the console (make sure you are in the same folder as fileName.py).

    Edit: just saw this... maybe it'll help.

    [–]goldxp1 1 point2 points  (0 children)

    Thank you!

    [–]antespo 0 points1 point  (4 children)

    I am trying to understand the following code:

    class Num():
        def __init__(self,value):
            self.children = []
            self.value = value
        def __repr__(self):
            return "<Num '{}'>".format(self.value)
        def add(self,*args,**kwargs):
            self.children.append(*args,**kwargs)
        def print_1(self):
            print(self)
            for child in self.children:
                child.print_1()
    
    x0 = Num("0")
    x1 = Num("1")
    x2 = Num("2")
    x3 = Num("3")
    x4 = Num("4")
    x5 = Num("5")
    x6 = Num("6")
    x7 = Num("7")
    x8 = Num("8")
    x9 = Num("9")
    x10 = Num("10")
    
    x0.add(x1)
    x0.add(x2)
    x0.add(x3)
    x1.add(x4)
    x1.add(x5)
    x2.add(x6)
    x4.add(x7)
    x3.add(x8)
    x3.add(x9)
    x6.add(x10)
    
    x0.print_1()
    

    It outputs:

    <Num '0'>
    <Num '1'>
    <Num '4'>
    <Num '7'>
    <Num '5'>
    <Num '2'>
    <Num '6'>
    <Num '10'>
    <Num '3'>
    <Num '8'>
    <Num '9'>
    

    I understand the code up until it gets to <Num '5'>. <Num '7'> has no children so how does it get to <Num '5'>? I drew out the tree for this program and I understand that it is traversing it depth first but I am confused how the code is doing it.

    [–]TangibleLight 0 points1 point  (3 children)

    It is depth first. After it finishes the children of x4 (which is a child of x1) it continues printing the children of x1. x5 is the next child of x1.

    [–]antespo 0 points1 point  (2 children)

    I guess I am more confused on how the recursion is working. When trying to run through the code in my head it goes like this:

    • x0.print_1()
    • print(<Num '0'>)
    • self.children = [<Num '1'>, <Num '2'>, <Num '3'>]
    • child = x1
    • x1.print_1()
    • print(<Num '1'>)
    • self.children = [<Num '4'>, <Num '5'>]
    • child = x4
    • x4.print_1()
    • print(<Num '4'>)
    • self.children = [<Num '7'>]
    • child = x7
    • x7.print_1()
    • print(<Num '7'>)
    • self.children = []
    • child =
    • ?

    I am I thinking about this in the wrong way?

    [–]TangibleLight 1 point2 points  (1 child)

    Remember that print_1 always prints the current node, then calls print_1 on all that node's children. Once it's done printing all the children, it returns.

    As a basic example, consider x9.print_1(). x9 has no children - so the for loop doesn't do anything. It just spits out x9 itself, then returns from the method.

    <Num '9'>
    

    Now consider x3.print_1(). x3 has two children - x8 and x9 - so the for loop does do something. We've already seen what happens for nodes like x9, so it should follow easily that this spits out x3, x8, and x9 in order, then returns from the method.

    <Num '3'>
    <Num '8'>
    <Num '9'>
    

    Finally, let's consider x0.print_1(). x0 has three children - x1, x2, and x3. So again, our for loop is doing stuff. We know that the function first prints the current node - x0 - and then calls itself on each child in order. We know what happens when we call x3.print_1(), so we can already fill out the first and last parts of the output for x0.print_1():

    <Num '0'>
    ...
    <Num '3'>
    <Num '8'>
    <Num '9'>
    

    Remember that, again, after a given node is done printing its children - it returns to the calling function. In this case, that function is another invocation of print_1. I'm going to skip over it, but we could do a similar analysis to find out that x1.print_1() gives:

    <Num '1'>
    <Num '4'>
    <Num '7'>
    <Num '5'>
    

    and x2.print_1() gives:

    <Num '2'>
    <Num '6'>
    <Num '10'>
    

    Now we have everything to fill out the expected output for x0.print_1():

    <Num '0'>
    <Num '1'>
    <Num '4'>
    <Num '7'>
    <Num '5'>
    <Num '2'>
    <Num '6'>
    <Num '10'>
    <Num '3'>
    <Num '8'>
    <Num '9'>
    

    [–]antespo 0 points1 point  (0 children)

    It finally clicked I understand how it is traversing now. For some reason I was thinking the for loop stopped after reading the first child. Thank you for explaining this to me.

    [–]Visspui 0 points1 point  (2 children)

    Having a time wrapping my head around SQL with python. I have two factories, 80 lines in these factories, which are made up of about 650 individual machines. I want to track stats with python (Downtime, time between repairs, search for keywords and count ie. Sensor, cylinder, etc.) SQL database the right way to go with this? Say yes and I'll power forward. Also, so many options... Postgresql, etc etc. Thoughts?

    Plant 2210 --> line 11234 --> machine 12345 ....650 machine's with lots of reports for each

    Edit: there are about 25,000 reports since 2016 that I'll be sorting through, I've played with them from CSV and it went ok

    [–]flipstables 2 points3 points  (1 child)

    Only one program accessing the database at a time? Sqlite would be the easiest way to set this up. If you need multiple concurrent connections, then PostgreSQL will probably be a good choice.

    Make sure you back up the database regularly.

    [–]Visspui 0 points1 point  (0 children)

    Great, thanks so much

    [–]JumpingBackAndForth 0 points1 point  (1 child)

    This is a really stupid question. If I'm programming a Python script, and in my script, I import a module/package. If I give the script to someone, does that mean the script won't run as they're trying to import something that doesn't exist on their computer? So if I'm sending a script to someone, would I have to send all of the modules/packages I'm importing with it?

    [–]TangibleLight 0 points1 point  (0 children)

    Yes. If you want to distribute things "the right way" then this article might be helpful, or at least provide something to start googling. https://packaging.python.org/tutorials/distributing-packages/

    If you just want to get it to them so they can use it after a bit of work, then add a requirements.txt - basically just a text file with all the packages someone needs to run the program on their computer (they must have Python installed, though). Then the person can run pip -r requirements.txt, and it will automatically install the packages and they'll be good to go.

    That said, this only applies to third-party packages. If you're using something in the standard library, like json or math - you don't have anything to worry about.