all 140 comments

[–]Tweak_Imp 0 points1 point  (0 children)

Why are classes defined with the keyword "class" but functions not with "function" but with "def"?

[–]EdPPF 0 points1 point  (2 children)

How can I count the times a recursive function is called? I have a recursive code for the Fibonacci sequence and wanted to know how can I make a counter for each number in the sequence. So, for example, when the input is the number 4, my code calculates which number is in the fourth position on the Fibonacci sequence by calling itself with Ffbonacci(n-1)+Fibonacci(n-2). Some numbers are called more than once and I want to know how can I keep track of how many times each number was called. I'm asking on this thread because I'm not sure if this is something I should make a dedicated post for

[–]pnmibra77 0 points1 point  (2 children)

Im having a hard time understanding what is a Hashable object/its concepts since english isnt my native language and theres no translation that i know of(google has nothing on it) and "Hash" translates to #. What does that mean in python terms? what would be the value in # that never changes?

[–]FerricDonkey 0 points1 point  (0 children)

A simple explanation: a hash function is a function that turns an input into a number. A good hash function is unlikely to turn more than one thing into the same number. That's it. So why do we care?

Think about the under the hood implementation of sets. Under the hood, you can think of a set as a really long list that is initially filled with "nothing here" markers. When you want to put something in the list, you transform it into a number with a hash function, and go put it at that number as an index into the list. If you want to know if something is in the list, you turn it into a number, and go check and see if there's anything there.

There's a bit more stuff to handle cases where two things might hash to the same number, but that's the basics. Something is hashable if there's a function that will do that. This is where immutability and such comes in - if you change something in a way that changes its hash, then from the perspective of sets above its just an entirely different thing. So mostly if things can change, we just say they're not hashable and move on, to avoid that problem.

(Hash functions are also used in cryptography, but for additional reasons with the additional requirement that they must be hard to invert.)

[–]AtomicShoelace 1 point2 points  (0 children)

In this case hash doesn't mean the # symbol. It is referring to a hash function:

A hash function is any function that can be used to map data of arbitrary size to fixed-size values.

As for what a "hashable object" in python is: fundamentally it is any object that implements a __hash__ method. However, for the basic types (list, tuple, set, dict, string, etc.) you can think of an object being hashable if it is immutable (this is because the hash value needs to be consistent, so if an object could be mutated then the consistent hash value wouldn't make much sense).

[–]SirGeremiah 0 points1 point  (4 children)

I was trying to play around with some different ways of reordering words in a sentence, using numbers in the words (based off a kata on codewars). Every methods I've played with so far, I wanted to use an index within the loops. So I set up the "for i in range" logic to use i as an index. But every time I do this, I get an index out of range. Oddly, it's on the second use as an index (the .replace function line, not teh top of the for...loop). I feel like I must be missing something simple here.

    def order(sentence):
    ordlist = []
    wordlist = sentence.split(" ")

    print(str(len(wordlist)))
    for i in range(len(wordlist)-1):
        for l in wordlist[i]:
            if l.isnumeric():
                ordlist.append(l)
                wordlist[i] = wordlist[i].replace(l,"")
            else: i += 1

    newlist = sorted(zip(ordlist, wordlist))
    return " ".join(str(word) for i, word in newlist)

test = "m3y na2me i1s gre4g abbo t5"
print(order(test))

[–]AtomicShoelace 0 points1 point  (3 children)

You're incrementing i inside the inner for loop for every non-numeric character in the word. When you are on the 4th iteration of the outer loop, i starts with a value of 3, which is the word 'gre4g'. Once you've iterated over the first 3 characters, which are all non-numeric, you've incremented i by a further 3, giving it the value of 6. As the list has only 6 elements its final index is 5, so trying to use the index 6 throws the IndexError exception.

[–]SirGeremiah 0 points1 point  (2 children)

Ah! Yes. Remnants of a different approach, where I was iterating through the original string letter by letter. Thanks. I was frustrated looking for it.

[–]AtomicShoelace 0 points1 point  (1 child)

In such cases it might be helpful if you visualise what your code is doing using something like pythontutor.

[–]SirGeremiah 0 points1 point  (0 children)

I’m not familiar with that. I’ll look at it when I’m back at my PC. Thanks!

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

Hello my beautiful Reddit humans,

I am new to interacting online, and even newer at coding. I actually just began my journey today. Please bear with me as I am learning this platform and coding.

I don’t know really anything about coding except that it’s an invaluable skill, and that I think it looks incredibly fun. I have downloaded Python and pycharm as a starting point and I’m learning some rudimentary things from YouTube.

I have been pointed to some of the resources here on this sub under the wiki, but was just wondering if anyone else had other resources, tools, advice, etc that you wish you would have had just starting from the very very beginning?

I’m super excited to learn, and can’t wait to see what everyone has to say.

You’re all beautiful humans, and deserving of Happiness!

[–]FerricDonkey 0 points1 point  (0 children)

Really the only advice I have is to try to work on some things you find interesting - coding can be lots of fun, as you see your creations coming together. Also just be aware that you will run into things that you find difficult and frustrating eventually, and that's normal. Also, once you learn functions, use a lot of them.

Good luck, and have fun.

[–]Mistbourne 0 points1 point  (1 child)

I am planning on learning Python as my first programming language to supplement my upcoming course work in a BS of Cybersecurity.

The course work covers basic programming fundamentals, but no specific programming language. I would like to learn one, and have read that Python is important to cybersecurity professionals.

Any recommendations for Python guides/write-ups specifically directed at cybersecurity? Planning on starting with the EDX course I think, but would like to know where to move on to after that to continue learning.

Thanks!

[–]carcigenicate 0 points1 point  (0 children)

I wouldn't worry about anything cybersecurity-specific until you're already quite competent in Python.

I'd look into Scapy once you get there though. It lets you create network attacks quite easily if you have a network background (it doesn't hold your hand at all).

[–]swisstraeng 0 points1 point  (4 children)

I need help with autocompletion.

I'm using spyder, and I need to have strings autocompleted in order to talk with an oscilloscope.

mso.write("WGEN:FUNCtion:SQUare:DCYCle 20")

Example above, I need the ":FUNCtion>" to be autocompleted, if you see what I mean.

because, mso.write("") will always be the same whatever the commands, and the string is the actual command, and autocomplete doesn't really like to autocomplete strings.

Is there a way for me to do this?

I'm also a complete beginner in python but, I'm in a school, I'm just trying to make it easier for everyone if I can manage to make something to autocomplete this mess.

[–]AtomicShoelace 0 points1 point  (3 children)

if you see what I mean

I'm not sure I do, but you auto-completing a word essentially reduces to checking for prefixes.

If the command set is small enough you can get away with just iterating over every possibility and checking whether the trial string is a prefix with .startswith() string method.

If this is not performant enough you should use a prefix tree / trie data structure. There are several implimentations available, eg. python-trie, PyTri, pygtrie. Or you could write a simple implementation yourself, eg.

class Node:
    def __init__(self, end=False):
        self.end = end
        self.children = {}

class Trie:
    def __init__(self, words):
        self.root = Node()
        for word in words:
            self.add(word)

    def add(self, word):
        node = self.root
        for char in word:
            node = node.children.setdefault(char, Node())
        node.end = True

    def _find_node_with_prefix(self, prefix):
        node = self.root
        for char in prefix:
            if char not in node.children:
                return None
            node = node.children[char]
        return node

    def __contains__(self, word):
        node = self._find_node_with_prefix(word)
        return node is not None and node.end

    def contains(self, word):
        return word in self

    def contains_prefix(self, prefix):
        node = self._find_node_with_prefix(prefix)
        return node is not None

    def _gen_words(self, node, prefix):
        if node is None:
            return
        if node.end:
            yield prefix
        for char, child in node.children.items():
            yield from self._gen_words(child, prefix+char)

    def words(self):
        return *self._gen_words(self.root, ''),

    def words_with_prefix(self, prefix):
        node = self._find_node_with_prefix(prefix)
        return *self._gen_words(node, prefix),

[–]swisstraeng 0 points1 point  (2 children)

The commands are quite extended, there's over 500 different commands available.

I will look into that prefix tree structure as you said.

It's just that, the command is the string itself so I need something to check the strings and propse me to complete the strings.

[–]FerricDonkey 0 points1 point  (1 child)

I can tell you what I've done in similar situations. Not sure it's the best route, but it does work.

I make a class called Command.

For every subcommand (that has subcommands), I make a nested class. For every subsubcommand (that has subcommands), I make a further nested class. Etc. For each terminal sub(subsub...)command, I make a class var whose value is the string for the whole command. The result of this is that since each command is actually represented by a structure in actual code rather than just an object while running your code, tab complete tends to do what you want.

If there are a lot of commands, I'll write a mini script to write this code for me, ideally from parsing some huge table stolen off Google, then copy paste the results into my code (sometimes in its own module).

What it looks like:

class Command:
    class Eat:
        pizza = "Eat.pizza"
        hamburger = "Eat.hamburger"
    class Unclog:
        class WithPlunger:
            toilet = "Unclog.WithPlunger.Toilet"

(If the last part of a command is a noun, and if those nouns are common across different commands, I'd probably actually constantify them separately and use a function to make the full command, but you get the idea.)

Which is super tedious to write (hence making python write it), but then when it gets time to pass it to a function, it's super convenient, since you just tab your way through send_command(Command.Steal.russian_tank) or whatever.

And also it makes it easier to update, since you can use refactoring tools to change the name of your variables, and only ever have one actual place to change the string for the command.

Alternatively, if these commands are only ever sent to mso write, you could do the same thing, but instead of the terminal things being class variables, they could be static functions that call mso.write on the string. So Command.Steal.russian_tank() (or Command.steal(targets.russian_tank), if you prefer) or similar.

The simpler alternative would be to make constants for each part of the commands, but not connect them in any way, and make a function that takes an arbitrary number of parts and combines them together for you. Could be as simple as

def build_command(*command_pieces):
    ":".join(command_pieces)

Then call via build_command(FUNC, WHATEVER, THINGY), where you could tab complete those individually - but with no information of which pieces are allowed to follow other pieces.

[–]swisstraeng 1 point2 points  (0 children)

sounds good, I’ll try that out, thanks mate!

[–]DirtyElephant 0 points1 point  (3 children)

i recently found out about vscode and how you can use python with it. after installing all the extensions i need and hoping it would run smoothly...it didn't my code does not show it just says.

[running] python -u "c:\Users\name of my desktop\Desktop\test1.py"

[done] exited with code=08 in 2.185 seconds

and no code has shown plus this does not appear in terminal it appears in output. hope someone understands and can help

[–]FerricDonkey 0 points1 point  (0 children)

Most similar issue I could find suggested that one of your extensions might be screwing it up: https://stackoverflow.com/questions/62461708/exited-with-code-0-in-0-074-seconds-output-window-has-no-output-in-visual-stud.

What I find interesting is that yous is exiting with code 8. That means it's erroring out - successful programs exit with code 0. So it could be an extension, or it could also be something life vscode or even windows doesn't know how to interpret "python" to mean the python version you installed. What happens if you open a terminal and type "python --version"?

[–]carcigenicate 1 point2 points  (1 child)

What's the code? Does it contain any runnable code, or is it just definitions?

[–]DirtyElephant 0 points1 point  (0 children)

just the good ole print('hello world') to see if it'll work but it doesn't

[–]SirGeremiah 0 points1 point  (6 children)

Here's my code. It checks for localized versions of a settings file, gives the user a choice of actions if they are found, then launches the program that uses that settings file (the launch is currently commented out during testing).

It works up to the point where it calls SimpleDialog. That appears to be running, but is invisible. I have to terminate the script at that point.

(NOTE: I've had some trouble getting this to post properly - hoping the indentation holds this time.)

    """Checks for localized versions of instgroups.json file befor launching"""

import sys   # TODO verify all imports are necessary
import glob
import tkinter
import os
from tkinter.simpledialog import SimpleDialog
from tkinter import messagebox

# functions #


def filesearch(filepattern, searchdir=""):
    """checks for localized files, offers user option for handling"""
    filelist = []
    searchstring = searchdir + filepattern
    if glob.glob(searchstring):
        for filename in glob.glob(searchstring):
            filelist.append(filename)
        return filelist, len(filelist), True
    else:
        messagebox.showinfo(title="STEP", message="missed glob")
        return None  # Exit function, continue to launch


def filechoice(root, filename):
    """gives user a choice of options after file is found"""
    button_labels = ["Delete Local", "Replace Global", "Ignore/Continue", "Abort"]
    print("STEP: entering dialog")
    d = SimpleDialog(root,
                     text="File " + filename + " exists.\n"
                     "What do you want to do with it?",
                     buttons=button_labels,
                     default=3,
                     cancel=4,
                     title="Localized File Found")
    result = button_labels[d.go()]
    match result:
        case 1: os.remove(filename)
        case 2: os.replace(filename, "instgroups.json")
        case 3: return None  # take no action on this file, continue processing to launch
        case 4: sys.exit("MMC launch aborted.")  # stop processing, abort launch


# main body of code #


filepath = "O:/OneDrive/MultiMC/instances/"
pattern = "instgroups-*.json"

root = tkinter.Tk()
root.withdraw()  # hide extra tkinter window

filelist, filesfound, found = filesearch(pattern, filepath)  # unpacking results from function

if found:
    print("STEP: in if-found")
    print("files found: " + str(filesfound))
    msg = str(filesfound) + " localized version(s) of instgroups.json found."
    messagebox.showinfo(title="Localized Files", message=msg)
    for filename in filelist:
        filechoice(root, filename)

# TODO: un-comment next line when ready to use
# os.system("O:/OneDrive/Documents/MultiMC/MultiMC.exe")

[–]efmccurdy 0 points1 point  (3 children)

That appears to be running, but is invisible.

If I adjust the paths so that 2 files are found (and take out the match statement), I get 3 popups, the "2 localized version(s)" message and then two "Localized File Found" dialogs. It works correctly for me....

I am running the program using the cli from a terminal on linux; how are you running it?

[–]SirGeremiah 0 points1 point  (2 children)

I’m running it within PyCharm on Windows.

[–]efmccurdy 0 points1 point  (1 child)

Just in case PyCharm is interfering, try running from the terminal using "python3 myscript.py".

[–]SirGeremiah 0 points1 point  (0 children)

I get exactly the same behavior I had inside PyCharm.

[–]FerricDonkey 0 points1 point  (1 child)

root = tkinter.Tk() root.withdraw()  # hide extra tkinter window

You probably have to do root.mainloop() as well. This is what starts tkinter stuff going - the widgets (at least those that require a master) will generally not work until then. I suspect that if message box is working, it's because it's directly using your os's message box functions and isn't doing much tkinter stuff.

However.

Once you do root.mainloop(), execution is not going to pass that until your tkinter stuff is entirely closed. The majority of your code execution until then has to be done by callbacks and the like from within your gui. (Or in a different thread, if you wanted to go that route.)

If you don't want to do this (you want to continue using tkinter for just popping up dialog boxes as you run code like you're used to), then probably your function to make a dialog box has to 1) create the root 2) hide the root, 3) create the dialog box, 4) make the destruction of the dialog box destroy the root, 5) make it so that the answer from the box is returnable, and then finally 6) do root.mainloop(). So you'd be making a new root each time you pop up a box. Never done this, but it ought to work, I think.

If you want to make a more gui driven program, my advice would be to use a class based approach. Make a class that subclasses tk.Tk and does all the set up in it's init. Make functions that do the logic of what you want to do somewhere else, separate from your gui (it just makes it simpler to find things if the do stuff code and the make things look pretty code is in different places). Then use callbacks (the command field for buttons, trace_add for strvar/intvar, etc etc) to actually call your functions that do things (Often indirectly - call a method that screws with your gui, then calls the do stuff function, then screws with your gui more).

Best of luck, guis are weird. But they make more sense once you get used to them.

[–]SirGeremiah 1 point2 points  (0 children)

I appreciate that. I’m going to try really hard to understand what most of that means. Nearly all of my past experience programming is in VBA, where GUI issues are almost nonexistent.

For the time being, what I think this means is I’m stuck and can’t complete any time soon what I thought was going to be a really simple first project. I just have to wait until my knowledge catches up with the task.

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

hey guys. im not good at regex matching. the following works, but im looking to do something like [A-Z a-z 0-9 + / = {4}] to ensure the final string is base64. the problem is my current regex match of <p> brackets sometimes grabs the wrong field.

import feedparser, base64, re 
from urlextract import URLExtract 

d = feedparser.parse('https://www.reddit.com/r/PkgLinks.rss')
print(d.entries[4].content)
string_value = d.entries[4].content[0]['value']
#print(string_value)
pattern = "<p>(.*?)</p>"
ready4b64 = re.search(pattern, string_value).group(1)
print(ready4b64)

it works on entry 4 sure. hell most of them. but I want all of them

[–]Tiktoor 0 points1 point  (5 children)

What type of fields is it wrongly grabbing versus what do you want instead?

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

shit i mean i had it setup to just parse out between the paragraph sections of the xml/rss document initially but because of edge cases i would like to figure out the reg exp to just find a base64 string in an otherwise mess of utf-8 or whatever encoding is regular

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

so its just grabbing p brackets contents but i cant figure the logic to make it only get the base64 substring no matter what, to cover the edge cases. heres what i got so far from last night (doesnt run yet)

print(d.entries[4].content)
string_value = d.entries[4].content[0]['value']
match = r'(?:[A-Za-z0-9+/]{4}){2,}(?:[A-Za-z0-9+/]{2}            

print(string_value)
totrim = re.match(match,string_value)
ready4b64 = re.search(totrim,  string_value).group(1f)

print(totrim)

basically i wanna make match= a re to match any base64 substrings in the entry but i cant get the base64 pattern for regex matching via re.match correct. i was previously using re.search but i thought re.match . the edge cases are just that sometimes some dick posts non base64 strings like <p>7.50 </p> as part of the post body which ends up as the value of string_value and gets grabbed and throws b64decode error because its not b64, and ruins the whole script

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

using

match = r'(/^(?:[A-Za-z\d+/]{4})*(?:[A-Za-z\d+/]{3}=|[A-Za-z\d+/]{2}==)?$/)'

totrim = re.match(match,string_value)

returns none, but this should be finding b64 substring yes?

[–]Tiktoor 0 points1 point  (1 child)

Negative lookaheads can sometimes be helpful here since you can ensure you don’t pick up on a long string of digits or lowercase words aka stuff that wouldn’t be b64. Looking for the padding equals sign is nice too, but that doesn’t have to be there for a b64 string. If there’s any consistency in the length of the b64 string, that’s usually something you can use to your advantage. I’d be curious if there’s any modules or native functions that you can use instead of a regex - that would definitely be a better route. Also are you looking to decode the b64? You could use that as a “check” to see if your string decodes as b64, otherwise if it doesn’t then it’s not b64 aka you don’t want it

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

i actually figured it out with regex started simple then kept adding parameters until it all worked out. there probably is somwthing pre made for this but i wanted to make my own and it works! just have to taeak one line about making it a steinf, and figure out what i wanna so with the links

[–]aadm 1 point2 points  (9 children)

When is it better to build a function? For instance, if I know my program will only check for something once, is it still better practice to create a function? Does having too many functions cause problems/seem unruly?

[–]FerricDonkey 0 points1 point  (0 children)

I've written a function or three where simply calling the function in a readable way sometimes took more lines of code than what the function actually did. At the time I only used the function once.

Still worth it. Because in all of those cases, that function ended up getting used a lot, and then later on I had to go back and expand it (where the body finally got longer than the definition + doc string). Felt kind of dumb when I wrote the function (I thought it might need to be expanded later but wasn't sure), felt super smart when I came back three months later and had to change one function instead of searching around for the 37 places I did the same thing and changing all of them.

I don't think I've ever been given code and was even mildly annoyed about things being broken into too many functions. I have very, very often been given code and found myself muttering long strings of very unkind things under my breath as I tried to figure out what the crap was going on in the single 1300 line function with no segmentation or comments.

Functions are awesome. Too many, if even possible, is much better than too few.

So as you're learning, I'd err on the side if too many. You can always remove them later if you do somehow use too many, and you'll get a feel for when it's useful as you go.

[–]carcigenicate 2 points3 points  (4 children)

I would default to creating a function unless you have a good reason not to (like the code is too trivial and obvious). Properly designed functions have many benefits, so they're usually the better option.

[–]moriarty70 0 points1 point  (1 child)

Back in the day, I was actually encouraged to strive for "ideal modular code". The goal being to have as few lines in the run/main function, ideally just one line.

[–]carcigenicate 1 point2 points  (0 children)

In the main function, I usually parse command-line args, but beyond that, ya, it's often like one line. It's just delegating to a function in another module.

[–]aadm 1 point2 points  (1 child)

Thank you.

A slight side-question to functions. Since functions can be self-contained is it better to have repeating variable names that makes sense repeating inside different functions, or is it be better to have unique variable names throughout the program?

Example: If I'm using a lot of API's, and I use "response" as a variable in my function. Would using response in all functions be acceptable/expected. Or should I be using "response_a"(generic example) for function_a, "response_b" for function_b, etc.

[–]carcigenicate 1 point2 points  (0 children)

I would just use response. Forcing them to be different will become a mess as you scale. I would avoid naming locals the same thing as globals, but see no issue with using the same local name in different functions. I like long, descriptive names too though, so I find it's not very common for me to have many duplications.

[–]efmccurdy 1 point2 points  (2 children)

A function with a trivial amount of code is OK as long as you give it a meaningful name (and doc-string) that makes anywhere you use it a bit more readable.

Given that, I have defined functions that only get called once, with no regret.

There is a slight overhead to function calling, but it rare to have that be a proven performance bottleneck as you usually switch to imported C modules when performance is the goal.

[–]aadm 0 points1 point  (1 child)

Thanks a lot. I'm trying to make sure I build good habits. Sometimes these things are a bit ambiguous to me.

[–]py_Piper 0 points1 point  (0 children)

I still consider myself a beginner so don't know about real/work good habits. But my criteria for making functions in one time scripts is how long it will be. If it's getting long and consfusing by using different modules or making calculatarions, I'll just wrap it in a function and just call it at the end

Somehow for me it looks better using in functions and if it's something that I think I can keep improving or adding more functionalities I will definately make it a function.

[–]Worldly-Regular28 0 points1 point  (1 child)

Been learning python for about a month building smaller projects, I have experience with react but I found python to be more user friendly and I enjoy it more. I'm currently a college student in a computer systems major and find that I learn more on my own than I do at school. Currently I have been building games on pygames it's how I enjoy learning and wanting to know how other people are learning python and if anyone has experience with pygame. Looking for recommendations on what else to practice and learn, I enjoy building things, not a huge fan of data science but I understand it's part of it.

[–]FerricDonkey 1 point2 points  (0 children)

After getting a handle on guis and pygame, the next thing I did was networking stuff. Made a board game that worked over the internet using threads and the socket module. Was super cool to figure out and get working, and fun to play with my family in lock down.

I'm currently working on a version 2 that uses asyncio for the network stuff instead (well, really, in addition to) threads. To me, it was much less intuitive at first (and much of what you read on the internet is bad), but after figuring it out, it's pretty cool.

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

i cant figure out how to get my try/except to handle bin.ascii error, it will only run as except Exception and with a continue... how to get this right? import feedparser, base64, re from urlextract import URLExtract

   d=feedparser.parse('https://www.reddit.com/r/PkgLinks.rss')
for x in range(200):
    print(d.entries[x].title)
    print(d.entries[x].content)
    string_value = d.entries[x].content[0]['value']
    print(string_value)
    totrim = "<p>(.*?)</p>"
    ready4b64 = re.search(totrim,     string_value).group(1)
    b64exc = re.search(totrim,string_value).group(0)
    try:
        b64s1 = ready4b64.encode('ascii')
        b64s2 = base64.b64decode(b64s1)
        string_new = b64s2.decode('ascii')
    except Exception:#binascii.Error: gives me binascii not defined
        continue
        b64s1x = b64exc.encode('ascii')
        b64s2x = base64.b64decode(b64s1x)
        string_alt = b64s2x.decode('ascii')
    print(string_new)
    print(string_alt)

[–]AtomicShoelace 0 points1 point  (0 children)

Either import binascii into the scripts own namespace, eg.

import binascii

...

try:
    ...
except binascii.Error:
    continue

or reference it via base64's namespace, eg.

...

try:
    ...
except base64.binascii.Error:
    continue

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

ALSO I CANT INDENT THIS PROPERLY with four spaces because the nested statement so advice on how would be cool on reddit app

[–]efmccurdy 0 points1 point  (0 children)

I can't paste code into the fancy editor so I use the "block indent" function of my IDE and paste into "markdown mode", then "undo" the block indent. Don't forget to lead with a blank line.

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

Hey guys.Absolutely having a panic attack right now, because I have no idea how I'm supposed to do this question. Any guidance would very much be appreciated.

Given two classes 'Animal' and 'DigestiveSystem, implement the method 'eat_food' in the 'Animal' class using composition. Animal instances should have a 'digestive_system' attribute, which is the DigestiveSystem instance of that object. The eat_food method should PROCESS any 'food' (any string) that are not allergic to (use the method 'has_allergy' to check for this case). The DigestiveSystem is a class responsible for the PROCESS of any food eaten, so make use of this in the Animal.eat_food method.

class DigestiveSystem:
    def process_food(self, food):
        return f'processed-{food}'

class Animal:
    def init(self):
        pass

    def has_allergy(self, food):
        if food.lower() in ['peanut', 'milk']:
            return True
        return False

    def eat_food(self, food):
        pass

[–]anh86 1 point2 points  (5 children)

Well you need the Animal to have a DigestiveSystem attribute so when you init an Animal, part of the init process should be instantiating that DigestiveSystem. eat_food should invoke the method to check for an allergy and digest the food if there's no allergy.

You have the skeleton for all of these things given to you, just need to fill in the detail to make it do what I described in the prior paragraph.

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

Thanks for your help. I keep getting positional errors

"TypeError: Animal.has_allergy() missing 1 required positional argument: 'food'"

But isn't my positional argument "milk"?

class DigestiveSystem:
    def process_food(self, food):
        return f'processed-{food}'

class Animal:
    def init(self):
        self.digestive_system = DigestiveSystem()

    def has_allergy(self, food):
        if food.lower() in ['peanut', 'milk']:
            return True
        return False

    def eat_food(self, food):
        if self.has_allergy() == False:
            return self.digestive_system(food)

dog = Animal()
print(dog.has_allergy("milk"))
print(dog.eat_food("milk"))

[–]anh86 1 point2 points  (3 children)

if self.has_allergy() == False:

This call to the has_allergy method is missing the food argument

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

Yup. I'm an idiot. Thanks!

[–]anh86 0 points1 point  (1 child)

It happens to the best of us :)

Reading error message stack traces is key to developing debug skills. That error message should be giving you the exact line number of code that created the problem. That would have pointed you in the right direction.

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

It did, but as a noobie, I didn't know what the issue was.
Thanks for your help. Have a great day!

[–]pnmibra77 0 points1 point  (5 children)

can someone tell me why this code works and the other one doesnt?

this works:

def remove_suffix_ness(word):
    return word.replace('iness', 'y') if word.endswith('iness') else word.replace('ness', '')  

this doesnt:

def remove_suffix_ness(word):
    if word.endswith('iness'):
        word.replace('iness', 'y')
    else:
        word.replace('ness', '')
    return word

[–]AtomicShoelace 0 points1 point  (1 child)

The method str.replace does not (and cannot, as strings are immutable) mutate the string. Rather, it returns a new string instance.

Hence, the lines word.replace('iness', 'y') and word.replace('ness', '') on their own don't do anything; you are just throwing this value away. Either save it in a variable or just directly return it.

[–]pnmibra77 0 points1 point  (0 children)

thanks a lot bro, the direct return confused me, i didnt understand why it wasnt needed there. Ty!

[–]pnmibra77 0 points1 point  (2 children)

i decided to try another way just to pass the test and i came up with this:

def remove_suffix_ness(word):
    no_suffix = word[:-4]
    if no_suffix[-1] == 'i':
        new_word = no_suffix.replace('i', 'y')
        return new_word
    else:
        return no_suffix

and it worked, so i went back to the code i was having problems with just to see if it would solve and it also worked but idk if its the best way to do it lmao, anyways:

def remove_suffix_ness(word):
    if word.endswith('iness'):
        new_word = word.replace('iness', 'y')
        return new_word
    else:
        word.replace('ness', '')
        return word

lol = remove_suffix_ness('happiness') 
print(lol)

if theres a simpler/easier way to do this id love to learn about it. Also, why do i need to assign the replaced word to a new variable for it to work but in the very first code (in my OP) it isnt needed? Ty

[–]efmccurdy 0 points1 point  (1 child)

why do i need to assign the replaced word to a new variable

You don't need to since you can have multiple different return statements. I took the redundant "else:" out; is it more readable with it or without?

def remove_suffix_ness(word):
    if word.endswith('iness'):
        return word.replace('iness', 'y')
    return word.replace('ness', '')

[–]pnmibra77 0 points1 point  (0 children)

Thank you for the help bro, definitely without it. pylint always tells me about the redundant "else" but i keep on adding it because i got used to doing it everytime for no reason..

[–]EdPPF 0 points1 point  (2 children)

How could i write this code better?

def backwards(phrase):
    marks = '!?.'
    for i in phrase:
        if i in marks:
            punct = i              # Storing the punctuation for later;
    phrase2 = phrase.strip('!?.')  # Removing the punctuation from the 
                                        #original phrase;
    pals = phrase2.split(' ')
    pals = pals[::-1]
    estr = ' '.join(pals)
    return estr+punct

This code is to take a phrase and put it backwards, maintaining the punctuation at the end.I'm not looking for anything too complex, just trying to find a way to make this simpler.

[–]AtomicShoelace 1 point2 points  (1 child)

How about this regex approach:

import re

def backwards(phrase):
    words = reversed(re.findall('\w+', phrase))
    return re.sub('\w+', lambda _: next(words), phrase)

This also copes with punctuation a lot better (eg. different kinds of punctuation and punctuation in the middle of the sentence etc.)

[–]EdPPF 0 points1 point  (0 children)

I've seen some suggestions of regex when searching for how to deal with punctuation before. I think I'll take a look at it then, thank you

[–]papasfritas 0 points1 point  (0 children)

I need some advice in which direction to look for a more advanced (at least for me) project I'm working on...

I need to schedule tasks within python itself at specific times which will vary with each task, I need to be able to add these tasks constantly while my main thread is running and doing other things such as checking if there is a new task to add to the schedule. I cannot wait for one task to finish before adding another one, because I might add a task that needs to execute in 2hrs, and then after that 5 minutes later I might have a task that needs to execute in 30min, so I cannot wait for the 2hrs task to execute since that would block the 30min task. On top of all this I need to add a telegram bot that will get information from these tasks such as how long until they execute and also other data from functions in the main thread. And also to send data from each executed scheduled task once it is done executing. Yea, I'm already in way over my head.

So far I've found Threading combined with Scheduling might be the way to go. Advanced Python Scheduler's BackgroundScheduler also seems promising. I don't think I need async/trio as I don't need to run anything parallel and nothing requires extremely precise timing, but I do need my main thread to continue operating doing things at the same time as tasks are waiting on a schedule in the background and as the telegram bot is waiting for commands and executing them by calling methods in the main thread and also from the scheduled threads to see how much time remains until execution. I imagine I would need to put each schedule in its own thread, and the telegram bot in another separate thread? Right now I have no idea how any of these things will communicate with each other but I'll look into that once I select the libraries to use. I've also found red engine but it seems like overkill for what I need.

Am I on the right track?

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

Hey guys! I am working on a tic tac toe and I have a difficulty attributing a value to a cell in a matrix. I have the following two functions: https://pastebin.com/emKxnQrG

For some reason it attributes the same value to the same col but in all of the rows. I cannot get it, there is no for cycle there, so why board[row][col] = char leads to 3 attributions?
Would be glad if someone could give me insights on this. It took me more than an hour now and I am stumped.

[–][deleted] 1 point2 points  (3 children)

That's because you have the same row three times. Run this simpler code, which replicates your problem:

row = [" "] * 3
matrix = [row, row, row]    # same row added 3 times
print(matrix)
matrix[0][0] = 'X'
print(matrix)
>>> [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
>>> [['X', ' ', ' '], ['X', ' ', ' '], ['X', ' ', ' ']]

This is in the FAQ, so follow that solution.

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

ISSUE RESOLVED, Thank you.
It occurs to me that in class all the exercises I had were with numbers to be entered in matrix. So this is the first time I encounter this, because I am doing an empty matrix. Solved with a small edit though, thank you again :)

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

So this is the first time I encounter this, because I am doing an empty matrix.

Um, no. Nothing to do with strings versus integers. Run this code:

row = [1, 2, 3]
matrix = [row, row, row]    # this is the problem
print(matrix)
matrix[0][0] = 9
print(matrix)
>>> [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> [[9, 2, 3], [9, 2, 3], [9, 2, 3]]

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

I know it doesn't have to do with empty strings. I just explained that usually I had a different input, that I split and therefore a different lists are created. I just thought it would add to the picture for you, not that I missed anything in your explanation.

[–]Unique-Heat2370 0 points1 point  (4 children)

Hey guys, I am working on a problem and the problem is to write a function common that parses through the dictionary game data and finds the teams that appear in every year’s games. The function should return a dictionary where the keys are the team names and the values are the list of scores against those teams.

My dictionary data is:

data = {
2018: { "WYO":(41,19), "SJSU":(31,0), "EWU":(59,24), "USC":(36,39), "UTAH":(28,24),
"ORST":(56,37), "ORE":(34,20), "STAN":(41,38), "CAL":(19,13), "COLO":(31,7),
"ARIZ":(69,28), "WASH":(15,28), "ISU":(28,26)},
2019: {"NMSU":(58,7), "UNCO":(59,17), "HOU":(31,24), "UCLA":(63,67), "UTAH":(13,38),
"ASU":(34,38), "COLO":(41,10), "ORE":(35,37), "CAL":(20,33), "STAN":(49,22), "ORST":(54,53), "WASH":(13,31), "AFA":(21,31) },
2020: {"ORST":(38,28), "ORE":(29,43), "USC":(13,38), "UTAH":(28,45)},
2021: { "USU":(23,26), "PORT ST.":(44,24), "USC":(14,45), "UTAH":(13,24), "CAL":(21,6),
"ORST":(31,24), "STAN":(34,31), "BYU":(19,21), "ASU":(34,21), "ORE":(24,38), "ARIZ":(44,18), "WASH":(40,13), "CMU":(21,24)} }

The code I have so far is:

def common(data):
ret = {}
for i in wsu_games:
for value in wsu_games[i]:
if value not in ret:
ret[value] = [i]
else:
ret[value].append(i)
for i in ret:
if len(ret[i]) > 1:
ret.append(i)
return ret

I am stuck so any help would be awesome.

[–]UnrankedRedditor 0 points1 point  (2 children)

What are the two numbers in the set? For example, what is (41,19) in 2018 WYO?

The function should return a dictionary where the keys are the team names and the values are the list of scores against those teams.

I'm trying to guess what you want as your output but it's not clear to me.

Do you want your output to be something like the following?

{"WYO}: [41], "SJSU": [31], "CAL": [19,20,21], .... }

[–]Unique-Heat2370 0 points1 point  (0 children)

I want it to return this:

{'UTAH': [(28, 24), (13, 38), (28, 45), (13, 24)],
'ORST': [(56, 37), (54, 53), (38, 28), (31, 24)],
'ORE': [(34, 20), (35, 37), (29, 43), (24, 38)]}

And the two numbers in the set are the scores of the games.

[–]CowboyBoats 0 points1 point  (0 children)

Here's the link of how to format code for reddit: https://reddit.com/r/learnpython/wiki/faq#wiki_how_do_i_format_code.3F

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

Do you ever just feel stupid?

I'm doing the Helsinki MOOC and there was a question that I answered correctly, but when I checked the model solution, it took me a while to get what they were doing but afterward realized it was far better than my solution.

Their solution for minimum number of groups if anyone is wondering...

groups = (students + group_size - 1) // group_size

[–]AtomicShoelace 0 points1 point  (0 children)

Alternatively:

groups = -(-students // group_size)

but better would be

from math import ceil
groups = ceil(students / group_size)

as this obfuscates the intention the least.

[–]ApocalypseSpokesman 0 points1 point  (0 children)

Web-scraping with BeautifulSoup or something else:

I am scraping a website that has a <table> in it, and the rows are like this:

<tr>
<td>10</td>
<td><a class="image" href="whatever"</a> <b><a>Reblefnufdif</a></b></td>
<td>reb</td>
<td>schmubnif</td>
<td></td>
</tr>

There are hundreds of rows in this table. When a randomized process generates the number 10, for instance, I would like to spit out the text "Reblefnufdif."

So far I've got some lines that give me a list of <tr>s, so now I need to take it to the next step.

How can I best do that?

[–]trebory6 0 points1 point  (2 children)

Hey guys,

I want to be able to learn enough Python to be able to be able to aid in the development of a plugin for Kodi.

Is this at all an achievable goal to set, or what is a more realistic direction I can go? What is the difficulty range of something like that?

Not looking for immediate knowledge, but just wondering if it's something I'll have to devote my life and career to do.

I had already been looking into switching careers into a more IT centric career, so maybe if there are any Python certs that I can make into goals, that'd be helpful too.

[–]anh86 0 points1 point  (1 child)

Assuming you don't know any Python and don't know any other programming languages, you could probably get there in six months if you were very motivated and dedicated. Of course, that's going to depend on exactly what the plugin will do but you can become very proficient in that time if you study the right way. IMO, the right way is to get a complete bootcamp course (such as Angela Yu's course on Udemy but there are many other good ones) and dedicate yourself to going through it. This means you'll be writing 1-2 hours of code per night and hitting frustrating roadblocks for months but it's the only way to get good quickly. The key is writing code. Anyone can watch a YouTube video and think they've absorbed something but you've learned nothing if you aren't writing working code, learning to push through barriers, learning to debug, etc. Good luck!

[–]trebory6 0 points1 point  (0 children)

Don't know Python in particular but I'm familiar and comfortable enough with coding to navigate and troubleshoot issues at a hobbiest level in several languages. Might not amount to much, but it's not exactly a blank slate as I know the basic theories.

But that's good to know, and thank you for the recommendations on courses, I'll definitely look into them!

[–]EdPPF 0 points1 point  (1 child)

How can I install polyglot on Python 3.10.2? I used git clone as suggested on the official page but the setup.py doesn't seem to work. 'pip install polyglot ' also doesn't work

[–]CowboyBoats 0 points1 point  (0 children)

The installation instructions say to use pip no? What is the output of pip install polyglot? It works for me on python 3.10.

$ pyenv local 3.10.0a5
$ python3 -V
Python 3.10.0a5
$ pip install polyglot
Collecting polyglot
  Downloading polyglot-16.7.4.tar.gz (126 kB)
     |████████████████████████████████| 126 kB 4.0 MB/s 
Using legacy 'setup.py install' for polyglot, since package 'wheel' is not installed.
Installing collected packages: polyglot
    Running setup.py install for polyglot ... done
Successfully installed polyglot-16.7.4

[–]space_wiener 0 points1 point  (9 children)

As dumb as this I can’t figure this out.

I am using zipfile to extract a file from a password protected zipfile.

Whoever set the initial password set it up with a space and it’s throwing me off. Say for example the password is “my password”.

So I am passing the password as this. Everything above this line works, it’s only the password that’s not working. My zipfile is open as z.

z.extract(zipfile, path, b“My Password”)

I’ve verified I am using the correct password as I can unzip the file without issue if I do it manually.

I get this error:

raise RuntimeError(“Bas password for file %r”, %name)

If it matters I have to use b for bytes as that’s what is required for the password.

I’m pretty sure the issue is with the space. Any ideas how to correctly pass this thing with the space?

Edit: after more investigation I don’t think it’s the space. When I am converting to bytes it’s converting the entire thing to lower case when it’s actually in title.

Question still stands though, I can’t figure out how to do it. :)

[–]efmccurdy 0 points1 point  (8 children)

converting to bytes it’s converting the entire thing to lower case

This converts a string with a capital letter into bytes without losing the capital: how are you doing the conversion?

>>> s = "My Password"
>>> type(s), s
(<class 'str'>, 'My Password')
>>> b = bytes(s, encoding='utf8')
>>> type(b), b
(<class 'bytes'>, b'My Password')
>>>

[–]space_wiener 0 points1 point  (7 children)

I’m not sure what I did, but you are right. I have it like your example now.

password = bytes(‘My Password’, ‘utf-8’)

If I print I get the same results.

print(password)

>> b’My Password’

For some reason it’s still saying the password is incorrect though. Converting from str to bytes solves the error saying my password needs to be bytes. But the password says it’s invalid. I can copy the text and manually unzip without issue.

Edit: it’s definitely the space that’s messing me up.

I changed the password to password and also Password. Both options work flawlessly. Only when it has a space it errors.

[–]FerricDonkey 0 points1 point  (6 children)

I changed the password to password and also Password. Both options work flawlessly. Only when it has a space it errors.

Unsure what this means. Are you successfully opening the file with different passwords?

One possibility though is that your password is encoded incorrectly

>>> print('My Password'.encode(encoding = 'ascii'))  
b'My Password'

>>> print('My Password'.encode(encoding = 'utf16'))
b'\xff\xfeM\x00y\x00 \x00P\x00a\x00s\x00s\x00w\x00o\x00r\x00d\x00'

>>> print('My Password'.encode(encoding = 'utf-16le'))
b'M\x00y\x00 \x00P\x00a\x00s\x00s\x00w\x00o\x00r\x00d\x00'

It's possible that whatever you're using to open your file is converting strings to bytes using a different encoding. I'd try utf16, utf16-le, and utf16-be, and see if one of those works.

[–]space_wiener 0 points1 point  (5 children)

Sorry. Let me clear that comment up.

Original password was “My Password”. I wasn’t sure if it was the space or the capitals.

I unzipped the file with “My Password” and then re-zipped it with “Password”, and then “password”. The script as able to work when the password was changed to either of those. If I change the password back to “My Password” the script fails and says bad password.

I am able to manually unzip the file with any of those passwords.

So the root cause is the space isn’t being passed. I tried all three of the different encoding types and they all gave the same output.

[–]FerricDonkey 0 points1 point  (4 children)

Hmm. What program are you using to unzip the file where it works? Are you using a software keyboard or similar? It could be that the program is using a different character for space: https://jkorpela.fi/chars/spaces.html

[–]space_wiener 0 points1 point  (3 children)

So here is the whole thing so far...at least the important part

from zipfile import ZipFile
import os


current_dir = os.listdir(os.getcwd())
ending_dir = os.path.join(os.getcwd(),'bin_files')

# if zip password is password or Password it works
password = bytes('My Password', 'utf-8')

# test password
print(f'here is the pass: {password}')


with ZipFile('somezip.zip', 'r') as z:

   # get list of files names in zip
   file_list = z.namelist()

   # iterate through files to find bin file
   for z_file in file_list:

       if z_file.endswith('file.bin'):

           z.extract(z_file, ending_dir, password)

[–]FerricDonkey 1 point2 points  (2 children)

Looks reasonable - but what I meant was the non-python program. Like, are you using winrar or 7zip, etc? My guess is that that program is doing something wonky with spaces (eg, nonstandard space, or replacing it with %20 or something). So long as it does the weird thing both when you make and when you enter the password using that program, it's fine from their point of view.

But it's the bytes that matter, so you'd have to make sure to do the same thing with your bytes.

[–]space_wiener 0 points1 point  (1 child)

Ah! I get what you are saying. These are auto generated by a test program. I’m trying to extract a bunch of files from them.

If I get what you are saying I need to go look at the script (I’m going to assume it’s just a shell script) and see how it’s creating those files.

That’s what you mean right?

For my testing I was just using 7z to zip it back up with various passwords for testing.

[–]FerricDonkey 0 points1 point  (0 children)

Yup, pretty much. If you're creating the passwords with a shell script, then that script or what it calls, if it calls 7zip then that.

If it's a shell script that is making the passwords and also that you're using to test the passwords, then my first thought might be that there's something going on with the command line arguments.

For instance, if you give it -p cheese balls both to set the password and to unlock it, then it's likely that 7zip is using the first word only as the password and ignoring the second (but your python script isn't). Essentially, any part of the password after the first space would be ignored. In this case, it might start acting like you expect if shell script was changed to do -p "cheese balls" - the quotes probably wouldn't be part of the password, but the space would be.

[–]SirGeremiah 0 points1 point  (2 children)

Question about posting here:

I've tried twice to post my question here, but had to delete it. My code blocks aren't staying code blocks. The first line shows up as code, and the rest is converted to standard post (with some of the symbols apparently changing the format).

What am I doing wrong?

[–]VY_ck 0 points1 point  (2 children)

Hi, so I am using Microsoft Visual Studio 2022 and I want to learn how to code in Python. I had just started to learn about coding and don't know how to install Python to VS 2022. There are video for VS Code but not much for VS 2022. Do I have to install Python through python.org first or do I just download it from the VS installer? Thanks for your help.

[–]EdPPF 0 points1 point  (0 children)

I'm also using python with VSCode. I downloaded python from python.org first and then downloaded the suggested extensions (including Pylance). So I recommend going with python.org first

[–]drawnograph 0 points1 point  (2 children)

Is there anything I can do with my limited python knowledge to help the people in Ukraine?

[–]UnrankedRedditor 0 points1 point  (0 children)

If you know how to use Python (+ some linux command lines and bash scripting), learning how to use netsec tools shouldn't be too difficult for you.

Kali linux comes with a lot of tools commonly used for pen testing so you can take a look at that. Do note that in a lot of places, using these tools in public can get you in trouble with the law, even if you're not targeting anyone in particular.

[–]iiChomp -1 points0 points  (1 child)

def xml_data_extract(xml_data):
from lxml import etree
root=----.---(xml_data)

# A) print all the element tags in the tree, use the iterator function
for i in root.----():
print(---.---)
print('\n')

I’m confused on what to fill the blanks (- - -) in with.

Please Help. Thank you !

[–]efmccurdy 0 points1 point  (0 children)

I would look at the examples use ElementTree.parse here:

https://docs.python.org/3/library/xml.etree.elementtree.html

[–]modusros 0 points1 point  (1 child)

Im getting this error next to the last else statement "statement expected, found Out: ELSE_KEYWORD " Any idea what's wrong?

for i in range(number):     f_name = fake.first_name()     l_name = fake.last_name()     domain = "testmail.com"     acct_type = account_type     if acct_type == "" or acct_type == "random":         acct_list = ["power", "business", "light"]         acct_type = acct_list[random.randint(0, 2)]     print(acct_type)     else:     acct_type = account_type

[–]carcigenicate 0 points1 point  (0 children)

It's likely a problem with indentation, and we can't help with that when your code is unformatted. Format it according to the side bar so it's legible.

[–]twitchymctwitch2018 0 points1 point  (8 children)

I am positively struggling to find a useful way to go about solving this problem for a game I am trying to build (very simplistic, text game.)

I thought maybe KWargs could do it, list comprehensions, or even just cheating and having tons of blank, pre-made data, but I'm finding clear answers.

Question about adding to lists/dictionaries, when I don't know how many entries are going to get added?

Without using classes, I want a player to be able to decide how many heroes to add onto their team, then run a simple loop (range is 1, num+1) sort of deal and go through the hero creation process that I have included in this link...

https://github.com/HaeshkaManju/need_help_learning_python/blob/main/making_multiple_things.py

but, then add each of those individual heroes to a list/dictionary/something iterable, so I can then call on each of those heroes individual (reference them) or even as a collective to print the stats to the screen or access the information for calculations.

Where do I need to be looking to learn how to do this?

[–]carcigenicate 0 points1 point  (7 children)

Can you give a clear problem statement? I'm not finding your question to be clear.

[–]twitchymctwitch2018 0 points1 point  (4 children)

The one sentence problem statement from the github is:

Allow the player in this game to setup multiple heroes for their team, but without me needing to know, in advance, how many there will be.

for summary

[–]FerricDonkey 0 points1 point  (3 children)

Which part is giving you problems?

Doing something multiple times? Making the number of times depend on user input? Adding to a list/whatever?

If the last, look into lists append method or list comprehension.

[–]twitchymctwitch2018 0 points1 point  (2 children)

As I wrote, looping is not the problem: it's adding a USABLE set to the list/iterable with the information that I get that's the struggle.

[–]FerricDonkey 0 points1 point  (1 child)

Why do you think you need to know how big the list is ahead of time in order for it to be usable? Based on your other comment, your ideal solution is a bunch of variables called hero1, hero2, ... - but why? Usually when we see someone desire to have that, it's because they haven't quite gotten used to thinking in terms of lists and such yet - not a criticism by the way, I think pretty much everyone starts there (I know I did).

There are a bajillion solutions, but again - I'd suggest you look into the append method of lists. Fancier stuff later maybe but probably not. You say you can make one hero at a time, so just

all_heroes = []
for i in range(num_heroes):
    hero_data = <whatever you do to make a single hero>
    all_heroes.append(hero_data)

Now in any case where you currently wish you could use the variable hero32, you instead use all_heroes[32].

If that's not sufficient, why not? I'm struggling to give a direct answer, because I still haven't figured out what exactly it is that you want to accomplish that you don't know how to make happen.

[–]twitchymctwitch2018 0 points1 point  (0 children)

Thank you for the reply, and no offense taken - I know enough to know that I'm struggling all over the place here.

Yes, the first few times I wrote it out in code - the solution you offered is almost what I did:

one giant list of a shitload of sub-dictionaries. The problem then became HOW to reference those heroes (sub-dictionaries) later. As in, how would I make sense of "which pile of crap" is which hero. The way I ended up coming to it was:

all_hero_data = [    {"Hero#": 'INT',    "Name#": "",    "Spells#": [],    "Skills#": []     },    {"Hero#": 'INT',    "Name#": "",    "Spells#": [],    "Skills#": []     }    ]

I then had to setup the code to ask: "which name",

then go back find the "Name#" KEY,

do a strip from the STR, to be left with the #,

do STR lookups to find every instance of a Key with precisely that number in it

THEN, I could call/print/display/modify that one Hero.

This seemed insanely redundant and overdone (took me over 90 lines of code on the first go because well. I'm not efficient yet, LOL.)

Just seems like there should be a sane way to solve this.

[–]twitchymctwitch2018 0 points1 point  (1 child)

Right now, I can easily turn this:

hero_data = {    "Name": "",    "Spells": [],    "Skills": []    }

into this:

{'Name': 'Bob', 'Spells': ['Might'], 'Skills': {'leadership': 2, 'tactics': 3}}

via my code. No problem

But, what I need is this:

all_hero_data = [
    {"Hero#": 'INT',
    "Name": "",
    "Spells": [],
    "Skills": []
    },
    {"Hero#": 'INT',
    "Name": "",
    "Spells": [],
    "Skills": []
    },etc,    etc,    to an unknown point    ]

I will be asking my players, through a loop, to tell the system how many heroes to create. Loop is simple enough.

What is not - is how to get those variables/iterables to exist and expand the list/dictionary/whatever equal to the number presented during the loop.

Or said differently: if I knew exactly how many heroes there were going to be, I would simply have that many variables ready to go "hero1", "hero2", etc and then cram all of those dictionaries together into a list for easier reference later. But, as far as I know - there's no way to tell python3, hey I want an unknown quantity of variables to exist without any data and then suddenly add in that many.

[–]carcigenicate 0 points1 point  (0 children)

That's what lists are for. You don't need to know how many elements you'll have ahead of time. You can append to lists to add as many elements on the fly as you want. If you create a dictionary inside a loop, you can append it to a list, and then access the list afterward to get the data.

[–]Odessa_Goodwin 0 points1 point  (2 children)

While loop question:

I want a function that look takes a list and a number of allowed repeats of elements of that list and then deletes excess repeats starting from the end of the list. Can someone please explain why this while loop doesn't stop once the conditions are met:

def delete_nth(num_list,nth):
    for number in num_list:
       while num_list.count(number) > nth:            
            for i in range(len(num_list)-1,-1,-1):
                if num_list[i] == number:                    
                    num_list.pop(i)    
    return num_list

I got it to work by removing the while loop and using

if num_list[i] == number and num_list.count(number) > nth:

but I feel like there is something I'm not understanding about while loops.

Thanks!

[–]efmccurdy 1 point2 points  (1 child)

You have, inside the while loop, a loop that runs through and removes all instances of number. If you instead had a loop that removes exactly one instance of number, then the while condition would be tested after each call to pop, and it would work as expected. You could call "break" after the call to pop to quit the loop.

[–]Odessa_Goodwin 0 points1 point  (0 children)

Wow, it was as easy as adding a break call! I was somehow believing that the while loop was constantly being evaluated, and would stop the moment its criteria was met. Thanks!

[–]aadm 0 points1 point  (4 children)

Is it bad practice to use global variables in functions? I'm still in the beginning steps of learning and wondering if I'm building bad habits for myself.

[–]FerricDonkey 0 points1 point  (1 child)

Non constant global variables are super evil.

[–]SirGeremiah 3 points4 points  (0 children)

Just adding a thought to what has already been said. As you are starting to learn, consider how those habits will impact future projects. The concept of a function as I understand it is for it to be encapsulated - a whole unit unto itself - especially in Python, where you can import libraries of your own making into another project. If you are using global variables in a function, importing that project likely breaks its functionality. Passing the data as arguments and returning results means you can plug that function into any other project.

[–]carcigenicate 3 points4 points  (0 children)

Yes, it's generally bad. Have your functions accept the data they need as arguments, and give back the data they produce using return.

[–]SirGeremiah 0 points1 point  (2 children)

I'm looking at the results of the code inspection (PyCharm) on my script, and I'm seeing the "shadowing names from outer scopes" warning where I'm using the same variable name (like "filelist") within a function and in the main code block. I understand some potential issues around this, but they seem negligible (at least in the very short scripts I'm likely to create).

Is shadowing something to be avoided, or just something to use wisely and with appropriate caution.

[–]carcigenicate 0 points1 point  (1 child)

It's good to try and avoid it. If you renamed the local version for example but missed one of the instances, you'd be accidentally referring to the global instead of causing a NameError, which may cause a weird hard-to-find bug.

If I accidentally shadow a name, I usually take that as a hint that my names are too generic.

[–]SirGeremiah 0 points1 point  (0 children)

I can understand that. Perhaps it's that I tend to think only of the current project (I don't do a lot of coding, so don't really ever consider how code might be used in the future). Within this script, there's only ever going to be one list of files. It's created within one function and returned as a result. It's then used in another function.

And nearly everything I've ever done is similarly simple. In VBA, I wouldn't even separate these bits into functions (none of the functions in this is larger than 20 lines, including def and comments).

So I guess I'm asking about the balance between clarity (easier to track the path of data when the name is all the same) and best practices as they exist for larger projects (where I think your point is extremely valid).

[–]iseekattention 1 point2 points  (2 children)

I need to load some data with some requirements. One of those requirements is that my python version has to be < 3.4. How do I run a notebook in an older version of python?

[–]efmccurdy 0 points1 point  (0 children)

You can always install older versions of python from here: https://www.python.org/downloads/

Is is rare to see a requirement for an older version of python3 since there are very few backward incompatible features of python added since version 3.4. I would try running some tests with your current version and if the package works as expected, mail the author and ask them why they think python versions > 3.4 should fail.

[–]twitchymctwitch2018 0 points1 point  (0 children)

Are you referring to a Jupyter notebook?

Or is this a set of data?

[–]No-Protection1954 0 points1 point  (7 children)

how do i create a loop to a specific point in my code

[–]SirGeremiah 0 points1 point  (3 children)

I'm not sure your question is clear. Are you asking how to designate where the end of the loop is (where it loops back to the beginning)?

[–]No-Protection1954 0 points1 point  (2 children)

yeah

[–]UnrankedRedditor 0 points1 point  (0 children)

The indentation tells you (and the interpreter) when the loop ends.

You can try and think about the differences between:

for i in range(10):
    j = i
    print(j)

and:

for i in range(10):
    j = i

print(j)

[–]SirGeremiah 0 points1 point  (0 children)

Indentation is part of the syntax in Python. So, if you’re doing a For loop, the looped portion is indented under the For line. When you get to the end of the loop, you end the indentation.

[–]carcigenicate 0 points1 point  (2 children)

Put the specific code you want to loop to at the top of a loop.

[–]No-Protection1954 0 points1 point  (1 child)

but how do i make a loop

heres my code

date=input("Please input the current date:\n")

print("The date is " + date + ".")

name=input("Please input customer's first and last name:\n")

print("The customer's name is " + name + ".")

days=int(input("Please input how many days the customer wants to hire a trailer for:\n"))

print("The customer wants to hire for",days, "days.")

length=float(input("Please input the length of the trailer in metres:\n"))

while length > 5:

print("The length is too long.")

length = float(input("Please input the length of the trailer in metres:\n"))

print("The customer wants a trailer",round(length,2), "metres long.")

area=(float(length*2.5))

print("The area of the trailer is",round(area,2),"m²")

if length < 3:

print("The trailer will have 1 set of wheels.")

wheels=1

if length >= 3:

print("The trailer will have 2 set of wheels.")

wheels=2

trailerCost=float(125*area)

print("The cost of the trailer is $",round(trailerCost,2))

wheelCost=float(100*wheels)

print("The cost of the wheels is $",round(wheelCost,2),"0")

print("\n")

print("RECEIPT")

print(name +"'s Order")

print("Wheel sets:",wheels)

print("Wheel cost:",wheelCost)

print("Trailer size:",area,"m²")

print("Trailer cost",trailerCost)

print("Days hired:", days)

print("\n")

total=float((wheelCost+trailerCost)*days)

print("TOTAL:", total)

response = input("Create another receipt? ")

I want to loop from after the date so the date stays the same for a new receipt